Skip to content
Snippets Groups Projects
Commit bc94d885 authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

Started work on rewrite

parent bd034a29
No related branches found
No related tags found
No related merge requests found
Showing
with 511 additions and 4 deletions
File moved
File moved
This diff is collapsed.
const senderColorHandler = new SenderColorHandler();
const mircColorHandler = new MircColorHandler();
class App {
constructor() {
this.navigation = new Navigation();
this.urlBar = new UrlBar();
this.buffers = [];
this.loadingQuery = 0;
this.render();
this.urlBar.addEventListener("search", (query) => this.search(query));
this.navigation.addEventListener("search", (query) => this.search(query));
this.urlBar.init();
}
render() {
const wrapper = document.createElement("div");
wrapper.appendChild(this.navigation.elem);
const results = document.createElement("div");
results.classList.add("results");
wrapper.appendChild(results);
this.elem = wrapper;
this.resultContainer = results;
this.buffers.forEach((buffer) => this.insert(buffer));
}
search(query) {
this.clear();
this.loadingQuery++;
const queryId = this.loadingQuery;
load("web/search/", {query: query}).then((result) => {
if (this.loadingQuery != queryId)
return;
this.buffers = result.map((buffer) => {
return new Buffer(buffer.bufferid, buffer.buffername, buffer.networkname, buffer.messages.map((msg) => {
return new Context(new MessagePreview(msg.messageid, msg.time, msg.sender, msg.message, msg.preview));
}));
});
this.buffers.forEach((buffer) => this.insert(buffer));
});
this.navigation.historyView.add(new HistoryElement(query));
this.navigation.input.value = query;
this.urlBar.set(query);
}
clear() {
while (this.buffers.length) {
const buffer = this.buffers.pop();
this.resultContainer.removeChild(buffer.elem);
}
}
clearAll() {
this.clear();
this.navigation.historyView.clear();
this.urlBar.clear();
}
insert(buffer) {
this.resultContainer.appendChild(buffer.elem);
}
}
const app = new App();
document.body.insertBefore(app.elem, document.body.firstChild);
\ No newline at end of file
class Buffer {
constructor(id, name, network, contextList = []) {
this.id = id;
this.name = name;
this.network = network;
this.contextList = contextList;
this.render();
}
render() {
const buffer = document.createElement("div");
buffer.classList.add("buffer");
const title = document.createElement("h2");
title.classList.add("title");
const titleValue = document.createTextNode(this.network + " - " + this.name);
title.appendChild(titleValue);
buffer.appendChild(title);
const contextWrap = document.createElement("div");
contextWrap.classList.add("container");
const loadMoreBtn = new LoadMore(translation.results.show_more);
loadMoreBtn.addEventListener("click", this.loadMore);
contextWrap.appendChild(loadMoreBtn.elem);
buffer.appendChild(contextWrap);
this.elem = buffer;
this.insertContainer = contextWrap;
this.loadMoreBtn = loadMoreBtn;
this.contextList.forEach((context) => this.insert(context));
}
loadMore() {
/* load data */
}
insert(context) {
this.insertContainer.insertBefore(context.elem, this.loadMoreBtn.elem);
}
}
\ No newline at end of file
class Context {
constructor(preview, beforeList=[], afterList=[]) {
this.preview = preview;
this.beforeList = beforeList;
this.afterList = afterList;
this.render();
}
render() {
const context = document.createElement("div");
context.classList.add("context");
const containerBefore = document.createElement("div");
containerBefore.classList.add("container");
containerBefore.classList.add("before");
const loadBeforeBtn = new LoadMore(translation.context.load_earlier);
loadBeforeBtn.addEventListener("click", this.loadBefore);
containerBefore.appendChild(loadBeforeBtn.elem);
context.appendChild(containerBefore);
context.appendChild(this.preview.elem);
const containerAfter = document.createElement("div");
containerAfter.classList.add("container");
containerAfter.classList.add("after");
const loadAfterBtn = new LoadMore(translation.context.load_later);
loadAfterBtn.addEventListener("click", this.loadAfter);
containerAfter.appendChild(loadAfterBtn.elem);
context.appendChild(containerAfter);
this.elem = context;
this.containerBefore = containerBefore;
this.loadBeforeBtn = loadBeforeBtn;
this.containerAfter = containerAfter;
this.loadAfterBtn = loadAfterBtn;
this.beforeList.forEach(this.insertBefore);
this.afterList.forEach(this.insertAfter);
}
loadBefore() {
/* load data */
}
insertBefore(message) {
this.containerBefore.insertBefore(message.elem, this.insertBeforeTarget);
this.insertBeforeTarget = message.elem;
}
loadAfter() {
/* load data */
}
insertAfter(message) {
this.containerAfter.insertBefore(message.elem, this.insertAfterTarget);
}
}
\ No newline at end of file
const HISTORY_KEY = "history";
const HISTORY_MAX_LENGTH = 4;
class HistoryView {
constructor() {
this.index = -1;
this.elements = this.load().map(function (query) {
return new HistoryElement(query);
});
this.render();
}
render() {
const historyView = document.createElement("div");
historyView.classList.add("history");
const list = document.createElement("ul");
const noHistory = new NoHistoryElement();
list.appendChild(noHistory.elem);
historyView.appendChild(list);
this.elem = historyView;
this.list = list;
this.noHistory = noHistory;
this.elements.forEach((elem) => this.insert(elem));
}
insert(item) {
this.list.insertBefore(item.elem, this.list.firstChild);
if (this.noHistory.elem.parentNode === this.list)
this.list.removeChild(this.noHistory.elem);
}
add(item) {
const idx = this.elements.map((item) => item.query).indexOf(item.query);
if (idx !== -1) {
this.list.removeChild(this.elements[idx].elem);
this.elements.splice(idx, 1);
}
this.elements.push(item);
this.insert(item);
this.truncate();
this.store();
}
clear() {
while (this.elements.length) {
this.list.removeChild(this.elements.pop().elem);
}
this.store();
this.list.appendChild(this.noHistory.elem);
}
load() {
const loaded = localStorage[HISTORY_KEY];
return JSON.parse(loaded===undefined ? "[]" : loaded);
}
store() {
localStorage[HISTORY_KEY] = JSON.stringify(this.elements.map((item) => item.query));
}
navigateBefore() {
this.index++;
this.index %= this.elements.length;
}
navigateLater() {
this.index--;
if (this.index < 0)
this.index = -1;
else
this.index %= this.elements.length;
}
truncate() {
while (this.elements.length > HISTORY_MAX_LENGTH)
this.list.removeChild(this.elements.shift().elem);
}
}
\ No newline at end of file
class HistoryElement {
constructor(query) {
this.query = query;
this.render();
}
render() {
const wrapper = document.createElement("li");
const icon = document.createElement("span");
icon.classList.add("icon");
const iconValue = document.createTextNode("history");
icon.appendChild(iconValue);
wrapper.appendChild(icon);
const queryValue = document.createTextNode(this.query);
wrapper.appendChild(queryValue);
this.elem = wrapper;
}
}
\ No newline at end of file
class LoadMore extends Component {
constructor(text) {
super();
const button = document.createElement("div");
button.classList.add("inline-button");
button.addEventListener("click", (event) => this.sendEvent("click", [event]));
const buttonValue = document.createTextNode(text);
button.appendChild(buttonValue);
this.elem = button;
}
}
\ No newline at end of file
class Message {
constructor(id, time, sender, content) {
this.id = id;
this.time = time;
this.sender = sender;
this.content = content;
this.render();
}
render() {
const message = document.createElement("div");
message.classList.add("message");
const time = document.createElement("time");
const timeValue = document.createTextNode(new Date(message.time.replace(" ", "T") + "Z").toLocaleString());
time.appendChild(timeValue);
message.appendChild(time);
const container = document.createElement("div");
container.classList.add("container");
const sender = document.createElement("div");
sender.classList.add("sender");
sender.style.color = senderColorHandler.nickToColor(this.getNick());
const senderValue = document.createTextNode(this.getNick());
sender.appendChild(senderValue);
container.appendChild(sender);
const content = document.createElement("div");
content.classList.add("content");
mircColorHandler.render(this.content).forEach((elem) => content.appendChild(elem));
container.appendChild(content);
message.appendChild(container);
this.elem = message;
}
getNick() {
return this.sender.split("!")[0];
}
getIdent() {
return this.sender.split("@")[0].split("!")[1];
}
getHost() {
return this.sender.split("@")[1];
}
}
\ No newline at end of file
class MessagePreview {
constructor(id, time, sender, content, preview) {
this.id = id;
this.time = time;
this.sender = sender;
this.content = content;
this.preview = preview;
this.render();
}
render() {
const message = document.createElement("div");
message.classList.add("message");
message.classList.add("preview");
const time = document.createElement("time");
const timeValue = document.createTextNode(new Date(this.time.replace(" ", "T") + "Z").toLocaleString());
time.appendChild(timeValue);
message.appendChild(time);
const container = document.createElement("div");
container.classList.add("container");
const sender = document.createElement("div");
sender.classList.add("sender");
sender.style.color = senderColorHandler.nickToColor(this.getNick());
const senderValue = document.createTextNode(this.getNick());
sender.appendChild(senderValue);
container.appendChild(sender);
const content = document.createElement("div");
content.classList.add("content");
mircColorHandler.render(this.content).forEach((elem) => content.appendChild(elem));
container.appendChild(content);
const preview = document.createElement("div");
preview.classList.add("preview");
mircColorHandler.highlight(this.preview).forEach((elem) => preview.appendChild(elem));
container.appendChild(preview);
message.appendChild(container);
this.elem = message;
}
getNick() {
return this.sender.split("!")[0];
}
getIdent() {
return this.sender.split("@")[0].split("!")[1];
}
getHost() {
return this.sender.split("@")[1];
}
}
\ No newline at end of file
const keyMapping = {
13: "Enter",
27: "Escape",
38: "ArrowUp",
40: "ArrowDown"
};
class Navigation extends Component {
constructor() {
super();
this.render();
}
render() {
const nav = document.createElement("div");
nav.classList.add("nav");
const wrapper = document.createElement("div");
wrapper.classList.add("container");
const searchBar = document.createElement("div");
searchBar.classList.add("searchBar");
const searchIcon = document.createElement("div");
searchIcon.classList.add("icon");
const searchIconValue = document.createTextNode("search");
searchIcon.appendChild(searchIconValue);
searchBar.appendChild(searchIcon);
const input = document.createElement("input");
input.classList.add("search");
input.placeholder = translation.search;
input.type = "text";
input.autocomplete = "off";
input.addEventListener("focus", () => this.elem.classList.add("focus"));
input.addEventListener("blur", () => this.elem.classList.remove("focus"));
input.addEventListener("keydown", (e) => {
switch (e.key || keyMapping[e.keyCode]) {
case "ArrowUp": {
this.historyView.navigateLater();
} break;
case "ArrowDown": {
this.historyView.navigateBefore();
} break;
case "Enter": {
this.sendEvent("search", [this.input.value]);
this.input.blur();
} break;
case "Escape": {
this.input.blur();
} break;
}
});
searchBar.appendChild(input);
wrapper.appendChild(searchBar);
nav.appendChild(wrapper);
const actions = document.createElement("div");
actions.classList.add("actions");
const logout = document.createElement("a");
logout.title = translation.logout;
logout.href = "login.php?action=logout";
logout.classList.add("icon");
const logoutValue = document.createTextNode("exit_to_app");
logout.appendChild(logoutValue);
actions.appendChild(logout);
nav.appendChild(actions);
const historyView = new HistoryView();
nav.appendChild(historyView.elem);
this.elem = nav;
this.input = input;
this.historyView = historyView;
}
}
\ No newline at end of file
class NoHistoryElement {
constructor() {
this.render();
}
render() {
const wrapper = document.createElement("p");
const value = document.createTextNode(translation.history.error_unavailable);
wrapper.appendChild(value);
this.elem = wrapper;
}
}
\ No newline at end of file
class UrlBar extends Component {
constructor() {
super();
window.addEventListener("hashchange", (e) => {
this.sendEvent("search", [this.get()]);
});
}
set(value) {
window.location.hash = value;
}
init() {
this.sendEvent("search", [this.get()]);
}
get() {
return decodeURIComponent(window.location.hash.substr(1));
}
clear() {
this.set("");
}
}
\ No newline at end of file
class Component {
constructor() {
this.eventListeners = {};
}
addEventListener(type, handler) {
this.getListeners(type).push(handler);
}
removeEventListener(type, handler) {
const listeners = this.getListeners(type);
listeners.splice(listeners.indexOf(handler), 1);
}
getListeners(type) {
if (!this.eventListeners[type])
this.eventListeners[type] = [];
return this.eventListeners[type];
}
sendEvent(type, argv) {
this.getListeners(type).forEach((listener) => {
listener.apply(null, argv);
})
}
}
\ No newline at end of file
class HighlightHandler {
render(text) {
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment