1
0
mirror of https://github.com/lxsang/antd-web-apps synced 2024-12-27 09:58:20 +01:00
antd-web-apps/talk/assets/quicktalk.js
2020-12-09 12:13:03 +01:00

277 lines
11 KiB
JavaScript

class QuickTalk {
constructor(opt) {
this.options = opt;
if (typeof this.options.target === "string") {
this.options.target = document.getElementById(this.options.target);
}
if (typeof this.options.page && typeof this.options.page === "string") {
this.options.page = document.getElementById(this.options.page);
}
this.preview_on = false;
this.instant_compose = undefined;
let editor = document.createElement("div");
let compose_button = document.createElement("button");
compose_button.setAttribute("class", "quick-talk-compose-button");
compose_button.textContent = "Write a comment";
this.options.target.appendChild(compose_button);
this.options.target.appendChild(editor);
let container = this.load_thread(this.options.target);
compose_button.addEventListener("click", (event) => {
if (this.instant_compose) {
this.instant_compose.parentNode.removeChild(this.instant_compose);
}
this.instant_compose = this.compose(editor, 0, true, (data) => {
this.show_comment(container, data, true).scrollIntoView();
});
});
}
request(uri, data, callback) {
let xhttp = new XMLHttpRequest();
xhttp.open("POST", uri, true);
xhttp.setRequestHeader("Content-type", "application/json");
xhttp.onreadystatechange = () => {
if (xhttp.readyState == 4) {
if (xhttp.status == 200) {
if (callback) {
callback(JSON.parse(xhttp.responseText));
}
}
else {
this.error(xhttp.statusText);
}
}
};
if (data) {
xhttp.send(JSON.stringify(data));
}
else {
xhttp.send();
}
}
set_status(type, msg) {
if (this.status_el) {
this.status_el.innerHTML = type + ": " + msg;
}
else {
console.log(type + ": " + msg);
}
}
clear_status() {
this.status_el.innerHTML = "";
}
info(msg) {
this.set_status("INFO", msg);
}
error(obj) {
console.log(obj);
this.set_status("ERROR", obj.toString());
}
compose(at, cid, auto_hide, callback) {
let preview = document.createElement("div");
preview.setAttribute("class", "quick-talk-preview");
preview.style.display = "none";
let container = document.createElement("div");
container.setAttribute("class", "quick-talk-compose");
let name = document.createElement("input");
name.value = "Name";
name.addEventListener("focus", (event) => {
if (name.value == "Name") {
name.value = "";
}
});
name.addEventListener("blur", (event) => {
if (name.value.trim() == "") {
name.value = "Name";
}
});
let email = document.createElement("input");
email.value = "Email";
email.addEventListener("focus", (event) => {
if (email.value == "Email") {
email.value = "";
}
});
email.addEventListener("blur", (event) => {
if (email.value.trim() == "") {
email.value = "Email";
}
});
let ta = document.createElement("textarea");
ta.onkeydown = (e) => {
if (e.keyCode === 9) {
// tab was pressed
// get caret position/selection
var val = ta.value, start = ta.selectionStart, end = ta.selectionEnd;
// set textarea value to: text before caret + tab + text after caret
ta.value =
val.substring(0, start) + " " + val.substring(end);
// put caret at right position again
ta.selectionStart = ta.selectionEnd = start + 4;
// prevent the focus lose
return false;
}
};
let footer = document.createElement("div");
footer.setAttribute("class", "quick-talk-compose-footer");
this.status_el = document.createElement("div");
let bt_preview = document.createElement("button");
bt_preview.textContent = "Preview";
bt_preview.addEventListener("click", (event) => {
let md = { data: ta.value };
if (!this.preview_on && ta.value.trim() != "") {
this.request(this.options.api_uri + "/preview", md, (ret) => {
if (ret.result) {
ta.style.display = "none";
preview.innerHTML = ret.result;
preview.style.display = "block";
bt_preview.textContent = "Edit";
this.preview_on = !this.preview_on;
}
else {
this.error(ret.error);
}
});
}
else {
ta.style.display = "block";
preview.style.display = "none";
bt_preview.textContent = "Preview";
this.preview_on = !this.preview_on;
}
});
let bt_submit = document.createElement("button");
bt_submit.textContent = "Send";
bt_submit.addEventListener("click", (event) => {
this.clear_status();
if (name.value.trim() == "" ||
name.value.trim() == "Name" ||
email.value.trim() == "" ||
email.value.trim() == "Email" ||
ta.value.trim() == "") {
this.info("Please enter all the fields");
return;
}
// check for email
let re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if (!re.test(String(email.value).toLowerCase()))
return this.info("Email is not correct");
// send the post request
let data = {
page: {
uri: this.options.uri,
},
comment: {
name: name.value,
email: email.value,
rid: cid,
content: ta.value,
},
};
if (this.options.author) {
data.author =
this.options.author.first + "@" + this.options.author.last;
}
this.request(this.options.api_uri + "/post", data, (ret) => {
if (ret.result) {
// TODO: more check goes here
name.value = "Name";
email.value = "Email";
ta.value = "";
if (auto_hide) {
at.removeChild(container);
this.instant_compose = undefined;
}
if (callback) {
callback(ret.result);
}
}
else {
this.error(ret.error);
}
});
});
footer.appendChild(this.status_el);
footer.appendChild(bt_preview);
footer.appendChild(bt_submit);
container.appendChild(name);
container.appendChild(email);
container.appendChild(ta);
container.appendChild(preview);
container.appendChild(footer);
at.appendChild(container);
if (this.options.page) {
this.options.page.scrollTop = container.offsetTop - this.options.page.offsetTop;
}
//container.scrollIntoView();
return container;
}
load_thread(at) {
let container = document.createElement("div");
container.setAttribute("class", "quick-talk-comment-thread");
at.appendChild(container);
this.request(this.options.api_uri, { page: this.options.uri }, (ret) => {
if (ret.result) {
ret.result.forEach((comment) => {
this.show_comment(container, comment, true);
});
}
else {
this.error(ret.error);
}
if (this.options.onload) {
this.options.onload();
}
});
return container;
}
show_comment(at, comment, show_footer) {
let container = document.createElement("div");
container.setAttribute("class", "quick-talk-comment");
let header = document.createElement("div");
header.setAttribute("class", "quick-talk-comment-header");
let username = document.createElement("span");
username.setAttribute("class", "quick-talk-comment-user");
let time = document.createElement("span");
time.setAttribute("class", "quick-talk-comment-time");
let content = document.createElement("div");
content.setAttribute("class", "quick-talk-comment-content");
username.innerHTML = comment.name;
let date = new Date(parseInt(comment.time) * 1000);
time.innerHTML = `on ${date.getDate()}/${date.getMonth()}/${date.getFullYear()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}, wrote:`;
content.innerHTML = comment.content;
header.appendChild(username);
header.appendChild(time);
container.appendChild(header);
container.appendChild(content);
let sub_comments = document.createElement("div");
sub_comments.setAttribute("class", "quick-talk-sub-comment");
if (comment.children && comment.children.length > 0) {
comment.children.forEach((cmt) => {
this.show_comment(sub_comments, cmt, false);
});
}
container.appendChild(sub_comments);
if (show_footer) {
let footer = document.createElement("div");
footer.setAttribute("class", "quick-talk-comment-footer");
let span = document.createElement("span");
span.innerText = "Reply";
footer.appendChild(span);
let editor = document.createElement("div");
footer.appendChild(editor);
span.addEventListener("click", (event) => {
if (this.instant_compose) {
this.instant_compose.parentNode.removeChild(this.instant_compose);
}
this.instant_compose = this.compose(editor, parseInt(comment.id), true, (data) => {
this.show_comment(sub_comments, data, false).scrollIntoView();
});
});
container.appendChild(footer);
}
at.appendChild(container);
return container;
}
}