(function () {
- var current_channel = null, private_manager = null, channel_manager = null;
-
+ var current_channel = null;
+ var private_manager = null;
+ var channel_manager = null;
var bottom_callback;
+ var ws_receive_msg;
+ var ws_schemas = {"http:": "ws:", "https:": "wss:"};
+
function no_bottom_callback() {
bottom_callback = no_bottom_callback;
- };
+ }
bottom_callback = no_bottom_callback;
function xhr(method, url, callback, data) {
return _.xhr(
method,
url,
- callback
- ? function () { callback(JSON.parse(this.responseText)); }
- : null,
- function (msg) { add_msg(null, "xhr_error", msg); },
- function (msg) { add_msg(null, "xhr_abort", msg); },
- data,
+ {
+ "abort": function (msg) {
+ add_msg(null, "xhr_abort", msg);
+ },
+ "error": function (msg) {
+ add_msg(null, "xhr_error", msg);
+ },
+ "load": (
+ callback
+ ? function () {
+ callback(JSON.parse(this.responseText));
+ }
+ : null
+ ),
+ "readystatechange": function () {
+ if (this.readyState === this.DONE) {
+ if (this.readyState === this.DONE) {
+ console.log("DONE url?", this.responseURL, url);
+ } else {
+ console.log("url?", this.responseURL, url);
+ }
+ }
+ }
+ },
+ data
);
}
function get_data_id(element) {
var attr = element.getAttribute("data-id");
- return attr !== null ? Number(attr) : null;
+ return (
+ attr !== null
+ ? Number(attr)
+ : null
+ );
}
function get_current_user_id() {
function set_msg(p, sender, msg) {
_.clear_children(p);
- if (typeof sender === 'number') {
+ if (typeof sender === "number") {
sender = private_manager.items_per_id[sender].username;
}
p.appendChild(_.dcTN(sender));
}
function make_tag_with_data_id(tag_name, data_id) {
- var i, tag = document.createElement(tag_name);
+ var tag = document.createElement(tag_name);
if (data_id !== null) {
tag.setAttribute("data-id", data_id);
}
- for (i = 2; i < arguments.length; i += 1) {
- tag.appendChild(arguments[i]);
- }
return tag;
}
function make_callback_a(callback) {
- var a = document.createElement("a"), i;
+ var a = document.createElement("a");
a.setAttribute("href", "javascript:void(0)");
a.addEventListener("click", callback);
- for (i = 1; i < arguments.length; i += 1) {
- a.appendChild(arguments[i]);
- }
return a;
}
function find_existing_msg(msg_id, callback) {
- var i, messages = _.dgEBCN0("messages");
+ var messages = _.dgEBCN0("messages");
return _.foreach_arr(
messages.children,
function (item) {
current_channel.setup_channel_header();
xhr(
"get",
- this.msg_url + "?" + this.msg_dest_field + "=" + field_value.toString(),
+ (
+ this.msg_url
+ + "?" + this.msg_dest_field
+ + "=" + field_value.toString()
+ ),
function (msgs) {
var messages = _.dgEBCN0("messages");
// add a "load previous" button here
_.foreach_arr(msgs.result, add_msg_callback);
- messages.scrollTop = messages.scrollHeight - messages.clientHeight;
+ messages.scrollTop = (
+ messages.scrollHeight - messages.clientHeight
+ );
}
);
}
function items_reload_callback(item) {
var t = this;
+ var li;
+ var a;
this.items_per_id[item.id] = item;
- _.dgEBCN0(this.items_classname).children[0].appendChild(
- make_tag_with_data_id(
- "li",
- item.id,
- make_callback_a(
- function () { t.set_channel(item.id); },
- _.dcTN(this.item_to_str(item)),
- ),
- ),
+ li = make_tag_with_data_id("li", item.id);
+ a = make_callback_a(
+ function () {
+ t.set_channel(item.id);
+ }
);
+ a.appendChild(this.item_to_tn(item));
+ li.appendChild(a);
+ _.dgEBCN0(this.items_classname).children[0].appendChild(li);
}
function PrivateMessageManager() {
var messages_header = _.dgEBCN0("messages_header");
clear_messages_header();
messages_header.children[0].appendChild(
- _.dcTN(this.item_to_str(this.items_per_id[this.msg_data.recipient_id]))
+ this.item_to_tn(this.items_per_id[this.msg_data.recipient_id])
);
messages_header.style.display = "block";
};
this.items_classname = "users";
this.items_per_id = {};
this.items_reload = function () {
- console.log("a");
_.clear_children(_.dgEBCN0(this.items_classname).children[0]);
_.clear_attributes(this.items_per_id);
- console.log("b");
xhr(
"get",
this.items_url,
function (data) {
- console.log("items_reload callback", data);
_.foreach_arr(
data.result,
function (item) {
+ var p;
items_reload_callback.call(t, item);
if (!item.is_authenticated) {
return;
}
_.clear_children(_.dgEBCN0("user"));
- _.dgEBCN0("user").appendChild(
- make_tag_with_data_id(
- "p", item.id, _.dcTN(item.username)
- ),
- );
+ p = make_tag_with_data_id("p", item.id);
+ p.appendChild(_.dcTN(item.username));
+ _.dgEBCN0("user").appendChild(p);
}
);
update_channel_header.call(t);
- },
+ }
);
- console.log("c");
- }
- this.item_to_str = function (item) {
- return item.username + "\xa0(" + item.email + ")";
+ };
+ this.item_to_tn = function (item) {
+ return _.dcTN(item.username + "\u00a0(" + item.email + ")");
};
this.match_channel = function (data) {
- var user_id, recipient_id;
+ var other_id;
+ var user_id;
if (data.table !== this.msg_table) {
return false;
}
user_id = get_current_user_id();
other_id = current_channel.msg_data.recipient_id;
return (
- data.obj.sender_id === user_id && data.obj.recipient_id === other_id
+ data.obj.sender_id === user_id
+ && data.obj.recipient_id === other_id
) || (
- data.obj.sender_id === other_id && data.obj.recipient_id === user_id
+ data.obj.sender_id === other_id
+ && data.obj.recipient_id === user_id
);
};
this.items_reload();
var btn = document.createElement("button");
clear_messages_header();
messages_header.children[0].appendChild(
- _.dcTN(this.item_to_str(this.items_per_id[this.msg_data.channel_id]))
+ this.item_to_tn(this.items_per_id[this.msg_data.channel_id])
);
_.foreach_arr(
this.items_per_id[this.msg_data.channel_id].users,
function (user_id) {
var item = private_manager.items_per_id[user_id];
- messages_header.children[1].appendChild(
- make_tag_with_data_id(
- "li",
- item.id,
- make_callback_a(
- function () { private_manager.set_channel(item.id); },
- _.dcTN(private_manager.item_to_str(item)),
- ),
- ),
+ var li = make_tag_with_data_id("li", item.id);
+ var a = make_callback_a(
+ function () {
+ private_manager.set_channel(item.id);
+ }
);
- },
+ a.appendChild(private_manager.item_to_tn(item));
+ li.appendChild(a);
+ messages_header.children[1].appendChild(li);
+ }
);
btn.appendChild(_.dcTN("Users"));
messages_header.addEventListener("click", function () {
messages_header.children[1].style.display = "none";
});
btn.addEventListener("click", function (event) {
+ var offset;
event = event || window.event;
if (messages_header.children[1].style.display === "none") {
messages_header.children[1].style.display = "block";
- messages_header.children[1].style.top = (btn.offsetTop + btn.offsetHeight).toString() + "px";
+ offset = btn.offsetTop + btn.offsetHeight;
+ messages_header.children[1].style.top = (
+ offset.toString() + "px"
+ );
} else {
messages_header.children[1].style.display = "none";
}
function (data) {
_.foreach_arr(data.result, items_reload_callback.bind(t));
update_channel_header.call(t);
- },
+ }
);
- }
- this.item_to_str = function (item) { return item.name; };
+ };
+ this.item_to_tn = function (item) {
+ return _.dcTN(item.name);
+ };
this.match_channel = function (data) {
- var obj;
if (data.table !== this.msg_table) {
return false;
}
bottom_callback = function () {
element.scrollTop = element.scrollHeight - element.clientHeight;
no_bottom_callback();
- }
+ };
} else {
no_bottom_callback();
}
}
- var ws_receive_msg = {
+ ws_receive_msg = {
+ DELETE: function (data) {
+ find_existing_msg(
+ data.obj.id,
+ function (tag) {
+ tag.parentElement.removeChild(tag);
+ }
+ );
+ },
INSERT: function (data) {
stick_to_bottom(_.dgEBCN0("messages"));
xhr(
}
);
},
+ TRUNCATE: function () {
+ _.clear_children(_.dgEBCN0("messages"));
+ },
UPDATE: function (data) {
var messages = _.dgEBCN0("messages");
stick_to_bottom(messages);
stick_to_bottom(messages);
xhr(
"get",
- current_channel.msg_url + get_data_id(tag).toString() + "/",
+ (
+ current_channel.msg_url
+ + get_data_id(tag).toString()
+ + "/"
+ ),
function (msg) {
- set_msg(tag, msg[current_channel.msg_user_field], msg.text);
+ set_msg(
+ tag,
+ msg[current_channel.msg_user_field],
+ msg.text
+ );
bottom_callback();
}
);
- },
- );
- },
- DELETE: function (data) {
- find_existing_msg(
- data.obj.id, function (tag) { tag.parentElement.removeChild(tag); }
+ }
);
- },
- TRUNCATE: function (data) {
- _.clear_children(_.dgEBCN0("messages"));
- },
+ }
};
function ws_receive(msg) {
var data = JSON.parse(msg.data);
- // here we could add indication for the pm or channel that is being modified
- if (data.table === "chat_channel" || data.table === "chat_channeluser") {
+ if (data.hasOwnProperty("Location")) {
+ location.href = data.Location;
+ }
+ // here we could add indication for the pm or channel being modified
+ if (
+ data.table === "chat_channel" || data.table === "chat_channeluser"
+ ) {
channel_manager.items_reload();
} else if (data.table === "chat_user") {
private_manager.items_reload();
}
function send_msg() {
- var ta = _.dgEBCN0("messages_footer").children[0], data, name;
- data = {"text": ta.value};
+ var data = {"text": ta.value};
+ var ta = _.dgEBCN0("messages_footer").children[0];
_.foreach_obj(
- current_channel.msg_data, function (name, value) { data[name] = value; }
+ current_channel.msg_data,
+ function (name, value) {
+ data[name] = value;
+ }
);
if (current_channel) {
xhr("post", current_channel.msg_url, null, JSON.stringify(data));
event = event || window.event;
keycode = event.code || event.key;
if (keycode === "Enter" || keycode === "NumpadEnter") {
- // todo: make it possible to add newlines using ctrl+enter
+ // nth: make it possible to add newlines using ctrl+enter
send_msg();
event.preventDefault();
event.stopPropagation();
window.addEventListener(
"load",
function (event) {
- var ws, schema, messages_footer;
+ var messages_footer;
+ var ws;
messages_footer = _.dgEBCN0("messages_footer");
set_channel.call(window);
event = event || window.event;
}
private_manager = new PrivateMessageManager();
channel_manager = new ChannelManager();
- schema = {"http:": "ws:", "https:": "wss:"}[window.location.protocol];
- ws = new WebSocket(schema + "//" + window.location.host + "/");
+ ws = new WebSocket(
+ ws_schemas[window.location.protocol]
+ + "//"
+ + window.location.host
+ + "/"
+ );
ws.addEventListener("message", ws_receive);
- messages_footer.children[0].addEventListener("keydown", input_onkeydown);
+ messages_footer.children[0].addEventListener(
+ "keydown",
+ input_onkeydown
+ );
messages_footer.children[0].value = "";
messages_footer.children[1].addEventListener("click", send_msg);
}
(function () {
- function foreach_arr(arr, callback) {
+ function foreach_arr(arr, callback, start) {
var i;
- for (i = arguments.length === 3 ? arguments[2] : 0; i < arr.length; i += 1) {
- if (callback(arr[i]) === false) {
+ for (i = start || 0; i < arr.length; i += 1) {
+ if (callback(arr[i]) === true) {
return true;
}
}
}
function foreach_obj(obj, callback) {
- var name;
- for (name in obj) {
- if (obj.hasOwnProperty(name) && callback(name, obj[name]) === true) {
- return true;
+ foreach_arr(
+ Object.keys(obj),
+ function (key) {
+ return callback(key, obj[key]);
}
- }
+ );
return false;
}
}
function clear_attributes(obj) {
- foreach_obj(obj, function (name) { delete obj[name]; })
+ foreach_obj(
+ obj,
+ function (name) {
+ delete obj[name];
+ }
+ );
}
- function xhr(method, url, callback, error_callback, abort_callback, data) {
- var xhr = new XMLHttpRequest();
- if (!error_callback) {
- error_callback = function (msg) { console.log("xhr_error", msg) };
+ function xhr(method, url, callbacks, data) {
+ var request = new XMLHttpRequest();
+ if (!callbacks.hasOwnProperty("error")) {
+ request.addEventListener(
+ "error",
+ function (msg) {
+ console.log("xhr_error", msg);
+ }
+ );
}
- if (!abort_callback) {
- abort_callback = function (msg) { console.log("xhr_abort", msg) };
+ if (!callbacks.hasOwnProperty("abort")) {
+ request.addEventListener(
+ "abort",
+ function (msg) {
+ console.log("xhr_abort", msg);
+ }
+ );
}
- xhr.addEventListener("error", error_callback);
- xhr.addEventListener("abort", abort_callback);
- if (callback) {
- xhr.addEventListener("load", callback);
- }
- xhr.open(method, url);
+ foreach_arr(
+ callbacks,
+ function (event_name, callback) {
+ request.addEventListener(event_name, callback);
+ }
+ );
+ request.open(method, url);
if (method.toLowerCase() === "put" || method.toLowerCase() === "post") {
- xhr.send(data);
+ request.send(data);
} else {
- xhr.send();
+ request.send();
}
- return xhr;
+ return request;
}
- window._ = {
- "dcTN": function (t) { return document.createTextNode(t); },
- "dgEBCN0": function (cn) { return document.getElementsByClassName(cn)[0]; },
- "foreach_arr": foreach_arr,
- "foreach_obj": foreach_obj,
- "clear_children": clear_children,
+ window._ = { //jslint-ignore-line
"clear_after": clear_after,
"clear_attributes": clear_attributes,
- "xhr": xhr,
+ "clear_children": clear_children,
+ "dcTN": function (t) {
+ return document.createTextNode(t);
+ },
+ "dgEBCN0": function (cn) {
+ return document.getElementsByClassName(cn)[0];
+ },
+ "foreach_arr": foreach_arr,
+ "foreach_obj": foreach_obj,
+ "xhr": xhr
};
}());
--- /dev/null
+#!/usr/bin/env python
+
+# Copyright (C) 2011 Alejandro Blanco <ablanco@yaco.es>
+# Copyright (C) 2024 mar77i <mar77i@protonmail.ch>
+
+import json
+from argparse import ArgumentParser
+from contextlib import contextmanager
+from pathlib import Path
+from subprocess import call
+from tempfile import NamedTemporaryFile
+from urllib.request import urlopen
+
+node_script = r"""
+var jslint = require({jslint}).default.jslint;
+var read = require("fs").readFileSync;
+var result;
+
+function print_warning(warning) {
+ if (warning === null) {
+ return;
+ }
+ if (warning.evidence !== undefined) {
+ console.log(warning.evidence);
+ }
+ console.log(warning.formatted_message);
+}
+
+console.log("Analyzing file " + process.argv[2]);
+result = jslint(read(process.argv[2], "utf8"), {jsoptions}, {jsglobals});
+result.warnings.forEach(print_warning);
+if (result.warnings.length > 0) {
+ console.error(result.warnings.length + " Error(s) found.");
+ process.exit(1);
+} else {
+ console.log("No errors found.");
+ process.exit(0);
+}
+"""
+
+
+def try_json_loads(value):
+ try:
+ return json.loads(value)
+ except json.JSONDecodeError:
+ return value
+
+
+@contextmanager
+def get_lint(jslint, jsoptions, jsglobals):
+ jsoptions_dict = {
+ key: try_json_loads(value)
+ for key, value in (item.split(":", 1) for item in jsoptions)
+ }
+ tmp_dir = Path("/dev/shm")
+ if not tmp_dir.exists():
+ tmp_dir = None
+ with NamedTemporaryFile("w", dir=tmp_dir, delete_on_close=False) as lint:
+ lint.write(
+ node_script.replace("{jslint}", json.dumps(str(jslint.absolute())))
+ .replace("{jsoptions}", json.dumps(jsoptions_dict))
+ .replace("{jsglobals}", json.dumps(jsglobals))
+ )
+ lint.close()
+ yield lint.name
+
+
+def main():
+ parser = ArgumentParser("Usage: %(prog)s")
+ parser.add_argument(
+ "-u",
+ "--upgrade",
+ dest="upgrade",
+ help="Upgrade JSLint",
+ action="store_true",
+ default=False,
+ )
+ parser.add_argument(
+ "-j",
+ "--jslint",
+ dest="jslint",
+ help="JSLint location",
+ type=Path,
+ default=Path(__file__).parent / "jslint.js",
+ )
+ parser.add_argument(
+ "-o",
+ "--option",
+ dest="jsoptions",
+ help="JSLint options",
+ default=["maxerr: 100"],
+ action="append",
+ )
+ parser.add_argument(
+ "-g",
+ "--global",
+ dest="jsglobals",
+ help="JSLint globals",
+ default=[],
+ action="append",
+ )
+ parser.add_argument(
+ "-n", "--node", dest="node", help="Node location", default="node"
+ )
+ parser.add_argument("files", nargs="+")
+ args = parser.parse_args()
+ if not args.jslint.exists() or args.upgrade:
+ with urlopen(
+ (
+ "https://raw.githubusercontent.com/jslint-org/"
+ "jslint/refs/heads/beta/jslint.mjs"
+ )
+ ) as response, open(args.jslint, "wb") as fh:
+ fh.write(response.read())
+ returncode = 0
+ with get_lint(args.jslint, args.jsoptions, args.jsglobals) as lint_name:
+ for file in args.files:
+ ret = call([args.node, lint_name, file])
+ if ret:
+ returncode = ret
+ exit(returncode)
+
+
+if __name__ == "__main__":
+ main()