代码拉取完成,页面将自动刷新
同步操作将从 doudoucode/javascript_design_patterns 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
margin: 10px;
}
.toolbar {
background: #ddd;
height: 40px;
line-height: 40px;
padding: 0 4px;
}
.editor {
min-height: 200px;
border: 4px solid #ddd;
font-size: 2rem;
font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
}
</style>
</head>
<body>
<div class="toolbar">
<button data-cmd="Bold">B</button>
<button data-cmd="Italic">I</button>
<button data-cmd="UnderLine">U</button>
<button data-cmd="HighLight">H</button>
<button data-cmd="undo">undo</button>
<span>|</span>
<button data-cmd="Save" id="save">Save</button>
</div>
<div class="editor" contenteditable="true">
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Vero nulla minima similique. Accusamus alias dolore
cumque explicabo, nostrum quisquam rerum quaerat provident voluptatibus illo error earum sed nisi vel! Illum.
</div>
<div class="snapshots">
</div>
<script>
class Command {
constructor(editor) {
this.editor = editor;
this.state = "";
}
Execute() {
this.state = this.editor.getHTML();
this.exec();
}
undo() {
this.editor.setHTML(this.state);
}
getState() {
return this.state;
}
}
class BoldCommand extends Command {
exec() {
this.editor.Bold();
}
}
class ItalicCommand extends Command {
exec() {
this.editor.Italic();
}
}
class UnderLineCommand extends Command {
exec() {
this.editor.UnderLine();
}
}
class HighLightCommand extends Command {
exec() {
this.editor.HighLight();
}
}
class SaveCommand extends Command{
exec(){
alert("Saved!!!!!")
}
}
class Editor {
constructor(el) {
this.el = el;
}
wrapElement(nodeName, style) {
const selec = window.getSelection();
const focusEle = selec.focusNode.nodeType === Node.TEXT_NODE ?
selec.focusNode.parentElement : selec.focusNode;
if (focusEle.nodeName === nodeName.toUpperCase()) {
focusEle.outerHTML = focusEle.innerHTML;
} else {
const range = selec.getRangeAt(0);
const node = document.createElement(nodeName);
style && (node.style = style)
range.surroundContents(node);
const newRange = document.createRange();
newRange.selectNodeContents(node);
selec.removeAllRanges();
selec.addRange(newRange);
}
}
Bold() {
this.wrapElement("b");
}
Italic() {
this.wrapElement("i");
}
UnderLine() {
this.wrapElement("u");
}
HighLight() {
this.wrapElement("span", "background:yellow;")
}
getHTML() {
return this.el.innerHTML;
}
setHTML(value) {
this.el.innerHTML = value;
}
}
class CommandExector {
constructor() {
this.factory = {};
this.history = [];
}
registerCommmand(name, func) {
this.factory[name] = func;
}
exec(name) {
const cmd = this.factory[name]();
cmd.Execute();
this.history.push(cmd);
}
undo() {
const popCmd = this.history.pop();
if (!popCmd) return;
popCmd.undo();
}
createSnapshot(){
return new Snapshot([...this.history])
}
restorySnapshot(snapshot){
const state = snapshot.getState();
this.history = [...state];
this.undo();
}
}
class Snapshot{
constructor(state){
this.state = state;
}
getState(){
return this.state;
}
}
class SnapshotHistory{
constructor(render){
this.history = [];
this.render = render;
}
addSnapshot(snapshot){
this.history.push(snapshot);
this.render.render(this);
}
get(index){
return this.history[index];
}
}
class SnapshotRender{
constructor(el,common){
this.el = el;
this.common = common;
}
render(history){
this.el.innerHTML = "";
history.history.forEach((item,idx)=>{
const div = document.createElement("div");
div.innerHTML = `#${idx} snapshot`;
div.dataset.idx = idx;
this.el.append(div);
div.addEventListener("click",e=>{
const idx = e.target.dataset.idx;
const state = history.get(idx);
this.common.restorySnapshot(state);
})
})
}
}
const editor = new Editor(document.querySelector(".editor"));
const commexec = new CommandExector();
commexec.registerCommmand("Bold", () => {
return new BoldCommand(editor)
})
commexec.registerCommmand("Italic", () => {
return new ItalicCommand(editor)
})
commexec.registerCommmand("UnderLine", () => {
return new UnderLineCommand(editor)
})
commexec.registerCommmand("HighLight", () => {
return new HighLightCommand(editor)
})
commexec.registerCommmand("Save",()=>{
return new SaveCommand(editor)
})
document.querySelectorAll("button").forEach(item => {
item.addEventListener("click", e => {
const cmd = e.target.dataset.cmd;
if (cmd === "undo") {
commexec.undo();
} else {
commexec.exec(cmd);
}
})
})
const render = new SnapshotRender(document.querySelector(".snapshots"),
commexec);
const snapshotHistory = new SnapshotHistory(render);
document.querySelector("#save").addEventListener("click",e=>{
const snapshot = commexec.createSnapshot();
snapshotHistory.addSnapshot(snapshot);
})
</script>
</body>
</html>
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。