我有一个内容可编辑的div,我希望用户输入。当用户使用onkeyup在框中键入内容时,我激活了一个更改某些字符颜色的函数:
var lTags = fixedCode.innerHTML.replace(/</gi, "<span style='color:gold;'><</span>");
var rTags = lTags.replace(/>/gi, "<span style='color:gold'>></span>");
fixedCode.innerHTML = rTags;
该代码的作用是将每个符号转换为金色。但是,当我这样做时,我不再能够在contenteditable框中键入单词,因为每次按下一个键时,该框都会自动刷新。
function checkIt(code) {
var fixedCode = document.getElementById(code);
var lTags = fixedCode.innerHTML.replace(/</gi, "<span style='color:gold;'><</span>");
var rTags = lTags.replace(/>/gi, "<span style='color:gold'>></span>");
fixedCode.innerHTML = rTags;
}
<div id="box" contenteditable="true" onkeyup="checkIt(this.id);">See for yourself</div>
要亲自查看,请尝试在框中键入任何HTML标记。
首先,为什么它会更改标签左
<
而不是标签>
右部分的颜色?以及如何在不删除变色 Material 的情况下在框内输入内容。我见过类似的问题,但答案是Jquery。 我不想使用JQUERY! 最佳答案
这个示例目前可以在Chrome中使用进行工作 ...,但是可以找到一种方法,即使文本是透明的,也可以使插入符号可见-在其他浏览器上,您一切顺利。
所以我对Hardcore-JS太懒了,一个让我大吃一惊的想法是使用
关于此技术的一个好的一面是,您始终(在contenteditable DIV中)保留要替换的内容的未更改版本!
不好的一面是,在每次击键时,您都再次解析相同的内容-随着替换列表的增加,它可能会成为性能杀手,因为替换列表会增加
O(n)
。有关优化的详细信息,请阅读前往VSCode Optimizations in Syntax Highlighting
基本示例:
function highLite(el) {
el.previousElementSibling.innerHTML = el.innerHTML
.replace(/(<|>)/g, "<span class='hl_angled'>$1</span>")
.replace(/(\{|\})/g, "<span class='hl_curly'>$1</span>");
}
body{margin:0; font:14px/1 sans-serif;}
.highLite{
border: 1px solid #888;
position: relative;
}
.highLite_colors,
.highLite_editable {
padding: 16px;
}
/* THE UNDERLAYING ONE WITH COLORS */
.highLite_colors {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
user-select: none;
}
/* THE OVERLAYING CONTENTEDITABLE WITH TRANSPARENT TEXT */
.highLite > div:nth-child(2) {
position: relative;
-webkit-text-fill-color: transparent; /* Chrome: make text transparent */
text-fill-color: transparent; /* One day, hopefully? */
color: black; /* But keep caret black */
}
.hl_angled{ color: turquoise; }
.hl_curly{ color: fuchsia; }
Try to type some angled < > or curly { } brackets
<div class="highLite">
<div class="highLite_colors">Type here:</div>
<div class="highLite_editable" contenteditable oninput="highLite(this);">Type here:</div>
</div>
高级示例:
(需要您自担风险,这是我的咖啡时间游乐场)
const lang = {
js: {
equa: /(\b=\b)/g,
quot: /(`|'|"|'|")/g,
comm: /((\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\/)|(\/\/.*))/g,
logi: /(%=|%|\-|\+|\*|&{1,2}|\|{1,2}|<=|>=|<|>|!={1,2}|={2,3})/g,
numb: /(\d+(\.\d+)?(e\d+)?)/g,
func: /(?<=^|\s*)(async|console|alert|Math|Object|Array|String|class(?!\s*\=)|function|(?<=\.)\D\w*)(?=\b)/g,
decl: /(?<=^|\s*)(var|let|const)/g, // Declarations
pare: /(\(|\))/g,
squa: /(\[|\])/g,
curl: /(\{|\})/g,
},
// Props order matters! Here I rely on "tags:"
// being already applied in the previous iteration
html: {
tags: /(?<=<(?:\/)?)(\w+)(?=\s|\>)/g,
angl: /(<\/?|>)/g,
attr: /((?<=<i class=html_tags>\w+<\/i>)[^<]+)/g,
}
};
const highLite = el => {
const dataLang = el.dataset.lang; // Detect "js", "html", "py", "bash", ...
const langObj = lang[dataLang]; // Extract object from lang regexes dictionary
let html = el.innerHTML;
Object.keys(langObj).forEach(function(key) {
html = html.replace(langObj[key], `<i class=${dataLang}_${key}>$1</i>`);
});
el.previousElementSibling.innerHTML = html; // Finally, show highlights!
};
const editors = document.querySelectorAll(".highLite_editable");
editors.forEach(el => {
el.contentEditable = true;
el.spellcheck = false;
el.autocorrect = "off";
el.autocapitalize = "off";
el.addEventListener("input", highLite.bind(null, el));
el.addEventListener("input", highLite.bind(null, el));
highLite(el); // Init!
});
* {margin: 0; box-sizing: boder-box;}
body {
font: 14px/1.4 sans-serif;
background: hsl(220, 16%, 16%);
color: #fff;
padding: 16px;
}
#editor {
display: flex;
}
h2 {
padding: 16px 0;
font-weight: 200;
font-size: 14px;
}
.highLite {
position: relative;
background: hsl(220, 16%, 14%);
}
.highLite_colors,
.highLite_editable {
padding: 16px;
top: 0;
left: 0;
right: 0;
bottom: 0;
white-space: pre-wrap;
font-family: monospace;
font-size: 13px;
}
/* THE OVERLAYING CONTENTEDITABLE WITH TRANSPARENT TEXT */
.highLite_editable {
position: relative;
-webkit-text-fill-color: transparent; /* Chrome: make text transparent */
text-fill-color: transparent; /* One day, hopefully? */
color: hsl(100, 95%, 95%); /* But keep caret colored */
}
.highLite_editable:focus {
outline: 1px solid hsl(220, 16%, 19%);
}
/* THE UNDERLAYING ONE WITH HIGHLIGHT COLORS */
.highLite_colors {
position: absolute;
user-select: none;
}
.highLite_colors i {
font-style: normal;
}
/* JS */
i.js_quot { color: hsl( 50, 75%, 70%); }
i.js_decl { color: hsl(200, 75%, 70%); }
i.js_func { color: hsl(300, 75%, 70%); }
i.js_pare { color: hsl(210, 75%, 70%); }
i.js_squa { color: hsl(230, 75%, 70%); }
i.js_curl { color: hsl(250, 75%, 70%); }
i.js_numb { color: hsl(100, 75%, 70%); }
i.js_logi { color: hsl(200, 75%, 70%); }
i.js_equa { color: hsl(200, 75%, 70%); }
i.js_comm { color: hsl(200, 10%, 45%); font-style: italic; }
i.js_comm > * { color: inherit; }
/* HTML */
i.html_angl { color: hsl(200, 10%, 45%); }
i.html_tags { color: hsl( 0, 75%, 70%); }
i.html_attr { color: hsl(200, 74%, 70%); }
<h2>HTML</h2>
<div class="highLite">
<div class="highLite_colors"></div>
<div class="highLite_editable" data-lang="html"><h2 class="head">
TODO: HTML is for <b>homework</b>
</h2></div>
</div>
<h2>JAVASCRIPT</h2>
<div class="highLite">
<div class="highLite_colors"></div>
<div class="highLite_editable" data-lang="js">// Type some JavaScript here
const arr = ["high", "light"];
let n = 2.1 * 3;
if (n < 10) {
console.log(`${n} is <= than 10`);
}
function casual (str) {
str = str || "nonsense";
alert("Just a casual"+ str +", still many TODOs");
}
casual (arr.join('') +" idea!");
/**
* The code is a proof of concept and far from
* perfect. You should never use regex but create or use a parser.
* Meanwhile, play with it and improve it!
*/</div>
</div>
有了这个基本思想,我留给读者的一个简单的 TODO 是-当我们正在编辑的DIV收到滚动条时,使用JavaScript相应地更新同级DIV的滚动位置。