diff --git a/frontends/etiquette_flask/static/common.js b/frontends/etiquette_flask/static/common.js
index 4674bf5..db2ffc7 100644
--- a/frontends/etiquette_flask/static/common.js
+++ b/frontends/etiquette_flask/static/common.js
@@ -1,225 +1,3 @@
-var PARAGRAPH_TYPES = new Set(["P", "PRE"]);
-
-function Editor(elements, on_open, on_save, on_cancel)
-{
- /*
- This class wraps around display elements like headers and paragraphs, and
- creates inputs / textareas to edit them with.
-
- The placeholder text for the edit elements comes from the
- data-editor-placeholder attribute of the display elements if available.
-
- The on_open, on_save and on_cancel callbacks will receive two arguments:
- 1. This editor object.
- 2. the edit elements as either:
- If the display elements ALL have data-editor-id attributes,
- then a dictionary of {data-editor-id: edit_element, ...}.
- Otherwise, an array of [edit_element, ...] in their original order.
-
- When your callbacks are used, the default `open`, `save`, `cancel`
- methods are not called automatically. You should call them from within
- your function.
- */
- this.cancel = function()
- {
- this.close();
- };
-
- this.close = function()
- {
- for (var index = 0; index < this.display_elements.length; index += 1)
- {
- this.display_elements[index].classList.remove("hidden");
- this.edit_elements[index].classList.add("hidden");
- }
- this.open_button.classList.remove("hidden")
- this.save_button.classList.add("hidden");
- this.cancel_button.classList.add("hidden");
- };
-
- this.hide_spinner = function()
- {
- this.spinner.classList.add("hidden");
- };
-
- this.open = function()
- {
- for (var index = 0; index < this.display_elements.length; index += 1)
- {
- var display_element = this.display_elements[index];
- var edit_element = this.edit_elements[index];
- display_element.classList.add("hidden");
- edit_element.classList.remove("hidden");
-
- var empty_text = display_element.dataset.editorEmptyText;
- if (empty_text !== undefined && display_element.innerText == empty_text)
- {
- edit_element.value = "";
- }
- else
- {
- edit_element.value = display_element.innerText;
- }
- }
- this.open_button.classList.add("hidden")
- this.save_button.classList.remove("hidden");
- this.cancel_button.classList.remove("hidden");
- };
-
- this.save = function()
- {
- for (var index = 0; index < this.display_elements.length; index += 1)
- {
- var display_element = this.display_elements[index];
- var edit_element = this.edit_elements[index];
-
- if (display_element.dataset.editorEmptyText !== undefined && edit_element.value == "")
- {
- display_element.innerText = display_element.dataset.editorEmptyText;
- }
- else
- {
- display_element.innerText = edit_element.value;
- }
- }
-
- this.close();
- };
-
- this.show_spinner = function()
- {
- this.spinner.classList.remove("hidden");
- };
-
- this.display_elements = [];
- this.edit_elements = [];
-
- this.can_use_element_map = true;
- this.display_element_map = {};
- this.edit_element_map = {};
-
- this.misc_data = {};
-
- for (var index = 0; index < elements.length; index += 1)
- {
- var display_element = elements[index];
- var edit_element;
- if (PARAGRAPH_TYPES.has(display_element.tagName))
- {
- edit_element = document.createElement("textarea");
- edit_element.rows = 6;
- }
- else
- {
- edit_element = document.createElement("input");
- edit_element.type = "text";
- }
- edit_element.classList.add("editor_input");
- edit_element.classList.add("hidden");
-
- if (display_element.dataset.editorPlaceholder !== undefined)
- {
- edit_element.placeholder = display_element.dataset.editorPlaceholder;
- }
-
- if (this.can_use_element_map)
- {
- if (display_element.dataset.editorId !== undefined)
- {
- this.display_element_map[display_element.dataset.editorId] = display_element;
- this.edit_element_map[display_element.dataset.editorId] = edit_element;
- }
- else
- {
- this.can_use_element_map = false;
- this.edit_element_map = null;
- this.display_element_map = null;
- }
- }
-
- display_element.parentElement.insertBefore(edit_element, display_element.nextSibling);
-
- this.display_elements.push(display_element);
- this.edit_elements.push(edit_element);
- }
-
- var self = this;
- var binder = function(func, fallback)
- {
- if (func == undefined)
- {
- return fallback;
- }
-
- var bound = function()
- {
- if (this.can_use_element_map)
- {
- func(self, self.edit_element_map, self.display_element_map);
- }
- else
- {
- func(self, self.edit_elements, self.display_elements);
- }
- }
- return bound;
- }
-
- this.bound_open = binder(on_open, this.open);
- this.bound_save = binder(on_save, this.save);
- this.bound_cancel = binder(on_cancel, this.cancel);
-
- var last_element = this.edit_elements[this.edit_elements.length - 1];
- var toolbox = document.createElement("div");
- toolbox.classList.add("editor_toolbox");
- last_element.parentElement.insertBefore(toolbox, last_element.nextSibling);
-
- this.open_button = document.createElement("button");
- this.open_button.innerText = "Edit";
- this.open_button.classList.add("editor_button");
- this.open_button.classList.add("editor_open_button");
- this.open_button.classList.add("green_button");
- this.open_button.onclick = this.bound_open.bind(this);
- toolbox.appendChild(this.open_button);
-
- this.save_button = document.createElement("button");
- this.save_button.innerText = "Save";
- this.save_button.classList.add("editor_button");
- this.save_button.classList.add("editor_save_button");
- this.save_button.classList.add("green_button");
- this.save_button.classList.add("hidden");
- this.save_button.onclick = this.bound_save.bind(this);
- toolbox.appendChild(this.save_button);
-
- this.cancel_button = document.createElement("button");
- this.cancel_button.innerText = "Cancel";
- this.cancel_button.classList.add("editor_button");
- this.cancel_button.classList.add("editor_cancel_button");
- this.cancel_button.classList.add("red_button");
- this.cancel_button.classList.add("hidden");
- this.cancel_button.onclick = this.bound_cancel.bind(this);
- toolbox.appendChild(this.cancel_button);
-
- this.spinner = document.createElement("span");
- this.spinner.innerText = "Submitting...";
- this.spinner.classList.add("editor_spinner");
- this.spinner.classList.add("hidden");
- toolbox.appendChild(this.spinner);
-
- for (var index = 0; index < this.edit_elements.length; index += 1)
- {
- var edit_element = this.edit_elements[index];
- if (edit_element.tagName == "TEXTAREA")
- {
- bind_box_to_button(edit_element, this.save_button, true);
- }
- else
- {
- bind_box_to_button(edit_element, this.save_button, false);
- }
- }
-}
-
function create_message_bubble(message_area, message_positivity, message_text, lifespan)
{
if (lifespan === undefined)
diff --git a/frontends/etiquette_flask/static/js/editor.js b/frontends/etiquette_flask/static/js/editor.js
new file mode 100644
index 0000000..b44a273
--- /dev/null
+++ b/frontends/etiquette_flask/static/js/editor.js
@@ -0,0 +1,221 @@
+var PARAGRAPH_TYPES = new Set(["P", "PRE"]);
+
+function Editor(elements, on_open, on_save, on_cancel)
+{
+ /*
+ This class wraps around display elements like headers and paragraphs, and
+ creates inputs / textareas to edit them with.
+
+ The placeholder text for the edit elements comes from the
+ data-editor-placeholder attribute of the display elements if available.
+
+ The on_open, on_save and on_cancel callbacks will receive two arguments:
+ 1. This editor object.
+ 2. the edit elements as either:
+ If the display elements ALL have data-editor-id attributes,
+ then a dictionary of {data-editor-id: edit_element, ...}.
+ Otherwise, an array of [edit_element, ...] in their original order.
+
+ When your callbacks are used, the default `open`, `save`, `cancel`
+ methods are not called automatically. You should call them from within
+ your function.
+ */
+ this.cancel = function()
+ {
+ this.close();
+ };
+
+ this.close = function()
+ {
+ for (var index = 0; index < this.display_elements.length; index += 1)
+ {
+ this.display_elements[index].classList.remove("hidden");
+ this.edit_elements[index].classList.add("hidden");
+ }
+ this.open_button.classList.remove("hidden")
+ this.save_button.classList.add("hidden");
+ this.cancel_button.classList.add("hidden");
+ };
+
+ this.hide_spinner = function()
+ {
+ this.spinner.classList.add("hidden");
+ };
+
+ this.open = function()
+ {
+ for (var index = 0; index < this.display_elements.length; index += 1)
+ {
+ var display_element = this.display_elements[index];
+ var edit_element = this.edit_elements[index];
+ display_element.classList.add("hidden");
+ edit_element.classList.remove("hidden");
+
+ var empty_text = display_element.dataset.editorEmptyText;
+ if (empty_text !== undefined && display_element.innerText == empty_text)
+ {
+ edit_element.value = "";
+ }
+ else
+ {
+ edit_element.value = display_element.innerText;
+ }
+ }
+ this.open_button.classList.add("hidden")
+ this.save_button.classList.remove("hidden");
+ this.cancel_button.classList.remove("hidden");
+ };
+
+ this.save = function()
+ {
+ for (var index = 0; index < this.display_elements.length; index += 1)
+ {
+ var display_element = this.display_elements[index];
+ var edit_element = this.edit_elements[index];
+
+ if (display_element.dataset.editorEmptyText !== undefined && edit_element.value == "")
+ {
+ display_element.innerText = display_element.dataset.editorEmptyText;
+ }
+ else
+ {
+ display_element.innerText = edit_element.value;
+ }
+ }
+
+ this.close();
+ };
+
+ this.show_spinner = function()
+ {
+ this.spinner.classList.remove("hidden");
+ };
+
+ this.display_elements = [];
+ this.edit_elements = [];
+
+ this.can_use_element_map = true;
+ this.display_element_map = {};
+ this.edit_element_map = {};
+
+ this.misc_data = {};
+
+ for (var index = 0; index < elements.length; index += 1)
+ {
+ var display_element = elements[index];
+ var edit_element;
+ if (PARAGRAPH_TYPES.has(display_element.tagName))
+ {
+ edit_element = document.createElement("textarea");
+ edit_element.rows = 6;
+ }
+ else
+ {
+ edit_element = document.createElement("input");
+ edit_element.type = "text";
+ }
+ edit_element.classList.add("editor_input");
+ edit_element.classList.add("hidden");
+
+ if (display_element.dataset.editorPlaceholder !== undefined)
+ {
+ edit_element.placeholder = display_element.dataset.editorPlaceholder;
+ }
+
+ if (this.can_use_element_map)
+ {
+ if (display_element.dataset.editorId !== undefined)
+ {
+ this.display_element_map[display_element.dataset.editorId] = display_element;
+ this.edit_element_map[display_element.dataset.editorId] = edit_element;
+ }
+ else
+ {
+ this.can_use_element_map = false;
+ this.edit_element_map = null;
+ this.display_element_map = null;
+ }
+ }
+
+ display_element.parentElement.insertBefore(edit_element, display_element.nextSibling);
+
+ this.display_elements.push(display_element);
+ this.edit_elements.push(edit_element);
+ }
+
+ var self = this;
+ var binder = function(func, fallback)
+ {
+ if (func == undefined)
+ {
+ return fallback;
+ }
+
+ var bound = function()
+ {
+ if (this.can_use_element_map)
+ {
+ func(self, self.edit_element_map, self.display_element_map);
+ }
+ else
+ {
+ func(self, self.edit_elements, self.display_elements);
+ }
+ }
+ return bound;
+ }
+
+ this.bound_open = binder(on_open, this.open);
+ this.bound_save = binder(on_save, this.save);
+ this.bound_cancel = binder(on_cancel, this.cancel);
+
+ var last_element = this.edit_elements[this.edit_elements.length - 1];
+ var toolbox = document.createElement("div");
+ toolbox.classList.add("editor_toolbox");
+ last_element.parentElement.insertBefore(toolbox, last_element.nextSibling);
+
+ this.open_button = document.createElement("button");
+ this.open_button.innerText = "Edit";
+ this.open_button.classList.add("editor_button");
+ this.open_button.classList.add("editor_open_button");
+ this.open_button.classList.add("green_button");
+ this.open_button.onclick = this.bound_open.bind(this);
+ toolbox.appendChild(this.open_button);
+
+ this.save_button = document.createElement("button");
+ this.save_button.innerText = "Save";
+ this.save_button.classList.add("editor_button");
+ this.save_button.classList.add("editor_save_button");
+ this.save_button.classList.add("green_button");
+ this.save_button.classList.add("hidden");
+ this.save_button.onclick = this.bound_save.bind(this);
+ toolbox.appendChild(this.save_button);
+
+ this.cancel_button = document.createElement("button");
+ this.cancel_button.innerText = "Cancel";
+ this.cancel_button.classList.add("editor_button");
+ this.cancel_button.classList.add("editor_cancel_button");
+ this.cancel_button.classList.add("red_button");
+ this.cancel_button.classList.add("hidden");
+ this.cancel_button.onclick = this.bound_cancel.bind(this);
+ toolbox.appendChild(this.cancel_button);
+
+ this.spinner = document.createElement("span");
+ this.spinner.innerText = "Submitting...";
+ this.spinner.classList.add("editor_spinner");
+ this.spinner.classList.add("hidden");
+ toolbox.appendChild(this.spinner);
+
+ for (var index = 0; index < this.edit_elements.length; index += 1)
+ {
+ var edit_element = this.edit_elements[index];
+ if (edit_element.tagName == "TEXTAREA")
+ {
+ bind_box_to_button(edit_element, this.save_button, true);
+ }
+ else
+ {
+ bind_box_to_button(edit_element, this.save_button, false);
+ }
+ }
+}
diff --git a/frontends/etiquette_flask/templates/album.html b/frontends/etiquette_flask/templates/album.html
index 3753e80..47f0221 100644
--- a/frontends/etiquette_flask/templates/album.html
+++ b/frontends/etiquette_flask/templates/album.html
@@ -9,6 +9,7 @@
+