|
|
|
@ -11,17 +11,21 @@ function editor_event_source(event)
|
|
|
|
|
/* Grab the button and the parent editor block. The onclick event itself
|
|
|
|
|
usually reports the SVG in the button as the source */
|
|
|
|
|
let node = event.target || event.srcElement;
|
|
|
|
|
while(node != document.body) {
|
|
|
|
|
if(node.tagName == "BUTTON" && !button) {
|
|
|
|
|
while (node != document.body) {
|
|
|
|
|
if (node.tagName == "BUTTON" && !button) {
|
|
|
|
|
button = node;
|
|
|
|
|
}
|
|
|
|
|
if(node.classList.contains("editor") && !editor) {
|
|
|
|
|
if (node.classList.contains("editor") && !editor) {
|
|
|
|
|
editor = node;
|
|
|
|
|
// Hack to use keybinds
|
|
|
|
|
if (!button) {
|
|
|
|
|
button = node.firstElementChild.firstElementChild
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
node = node.parentNode;
|
|
|
|
|
}
|
|
|
|
|
if(!button || !editor) return;
|
|
|
|
|
if (!button || !editor) return;
|
|
|
|
|
|
|
|
|
|
const ta = editor.querySelector(".editor textarea");
|
|
|
|
|
return [editor, button, ta];
|
|
|
|
@ -47,7 +51,7 @@ function editor_insert_around(event, before="", after=null)
|
|
|
|
|
let indexStart = ta.selectionStart;
|
|
|
|
|
let indexEnd = ta.selectionEnd;
|
|
|
|
|
|
|
|
|
|
if(after === null) {
|
|
|
|
|
if (after === null) {
|
|
|
|
|
after = before;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -55,7 +59,7 @@ function editor_insert_around(event, before="", after=null)
|
|
|
|
|
before + ta.value.substring(indexStart, indexEnd) + after);
|
|
|
|
|
|
|
|
|
|
/* Restore selection */
|
|
|
|
|
if(indexStart != indexEnd) {
|
|
|
|
|
if (indexStart != indexEnd) {
|
|
|
|
|
ta.selectionStart = start;
|
|
|
|
|
ta.selectionEnd = end;
|
|
|
|
|
}
|
|
|
|
@ -76,13 +80,13 @@ function editor_act_on_lines(event, fn)
|
|
|
|
|
let indexEnd = ta.selectionEnd;
|
|
|
|
|
|
|
|
|
|
let firstLineIndex = ta.value.substring(0, indexStart).lastIndexOf('\n');
|
|
|
|
|
if(firstLineIndex < 0)
|
|
|
|
|
if (firstLineIndex < 0)
|
|
|
|
|
firstLineIndex = 0;
|
|
|
|
|
else
|
|
|
|
|
firstLineIndex += 1;
|
|
|
|
|
|
|
|
|
|
let lastLineIndex = ta.value.substring(indexEnd).indexOf('\n');
|
|
|
|
|
if(lastLineIndex < 0)
|
|
|
|
|
if (lastLineIndex < 0)
|
|
|
|
|
lastLineIndex = ta.value.length;
|
|
|
|
|
else
|
|
|
|
|
lastLineIndex += indexEnd;
|
|
|
|
@ -124,7 +128,7 @@ function editor_clear_modals(event, close = true)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* End-user functions */
|
|
|
|
|
function editor_inline(event, type)
|
|
|
|
|
function editor_inline(event, type, enable_preview = true)
|
|
|
|
|
{
|
|
|
|
|
tokens = {
|
|
|
|
|
bold: "**",
|
|
|
|
@ -134,11 +138,13 @@ function editor_inline(event, type)
|
|
|
|
|
inlinecode: "`",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if(type in tokens){
|
|
|
|
|
if (type in tokens) {
|
|
|
|
|
editor_insert_around(event, tokens[type]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
preview();
|
|
|
|
|
if (enable_preview) {
|
|
|
|
|
preview();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function editor_display_link_modal(event) {
|
|
|
|
@ -148,11 +154,11 @@ function editor_display_link_modal(event) {
|
|
|
|
|
let selection = ta.value.substring(indexStart, indexEnd);
|
|
|
|
|
|
|
|
|
|
// Assuming it's a link
|
|
|
|
|
if(selection.match(/^https?:\/\/\S+/)) {
|
|
|
|
|
if (selection.match(/^https?:\/\/\S+/)) {
|
|
|
|
|
event.currentTarget.querySelector("#link-link-input").value = selection;
|
|
|
|
|
}
|
|
|
|
|
// Or text
|
|
|
|
|
else if(selection != "") {
|
|
|
|
|
else if (selection != "") {
|
|
|
|
|
event.currentTarget.querySelector("#link-desc-input").value = selection;
|
|
|
|
|
}
|
|
|
|
|
// Or nothing selected
|
|
|
|
@ -177,7 +183,7 @@ function editor_insert_link(event, link_id, text_id, media = false)
|
|
|
|
|
|
|
|
|
|
const media_selector = document.getElementsByName("media-type");
|
|
|
|
|
for(i = 0; i < media_selector.length; i++) {
|
|
|
|
|
if(media_selector[i].checked) {
|
|
|
|
|
if (media_selector[i].checked) {
|
|
|
|
|
media_type = `{type=${media_selector[i].value}}`;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -188,7 +194,7 @@ function editor_insert_link(event, link_id, text_id, media = false)
|
|
|
|
|
`${media ? "!" : ""}[${text.length === 0 ? ta.value.substring(indexStart, indexEnd) : text}](${link})${media ? media_type : ""}`);
|
|
|
|
|
|
|
|
|
|
/* Restore selection */
|
|
|
|
|
if(indexStart != indexEnd) {
|
|
|
|
|
if (indexStart != indexEnd) {
|
|
|
|
|
ta.selectionStart = start;
|
|
|
|
|
ta.selectionEnd = end;
|
|
|
|
|
}
|
|
|
|
@ -207,18 +213,18 @@ function editor_title(event, level, diff)
|
|
|
|
|
while(count < line.length && line[count] == '#') count++;
|
|
|
|
|
|
|
|
|
|
let contents_index = count;
|
|
|
|
|
if(count < line.length && line[count] == ' ') contents_index++;
|
|
|
|
|
if (count < line.length && line[count] == ' ') contents_index++;
|
|
|
|
|
let contents = line.slice(contents_index);
|
|
|
|
|
|
|
|
|
|
if(level > 0 || count == 1 && diff == -1) {
|
|
|
|
|
if (level > 0 || count == 1 && diff == -1) {
|
|
|
|
|
/* Remove the title if the corresponding level is re-requested */
|
|
|
|
|
if(count == level || count == 1 && diff == -1)
|
|
|
|
|
if (count == level || count == 1 && diff == -1)
|
|
|
|
|
return contents;
|
|
|
|
|
/* Otherwise, add it */
|
|
|
|
|
else
|
|
|
|
|
return '#'.repeat(level) + ' ' + contents;
|
|
|
|
|
}
|
|
|
|
|
else if(count > 0) {
|
|
|
|
|
else if (count > 0) {
|
|
|
|
|
/* Apply the difference */
|
|
|
|
|
let new_level = Math.max(1, Math.min(6, count + diff));
|
|
|
|
|
return '#'.repeat(new_level) + ' ' + contents;
|
|
|
|
@ -235,7 +241,7 @@ function editor_quote(event)
|
|
|
|
|
while(count < line.length && line[count] == '>') count++;
|
|
|
|
|
|
|
|
|
|
let contents_index = count;
|
|
|
|
|
if(count < line.length && line[count] == ' ') contents_index++;
|
|
|
|
|
if (count < line.length && line[count] == ' ') contents_index++;
|
|
|
|
|
let contents = line.slice(contents_index);
|
|
|
|
|
|
|
|
|
|
/* Apply the difference */
|
|
|
|
@ -251,7 +257,7 @@ function editor_bullet_list(event)
|
|
|
|
|
let count = ident.length;
|
|
|
|
|
|
|
|
|
|
const contents = line.slice(count);
|
|
|
|
|
if((count < line.length || count == 0) && line[count] != '-') return '- ' + contents;
|
|
|
|
|
if ((count < line.length || count == 0) && line[count] != '-') return '- ' + contents;
|
|
|
|
|
|
|
|
|
|
return ident + "\t" + contents;
|
|
|
|
|
});
|
|
|
|
@ -265,7 +271,7 @@ function editor_numbered_list(event)
|
|
|
|
|
let count = ident.length;
|
|
|
|
|
|
|
|
|
|
const contents = line.slice(count);
|
|
|
|
|
if((count < line.length || count == 0) && isNaN(line[count])) return '1. ' + contents;
|
|
|
|
|
if ((count < line.length || count == 0) && isNaN(line[count])) return '1. ' + contents;
|
|
|
|
|
|
|
|
|
|
return ident + "\t" + contents;
|
|
|
|
|
});
|
|
|
|
@ -334,24 +340,43 @@ ta.addEventListener('keydown', function(e) {
|
|
|
|
|
// Ctrl+B adds bold
|
|
|
|
|
// Ctrl+I adds italic
|
|
|
|
|
// Ctrl+U adds underline
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Ctrl+Enter send the form
|
|
|
|
|
if (e.ctrlKey && keyCode == 13) {
|
|
|
|
|
let t = e.target;
|
|
|
|
|
while(! (t instanceof HTMLFormElement)) {
|
|
|
|
|
t = t.parentNode;
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
t.submit();
|
|
|
|
|
} catch(exception) {
|
|
|
|
|
t.submit.click();
|
|
|
|
|
if (e.ctrlKey) {
|
|
|
|
|
switch (keyCode) {
|
|
|
|
|
case 13:
|
|
|
|
|
let t = e.target;
|
|
|
|
|
while(! (t instanceof HTMLFormElement)) {
|
|
|
|
|
t = t.parentNode;
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
t.submit();
|
|
|
|
|
} catch(exception) {
|
|
|
|
|
t.submit.click();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 66: // B
|
|
|
|
|
editor_inline(e, "bold", false);
|
|
|
|
|
break;
|
|
|
|
|
case 72: // H
|
|
|
|
|
editor_title(e, 0, +1);
|
|
|
|
|
break;
|
|
|
|
|
case 73: // I
|
|
|
|
|
editor_inline(e, "italic", false);
|
|
|
|
|
break;
|
|
|
|
|
case 83: // S
|
|
|
|
|
editor_inline(e, "strike", false);
|
|
|
|
|
break;
|
|
|
|
|
case 85: // U
|
|
|
|
|
editor_inline(e, "underline", false);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set a timeout for refreshing the preview
|
|
|
|
|
if (previewTimeout != null) {
|
|
|
|
|
clearTimeout(previewTimeout);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
previewTimeout = setTimeout(preview, 3000);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|