代码拉取完成,页面将自动刷新
<!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: 400px;
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="checkpoint"></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 CheckPoint{
constructor(state){
this.state = state;
}
getState(){
return this.state;
}
}
class CheckPointHistory{
constructor(render){
this.checkPoints = [];
this.render = render;
}
addCheckPoint(checkpoint){
const name = `# ${this.checkPoints.length} checkPoint`;
const state = {name:name,checkpoint}
this.checkPoints.push(state);
this.render.render(this);
}
get(index){
return this.checkPoints[index].checkpoint;
}
}
class CheckPointRender{
constructor(el,execute){
this.el = el;
this.execute = execute;
}
render(history){
this.el.innerHTML = "";
history.checkPoints.forEach((item,idx)=>{
const div = document.createElement("div");
div.innerHTML = `# ${item.name}`
div.setAttribute("data-idx",idx)
this.el.append(div);
div.addEventListener("click",(e)=>{
const idx = e.target.dataset.idx;
this.execute.restore(history.get(idx));
})
})
}
}
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();
}
saveCheckPoint(){
return new CheckPoint(this.history);
}
restore(chkpoint){
let history = [...chkpoint.getState()];
console.log(history)
this.history = history;
this.undo();
}
}
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",()=>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 CheckPointRender(document.querySelector(".checkpoint"),commexec);
const checkPointHistory = new CheckPointHistory(render);
document.querySelector("#save").addEventListener("click",e=>{
checkPointHistory.addCheckPoint(commexec.saveCheckPoint());
})
</script>
</body>
</html>
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。