2017-07-17 00:21:37 +00:00
|
|
|
var PARAGRAPH_TYPES = new Set(["P", "PRE"]);
|
|
|
|
|
2017-06-15 04:44:18 +00:00
|
|
|
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");
|
|
|
|
|
2017-07-14 06:07:44 +00:00
|
|
|
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;
|
|
|
|
}
|
2017-06-15 04:44:18 +00:00
|
|
|
}
|
|
|
|
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];
|
|
|
|
|
2017-07-14 06:07:44 +00:00
|
|
|
if (display_element.dataset.editorEmptyText !== undefined && edit_element.value == "")
|
|
|
|
{
|
|
|
|
display_element.innerText = display_element.dataset.editorEmptyText;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
display_element.innerText = edit_element.value;
|
|
|
|
}
|
2017-06-15 04:44:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
this.close();
|
|
|
|
};
|
|
|
|
|
|
|
|
this.show_spinner = function()
|
|
|
|
{
|
|
|
|
this.spinner.classList.remove("hidden");
|
|
|
|
};
|
|
|
|
|
|
|
|
this.display_elements = [];
|
|
|
|
this.edit_elements = [];
|
2017-07-14 06:17:47 +00:00
|
|
|
|
2017-06-15 04:44:18 +00:00
|
|
|
this.can_use_element_map = true;
|
2017-07-14 06:17:47 +00:00
|
|
|
this.display_element_map = {};
|
2017-06-15 04:44:18 +00:00
|
|
|
this.edit_element_map = {};
|
|
|
|
|
2017-07-14 06:13:34 +00:00
|
|
|
this.misc_data = {};
|
|
|
|
|
2017-06-15 04:44:18 +00:00
|
|
|
for (var index = 0; index < elements.length; index += 1)
|
|
|
|
{
|
|
|
|
var display_element = elements[index];
|
|
|
|
var edit_element;
|
2017-07-17 00:21:37 +00:00
|
|
|
if (PARAGRAPH_TYPES.has(display_element.tagName))
|
2017-06-15 04:44:18 +00:00
|
|
|
{
|
|
|
|
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");
|
2017-07-14 06:17:47 +00:00
|
|
|
|
2017-06-15 04:44:18 +00:00
|
|
|
if (display_element.dataset.editorPlaceholder !== undefined)
|
|
|
|
{
|
|
|
|
edit_element.placeholder = display_element.dataset.editorPlaceholder;
|
|
|
|
}
|
2017-07-14 06:17:47 +00:00
|
|
|
|
2017-06-15 04:44:18 +00:00
|
|
|
if (this.can_use_element_map)
|
|
|
|
{
|
|
|
|
if (display_element.dataset.editorId !== undefined)
|
|
|
|
{
|
2017-07-14 06:17:47 +00:00
|
|
|
this.display_element_map[display_element.dataset.editorId] = display_element;
|
2017-06-15 04:44:18 +00:00
|
|
|
this.edit_element_map[display_element.dataset.editorId] = edit_element;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.can_use_element_map = false;
|
|
|
|
this.edit_element_map = null;
|
2017-07-14 06:17:47 +00:00
|
|
|
this.display_element_map = null;
|
2017-06-15 04:44:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2017-07-14 06:17:47 +00:00
|
|
|
func(self, self.edit_element_map, self.display_element_map);
|
2017-06-15 04:44:18 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-07-14 06:17:47 +00:00
|
|
|
func(self, self.edit_elements, self.display_elements);
|
2017-06-15 04:44:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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");
|
2017-12-08 19:59:27 +00:00
|
|
|
toolbox.classList.add("editor_toolbox");
|
2017-06-15 04:44:18 +00:00
|
|
|
last_element.parentElement.insertBefore(toolbox, last_element.nextSibling);
|
|
|
|
|
|
|
|
this.open_button = document.createElement("button");
|
|
|
|
this.open_button.innerText = "Edit";
|
2017-07-10 02:51:58 +00:00
|
|
|
this.open_button.classList.add("editor_button");
|
2017-06-15 04:44:18 +00:00
|
|
|
this.open_button.classList.add("editor_open_button");
|
2017-12-16 22:13:02 +00:00
|
|
|
this.open_button.classList.add("green_button");
|
2017-06-15 04:44:18 +00:00
|
|
|
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";
|
2017-07-10 02:51:58 +00:00
|
|
|
this.save_button.classList.add("editor_button");
|
2017-06-15 04:44:18 +00:00
|
|
|
this.save_button.classList.add("editor_save_button");
|
2017-12-16 22:13:02 +00:00
|
|
|
this.save_button.classList.add("green_button");
|
2017-06-15 04:44:18 +00:00
|
|
|
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";
|
2017-07-10 02:51:58 +00:00
|
|
|
this.cancel_button.classList.add("editor_button");
|
2017-06-15 04:44:18 +00:00
|
|
|
this.cancel_button.classList.add("editor_cancel_button");
|
2017-12-16 22:13:02 +00:00
|
|
|
this.cancel_button.classList.add("red_button");
|
2017-06-15 04:44:18 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-21 05:53:59 +00:00
|
|
|
function create_message_bubble(message_area, message_positivity, message_text, lifespan)
|
2016-09-18 08:33:46 +00:00
|
|
|
{
|
|
|
|
if (lifespan === undefined)
|
|
|
|
{
|
|
|
|
lifespan = 8000;
|
|
|
|
}
|
|
|
|
var message = document.createElement("div");
|
2017-03-04 06:30:57 +00:00
|
|
|
message.className = "message_bubble " + message_positivity;
|
2016-09-18 08:33:46 +00:00
|
|
|
var span = document.createElement("span");
|
|
|
|
span.innerHTML = message_text;
|
|
|
|
message.appendChild(span);
|
|
|
|
message_area.appendChild(message);
|
|
|
|
setTimeout(function(){message_area.removeChild(message);}, lifespan);
|
|
|
|
}
|
|
|
|
|
2018-02-18 00:08:38 +00:00
|
|
|
function _request(method, url, callback)
|
2016-09-18 08:33:46 +00:00
|
|
|
{
|
|
|
|
var request = new XMLHttpRequest();
|
|
|
|
request.onreadystatechange = function()
|
|
|
|
{
|
|
|
|
if (request.readyState == 4)
|
|
|
|
{
|
|
|
|
if (callback != null)
|
|
|
|
{
|
2016-12-21 09:11:50 +00:00
|
|
|
var text = request.responseText;
|
2018-02-18 02:47:17 +00:00
|
|
|
var response = {
|
|
|
|
"data": JSON.parse(text),
|
|
|
|
"meta": {}
|
|
|
|
};
|
|
|
|
response["meta"]["request_url"] = url;
|
|
|
|
response["meta"]["status"] = request.status;
|
2017-02-26 08:33:26 +00:00
|
|
|
callback(response);
|
2016-09-18 08:33:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
var asynchronous = true;
|
2018-02-18 00:08:38 +00:00
|
|
|
request.open(method, url, asynchronous);
|
|
|
|
return request;
|
|
|
|
}
|
|
|
|
function get(url, callback)
|
|
|
|
{
|
|
|
|
request = _request("GET", url, callback);
|
|
|
|
request.send();
|
|
|
|
}
|
|
|
|
function post(url, data, callback)
|
|
|
|
{
|
|
|
|
request = _request("POST", url, callback);
|
2016-09-18 08:33:46 +00:00
|
|
|
request.send(data);
|
|
|
|
}
|
|
|
|
|
2017-05-13 23:13:26 +00:00
|
|
|
function create_album_and_follow(parent)
|
|
|
|
{
|
|
|
|
var url = "/albums/create_album";
|
|
|
|
var data = new FormData();
|
|
|
|
if (parent !== undefined)
|
|
|
|
{
|
|
|
|
data.append("parent", parent);
|
|
|
|
}
|
|
|
|
function receive_callback(response)
|
|
|
|
{
|
2018-02-18 02:47:17 +00:00
|
|
|
if (response["meta"]["status"] == 200 && response["data"]["id"])
|
2017-07-29 22:40:40 +00:00
|
|
|
{
|
2018-02-18 02:47:17 +00:00
|
|
|
window.location.href = "/album/" + response["data"]["id"];
|
2017-07-29 22:40:40 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
console.log(response);
|
|
|
|
}
|
2017-05-13 23:13:26 +00:00
|
|
|
}
|
|
|
|
post(url, data, receive_callback);
|
2016-10-10 03:50:13 +00:00
|
|
|
}
|
2017-05-13 23:13:26 +00:00
|
|
|
|
2017-12-16 11:47:54 +00:00
|
|
|
function delete_all_children(element)
|
|
|
|
{
|
|
|
|
while (element.firstChild)
|
|
|
|
{
|
|
|
|
element.removeChild(element.firstChild);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-24 08:24:38 +00:00
|
|
|
function bind_box_to_button(box, button, ctrl_enter)
|
|
|
|
{
|
|
|
|
// Thanks Yaroslav Yakovlev
|
|
|
|
// http://stackoverflow.com/a/9343095
|
|
|
|
var bound_box_hook = function(event)
|
|
|
|
{
|
|
|
|
if (event.key !== "Enter")
|
|
|
|
{return;}
|
|
|
|
|
|
|
|
ctrl_success = !ctrl_enter || (event.ctrlKey)
|
|
|
|
|
|
|
|
if (! ctrl_success)
|
|
|
|
{return;}
|
|
|
|
|
|
|
|
button.click();
|
|
|
|
}
|
|
|
|
box.addEventListener("keyup", bound_box_hook);
|
|
|
|
}
|
|
|
|
|
|
|
|
function entry_with_history_hook(event)
|
2016-10-10 03:50:13 +00:00
|
|
|
{
|
2018-02-24 08:24:38 +00:00
|
|
|
//console.log(event);
|
|
|
|
var box = event.target;
|
|
|
|
|
2016-10-10 03:50:13 +00:00
|
|
|
if (box.entry_history === undefined)
|
2018-02-24 08:24:38 +00:00
|
|
|
{box.entry_history = [];}
|
|
|
|
|
2016-10-10 03:50:13 +00:00
|
|
|
if (box.entry_history_pos === undefined)
|
2018-02-24 08:24:38 +00:00
|
|
|
{box.entry_history_pos = -1;}
|
|
|
|
|
|
|
|
if (event.key === "Enter")
|
2016-10-10 03:50:13 +00:00
|
|
|
{
|
|
|
|
box.entry_history.push(box.value);
|
|
|
|
}
|
2018-02-24 08:24:38 +00:00
|
|
|
else if (event.key === "ArrowUp")
|
2016-10-10 03:50:13 +00:00
|
|
|
{
|
|
|
|
if (box.entry_history.length == 0)
|
2018-02-24 08:24:38 +00:00
|
|
|
{return}
|
|
|
|
|
2016-10-10 03:50:13 +00:00
|
|
|
if (box.entry_history_pos == -1)
|
2018-02-24 08:24:38 +00:00
|
|
|
{box.entry_history_pos = box.entry_history.length - 1;}
|
2016-10-10 03:50:13 +00:00
|
|
|
else if (box.entry_history_pos > 0)
|
2018-02-24 08:24:38 +00:00
|
|
|
{box.entry_history_pos -= 1;}
|
|
|
|
|
2016-10-10 03:50:13 +00:00
|
|
|
box.value = box.entry_history[box.entry_history_pos];
|
2017-02-25 06:07:59 +00:00
|
|
|
setTimeout(function(){box.selectionStart = box.value.length;}, 0);
|
2016-10-10 03:50:13 +00:00
|
|
|
}
|
2018-02-24 08:24:38 +00:00
|
|
|
else if (event.key === "Escape")
|
2016-10-10 03:50:13 +00:00
|
|
|
{
|
|
|
|
box.value = "";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
box.entry_history_pos = -1;
|
|
|
|
}
|
2016-12-21 09:11:50 +00:00
|
|
|
}
|
2018-02-18 03:12:34 +00:00
|
|
|
|
|
|
|
function html_to_element(html)
|
|
|
|
{
|
|
|
|
var template = document.createElement("template");
|
|
|
|
template.innerHTML = html;
|
|
|
|
return template.content.firstChild;
|
|
|
|
}
|