mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 01:41:22 +01:00
157 lines
4.9 KiB
JavaScript
157 lines
4.9 KiB
JavaScript
"use strict";
|
|
|
|
window.Pell = (function () {
|
|
const defaultParagraphSeparatorString = "defaultParagraphSeparator";
|
|
const formatBlock = "formatBlock";
|
|
const addEventListener = (parent, type, listener) => parent.addEventListener(type, listener);
|
|
const appendChild = (parent, child) => parent.appendChild(child);
|
|
const createElement = tag => document.createElement(tag);
|
|
const queryCommandState = command => document.queryCommandState(command);
|
|
const queryCommandValue = command => document.queryCommandValue(command);
|
|
const exec = (command, value = null) => document.execCommand(command, false, value);
|
|
|
|
const defaultActions = {
|
|
bold: {
|
|
icon: "<b>B</b>",
|
|
title: "Bold",
|
|
state: () => queryCommandState("bold"),
|
|
result: () => exec("bold")
|
|
},
|
|
italic: {
|
|
icon: "<i>I</i>",
|
|
title: "Italic",
|
|
state: () => queryCommandState("italic"),
|
|
result: () => exec("italic")
|
|
},
|
|
underline: {
|
|
icon: "<u>U</u>",
|
|
title: "Underline",
|
|
state: () => queryCommandState("underline"),
|
|
result: () => exec("underline")
|
|
},
|
|
strikethrough: {
|
|
icon: "<strike>S</strike>",
|
|
title: "Strike-through",
|
|
state: () => queryCommandState("strikeThrough"),
|
|
result: () => exec("strikeThrough")
|
|
},
|
|
heading1: {
|
|
icon: "<b>H<sub>1</sub></b>",
|
|
title: "Heading 1",
|
|
result: () => exec(formatBlock, "<h1>")
|
|
},
|
|
heading2: {
|
|
icon: "<b>H<sub>2</sub></b>",
|
|
title: "Heading 2",
|
|
result: () => exec(formatBlock, "<h2>")
|
|
},
|
|
paragraph: {
|
|
icon: "¶",
|
|
title: "Paragraph",
|
|
result: () => exec(formatBlock, "<p>")
|
|
},
|
|
quote: {
|
|
icon: "“ ”",
|
|
title: "Quote",
|
|
result: () => exec(formatBlock, "<blockquote>")
|
|
},
|
|
olist: {
|
|
icon: "#",
|
|
title: "Ordered List",
|
|
result: () => exec("insertOrderedList")
|
|
},
|
|
ulist: {
|
|
icon: "•",
|
|
title: "Unordered List",
|
|
result: () => exec("insertUnorderedList")
|
|
},
|
|
code: {
|
|
icon: "</>",
|
|
title: "Code",
|
|
result: () => exec(formatBlock, "<pre>")
|
|
},
|
|
line: {
|
|
icon: "―",
|
|
title: "Horizontal Line",
|
|
result: () => exec("insertHorizontalRule")
|
|
},
|
|
link: {
|
|
icon: "🔗",
|
|
title: "Link",
|
|
result: () => navigator.clipboard.readText().then(url => exec("createLink", url))
|
|
},
|
|
image: {
|
|
icon: "📷",
|
|
title: "Image",
|
|
result: () => {
|
|
navigator.clipboard.readText().then(url => exec("insertImage", url));
|
|
exec("enableObjectResizing");
|
|
}
|
|
}
|
|
};
|
|
|
|
const defaultClasses = {
|
|
actionbar: "pell-actionbar",
|
|
button: "pell-button",
|
|
content: "pell-content",
|
|
selected: "pell-button-selected"
|
|
};
|
|
|
|
const init = settings => {
|
|
const actions = settings.actions
|
|
? settings.actions.map(action => {
|
|
if (typeof action === "string") return defaultActions[action];
|
|
else if (defaultActions[action.name]) return {...defaultActions[action.name], ...action};
|
|
return action;
|
|
})
|
|
: Object.keys(defaultActions).map(action => defaultActions[action]);
|
|
|
|
const classes = {...defaultClasses, ...settings.classes};
|
|
|
|
const defaultParagraphSeparator = settings[defaultParagraphSeparatorString] || "div";
|
|
|
|
const actionbar = createElement("div");
|
|
actionbar.className = classes.actionbar;
|
|
appendChild(settings.element, actionbar);
|
|
|
|
const content = (settings.element.content = createElement("div"));
|
|
content.contentEditable = true;
|
|
content.className = classes.content;
|
|
content.oninput = ({target: {firstChild}}) => {
|
|
if (firstChild && firstChild.nodeType === 3) exec(formatBlock, `<${defaultParagraphSeparator}>`);
|
|
else if (content.innerHTML === "<br>") content.innerHTML = "";
|
|
settings.onChange(content.innerHTML);
|
|
};
|
|
content.onkeydown = event => {
|
|
if (event.key === "Enter" && queryCommandValue(formatBlock) === "blockquote") {
|
|
setTimeout(() => exec(formatBlock, `<${defaultParagraphSeparator}>`), 0);
|
|
}
|
|
};
|
|
appendChild(settings.element, content);
|
|
|
|
actions.forEach(action => {
|
|
const button = createElement("button");
|
|
button.className = classes.button;
|
|
button.innerHTML = action.icon;
|
|
button.title = action.title;
|
|
button.setAttribute("type", "button");
|
|
button.onclick = () => action.result() && content.focus();
|
|
|
|
if (action.state) {
|
|
const handler = () => button.classList[action.state() ? "add" : "remove"](classes.selected);
|
|
addEventListener(content, "keyup", handler);
|
|
addEventListener(content, "mouseup", handler);
|
|
addEventListener(button, "click", handler);
|
|
}
|
|
|
|
appendChild(actionbar, button);
|
|
});
|
|
|
|
if (settings.styleWithCSS) exec("styleWithCSS");
|
|
exec(defaultParagraphSeparatorString, defaultParagraphSeparator);
|
|
|
|
return settings.element;
|
|
};
|
|
|
|
return {exec, init};
|
|
})();
|