键入时要替换contenteditable框中的内容? [英] Replacing content in contenteditable box while typing?

查看:46
本文介绍了键入时要替换contenteditable框中的内容?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个内容可编辑的div,我希望用户输入.当用户使用onkeyup在框中键入内容时,我会激活一个功能,该功能可以更改某些字符的颜色:

I have a contenteditable div I want users to type in. When users type inside the box with onkeyup, I activate a function that changes the color of certain characters:

var lTags = fixedCode.innerHTML.replace(/&lt;/gi, "<span style='color:gold;'>&lt;</span>");
var rTags = lTags.replace(/&gt;/gi, "<span style='color:gold'>&gt;</span>");
fixedCode.innerHTML = rTags;

此代码的作用是需要每一个<符号和每个>符号,然后将其变成金色.但是,当我这样做时,由于在每次按下键时该框都会自动刷新,因此我不再能够在contenteditable框中键入单词.

What this code does is it takes every < sign and every > sign and turns it into a gold color. However, when I do this, I am no longer able to type words into the contenteditable box since the box refreshes itself every time I press a key.

function checkIt(code) {
   var fixedCode = document.getElementById(code);
   var lTags = fixedCode.innerHTML.replace(/&lt;/gi, "<span style='color:gold;'>&lt;</span>");
   var rTags = lTags.replace(/&gt;/gi, "<span style='color:gold'>&gt;</span>");
   fixedCode.innerHTML = rTags;
}

<div id="box" contenteditable="true" onkeyup="checkIt(this.id);">See for yourself</div>

要亲自查看,请尝试在框中键入任何HTML标记. 首先,为什么它会更改标签左侧<而不是右侧标签>的颜色?以及如何在不删除变色材料的情况下在框内输入内容.我见过类似的问题,但答案是Jquery. 我不想使用JQUERY!

To see for yourself, try typing any HTML tag in the box. First of all, why does it change the color of the left < of a tag but not the right part of the tag >? And how can I actually type inside the box without deleting the color-changing stuff. I've seen similar questions, but the answers were Jquery. I do not want to use JQUERY!

推荐答案

此示例当前将在Chrome中运行 ...,但是想出一种方法,即使文本是透明的,也可以使插入符号可见-在其他浏览器上,一切都很好.

This example will currently work in Chrome... but figure out a way to make the caret visible even if the text is transparent - on other browsers, and you're good to go.

所以我懒得 hardcore-JS ,一个让我大吃一惊的想法是使用

So I was too lazy to hardcore-JS and one idea that popped my mind was to use

  • 两个重叠的DIV元素
  • 重叠的内容可编辑具有透明文本,但可见的插入符号
  • 底层DIV可以显示替换后的彩色内容:
  • two overlaying DIV elements
  • The overlaying contenteditable has transparent text but visible caret!
  • The underlaying DIV is the one that shows your replaced colorful stuff:

关于此技术的一个好的方面是,您始终(在可内容编辑的DIV中)保留要替换的内容的未更改版本!
不好的一面是,在每次击键时,您都会再次解析相同的内容-随着替换列表的增加,它会变得越来越大,而性能却越来越高.

One good side about this technique is that you always keep (in the contenteditable DIV) the unchanged version of the content to be replaced!
The not-so-good side is that on every keystroke you parse all over again the same content - and as it gets bigger might be a performance killer as your replacement list grows O(n).

有关优化的详细信息,请访问

For a beautiful read on optimization head to VSCode Optimizations in Syntax Highlighting

function highLite(el) {
  el.previousElementSibling.innerHTML = el.innerHTML
     .replace(/(&lt;|&gt;)/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 &lt; &gt; 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: /(`|'|"|&#39;|&#34;)/g,
    comm: /((\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\/)|(\/\/.*))/g,
    logi: /(%=|%|\-|\+|\*|&amp;{1,2}|\|{1,2}|&lt;=|&gt;=|&lt;|&gt;|!={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: /(?<=&lt;(?:\/)?)(\w+)(?=\s|\&gt;)/g,
    angl: /(&lt;\/?|&gt;)/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">&lt;h2 class="head"&gt;
TODO: HTML is for &lt;b&gt;homework&lt;/b&gt;
&lt;/h2&gt;</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 &lt; 10) {
  console.log(`${n} is &lt;&#61; 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的滚动位置.

given this basic idea, a simple TODO I left for the reader is to - when the DIV we're editing receives scrollbars, update accordingly the scroll position for the sibling DIV using JavaScript.

这篇关于键入时要替换contenteditable框中的内容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆