419 lines
12 KiB
JavaScript
Raw Normal View History

2024-10-28 01:33:33 +08:00
/** *
* 工具类
*/
(function () {
/**
* 最新修改的元素
*/
const latestOpDoc = null
class MyRecovery {
constructor(data, func) {
this.data = data;
this.func = func;
}
getData() {
return this.data;
}
getFun() {
return this.func;
}
recovery() {
this.func();
}
}
/**
* 行数增加记录
*/
const num = 0
/**
* 是否开始输入中文
*/
const inCompositionEvent = false;
/**
* 我的文档数据
*/
const MyDocMap = new Map()
// push推一个在后面就是 append 的意思
// pop从后面拉走配合 push 就是栈
// unshift从前面加一个数据就是 insert(it, 0) 的意思
// shift前面拉个数据走配合 shift 就是一个反向栈,配合 push 就是队列
class MyQueue {
constructor(size) {
this.insertIndex = 0
this.delIndex = 0
this.capacity = 0;
this.size = size;
this.arr = new Array(size);
}
push(handle) {
if (this.capacity === this.arr.length) {
console.log("满了");
this.capacity--;
this.arr[this.capacity] = null;
//todo 替代
// this.end++;
}
this.arr[this.capacity] = handle;
this.capacity++;
}
pull() {
if (this.capacity <= 0) {
return null
}
this.capacity--;
//到底回退
if (this.shift > this.size) {
this.shift = 0;
}
return this.arr[this.shift];
}
}
class MyNode {
constructor(id) {
this.id = id
this.hidden = false
this.style = new InnerStyle()
}
getHidden() {
return this.hidden
}
setHidden(val) {
this.hidden = val
}
setSource(source) {
this.source = source
}
getSource() {
return this.source
}
getStyle() {
return this.style
}
}
class InnerStyle {
constructor() {
this.nodeType = "p"
//map-> index:classList
this.childrenStyle = null;
this.preStyle = null;
this.getNodeType = function getNodeType() {
return this.nodeType
}
this.setNodeType = function setNodeType(nodeType) {
this.nodeType = nodeType
}
//前置类型 如 ul ol 代码块 等
this.setPreStyle = function setPreStyle(k, v) {
if (this.preStyle == null) {
this.preStyle = new MyKV(k, v);
}
}
this.getPreStyle = function getPreStyle() {
return this.preStyle
}
}
setChildrenStyle(index, classList) {
if (this.childrenStyle === null) {
this.childrenStyle = new Map();
}
this.childrenStyle.set(index, classList)
}
getChildrenStyle(index) {
return this.childrenStyle.get(index);
}
getChildrenStyleMap() {
return this.childrenStyle;
}
setChildrenStyleMapNull() {
this.childrenStyle = null;
}
}
class MyKV {
constructor(k, v) {
this.k = k
this.v = v
this.getK = function getK() {
return this.k
}
this.getV = function getV() {
return this.v
}
}
}
/**
* 主节点元素
*/
const MyRoot = document.getElementById("noteshare")
function isNum(value) {
return !isNaN(parseFloat(value)) && isFinite(value)
}
function getSelection() {
return window.getSelection() || document.selection
}
/**
*
* @returns 生产uuid
*/
function uuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
.replace(/[xy]/g, function (c) {
const r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8)
return v.toString(16)
}).split("-")[0]
}
/**
* 在目标元素后面插叙 新元素
* @param {*} newElement
* @param {*} targetElement
*/
function insertAfter(newElement, targetElement) {
// console.log("开始: ",newElement, targetElement)
var parent = targetElement.parentNode
if (parent.lastChild == targetElement) {
// 如果最后的节点是目标元素,则直接添加。因为默认是最后
parent.appendChild(newElement)
} else {
parent.insertBefore(newElement, targetElement.nextSibling)
//如果不是,则插入在目标元素的下一个兄弟节点 的前面。也就是目标元素的后面
}
}
function parseOrder(curP) {
return parseInt(curP.getAttribute("data-order"))
}
/**
*
* @param {*} curP
* @param onkeydownHandle
*/
function firstCmd(curP, onkeydownHandle) {
let newParagraph;
let inputLength = curP.innerText.length
/**
* h1 ~ h6
*/
if (curP.innerText.startsWith("#") && curP.innerHTML.endsWith("&nbsp;")) {
let curNo = parseOrder(curP)
let mapNode = utils.MyDocMap.get(curNo)
// console.log(curP, " - ", curP.innerHTML, curP.innerHTML.startsWith("# "))
if (curP.innerHTML.startsWith("#&nbsp;") || curP.innerHTML.startsWith("# ")) {
mapNode.getStyle().setNodeType("h1")
becomeAnotherElement(curP, "h1", onkeydownHandle)
} else if (curP.innerHTML.startsWith("##&nbsp;")) {
mapNode.getStyle().setNodeType("h2")
becomeAnotherElement(curP, "h2", onkeydownHandle)
} else if (curP.innerHTML.startsWith("###&nbsp;")) {
mapNode.getStyle().setNodeType("h3")
becomeAnotherElement(curP, "h3", onkeydownHandle)
} else if (curP.innerHTML.startsWith("####&nbsp;")) {
mapNode.getStyle().setNodeType("h4")
becomeAnotherElement(curP, "h4", onkeydownHandle)
} else if (curP.innerHTML.startsWith("#####&nbsp;")) {
mapNode.getStyle().setNodeType("h5")
becomeAnotherElement(curP, "h5", onkeydownHandle)
} else {
mapNode.getStyle().setNodeType("h6")
becomeAnotherElement(curP, "h6", onkeydownHandle)
}
}
/**
* 无序列表效果
*/
if (inputLength === 2 && curP.innerText.startsWith("-") && curP.innerHTML.endsWith("&nbsp;")) {
let curNo = parseOrder(curP)
let mapNode = utils.MyDocMap.get(curNo)
mapNode.getStyle().setPreStyle("ul", true)
//clean
curP.innerHTML = ""
mapNode.setSource("")
//根据上一层级元素动态选择 todo
curP.setAttribute("style", "padding-left: 1rem;")
//新增元素
newParagraph = document.createElement("span");
newParagraph.setAttribute("contenteditable", "false")
//∙ vs ∘
newParagraph.innerHTML = "∙ &nbsp;"
curP.append(newParagraph)
//添加一个选区
var selObj = window.getSelection()
var rangeObj = document.createRange()
rangeObj.selectNode(curP)
selObj.addRange(rangeObj)
//收起选区到一个点,光标落在一个可编辑元素上
window.getSelection().collapse(curP, true)
}
/**
* 有序列表效果
*/
if (inputLength > 2 && inputLength <= 5 && isNum(curP.innerText.substring(0, inputLength - 2)) && curP.innerHTML.endsWith(".&nbsp;")) {
let num = curP.innerText.substring(0, inputLength - 2)
console.log(curP.innerText, num)
let curNo = parseOrder(curP)
let mapNode = utils.MyDocMap.get(curNo)
mapNode.getStyle().setPreStyle("ol", num)
//clean
curP.innerHTML = ""
mapNode.setSource("")
//todo
curP.setAttribute("style", "padding-left: 1rem;")
//新增元素
newParagraph = document.createElement("span");
newParagraph.setAttribute("contenteditable", "false")
newParagraph.innerHTML = num + ".&nbsp;"
curP.append(newParagraph)
//添加一个选区
var selObj = window.getSelection()
var rangeObj = document.createRange()
rangeObj.selectNode(curP)
selObj.addRange(rangeObj)
//收起选区到一个点,光标落在一个可编辑元素上
window.getSelection().collapse(curP, true)
}
}
/**
* 变成另一个元素
* @param {*} curP
* @param {*} elementName
*/
function becomeAnotherElement(curP, elementName, onkeydownHandle) {
var newParagraph = document.createElement(elementName)
newParagraph.setAttribute("contenteditable", "true")
newParagraph.setAttribute("data-id", curP.getAttribute("data-id"))
newParagraph.setAttribute("id", curP.getAttribute("data-id"))
newParagraph.setAttribute("data-order", curP.getAttribute("data-order"))
newParagraph.onkeydown = onkeydownHandle
//todo 支持 有数据的行 在行首输入 #
// if()
// switch (elementName){
// case "h1":
// }
newParagraph.innerHTML = "<br>"
insertAfter(newParagraph, curP)
curP.remove()
//matData
let curNo = parseOrder(curP)
let mapNode = utils.MyDocMap.get(curNo)
mapNode.setSource("")
//收起选区到一个点,光标落在一个可编辑元素上
window.getSelection().setPosition(newParagraph, 0)
}
function parseStyleName2ClassName(styleName) {
switch (styleName) {
case "b":
return "childStyleStrong";
case "i":
return "childStyleI";
case "u":
return "childStyleU";
case "c_red":
return "childStyleColor";
case "del":
return "childStyleDel"
}
}
function syncOnePInfo(p) {
//子元素为空不处理
if (p.children.length <= 0) {
return
}
// let id = p.getAttribute("id");
let order = parseInt(p.getAttribute("data-order"));
let curMapData = this.MyDocMap.get(order);
//清空重置
curMapData.getStyle().setChildrenStyleMapNull();
for (let i = 0; i < p.children.length; i++) {
let curItem = p.children[i];
let tmpClassList = curItem.classList;
if (tmpClassList != null && tmpClassList.length > 0) {
curMapData.getStyle().setChildrenStyle(i, tmpClassList);
}
}
console.log("curPEle : ", p, " children: ", p.children, " childrenMap: ", curMapData.getStyle().getChildrenStyleMap())
}
window.utils = {
isNum,
uuid,
parseOrder,
getSelection,
insertAfter,
firstCmd,
becomeAnotherElement,
parseStyleName2ClassName,
syncOnePInfo,
latestOpDoc,
num,
inCompositionEvent,
MyDocMap,
MyRoot,
MyNode,
InnerStyle,
MyKV,
MyQueue,
MyRecovery,
}
})()