我正在构建一个programmable calculator,它使用一个contenteditable div作为输入您需要评估的表达式的位置。 div侦听用户敲击返回键,然后将其文本内容传递给计算器引擎,清除自身,然后显示表达式的结果。
一切都在桌面浏览器上按预期工作,但在移动浏览器下,当插入符号不在文本末尾时按下返回键时会有一些奇怪的行为。有时点击返回键会插入一个空格或换行符,有时它会在插入符号之前提交并清除所有内容,而在Chrome下它似乎会创建一个新的div元素。我有什么想法吗?
我已经成功测试了在Ubuntu 17.10上运行的Firefox 59.0.2和Chromium 65.0.3325.181以及在Windows 7上运行的Firefox 59.0.2中的代码。我在Firefox 59.0.2和Chrome 65.0.3325.109中测试代码失败了在Android 8.1.0上运行。
window.addEventListener("load", function () {
"use strict";
var i = document.getElementById("i");
var o = document.getElementById("o");
i.addEventListener("keypress", function (e) {
if (e.key === "Enter") {
e.preventDefault();
o.textContent = i.textContent;
i.textContent = "";
return false;
}
return true;
});
});
div {
font-size: 24px;
padding: 1em;
border: 1px solid black;
min-height: 1em;
box-sizing: content-box;
margin: 1em;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=0">
<title>Test</title>
</head>
<body>
<div id="i" contenteditable="true"></div>
<div id="o"></div>
</body>
</html>
修改
经过一些工作,我做了另一种检测输入,复制文本和清除方框的方法。它不再监听击键,而是监视盒子本身的变化。它适用于桌面,但在移动设备上以类似方式失败。它还有一个额外的问题,如果你键入太快,它将崩溃Firefox手机。我在以前的浏览器上测试过代码。
window.addEventListener("load", function () {
"use strict";
var i = document.getElementById("i");
var o = document.getElementById("o");
var getText;
var input;
getText = function (e) {
var s = [];
e.childNodes.forEach(function (n) { // get every child
switch (n.nodeType) {
case 1: // element, so recurse
s.push(getText(n));
break;
case 3: // text
s.push(n.nodeValue);
break;
}
});
return s.join("");
};
input = function (e) {
if (i.childNodes.length > 1 || (i.firstChild && i.firstChild.nodeType != 3)) { // checking for added <br />
e.preventDefault();
o.textContent = getText(i);
while (i.firstChild) { // clear element
i.removeChild(i.firstChild);
}
// add and remove listener to prevent event from firing on clear
i.removeEventListener("input", input);
setTimeout(function () {
i.addEventListener("input", input, true);
}, 100);
return false;
}
return true;
};
i.addEventListener("input", input, true);
});
div {
font-size: 24px;
padding: 1em;
border: 1px solid black;
min-height: 1em;
box-sizing: content-box;
margin: 1em;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=0">
<title>Test</title>
</head>
<body>
<div id="i" contenteditable="true"></div>
<div id="o"></div>
</body>
</html>
编辑2(含解决方法):
经过一番思考后,我意识到我不需要使用一个有意义的div,所以我重新使用它来使用一个正常工作的样式文本输入字段。
window.addEventListener("load", function () {
"use strict";
var f = document.getElementById("f");
var i = document.getElementById("i");
var o = document.getElementById("o");
f.addEventListener("submit", function (e) {
e.preventDefault();
o.textContent = i.value;
i.value = "";
return false;
});
});
input[type="text"] {
display: block;
width: 100%;
overflow: auto;
outline: none;
border: none;
border-radius: 0;
box-shadow: none;
box-sizing: content-box;
}
#i, div {
width: calc(100% - 4em - 2px);
min-height: 1em;
font-size: 24px;
padding: 1em;
border: 1px solid black;
min-height: 1em;
margin: 1em;
color: black;
font-family: serif;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=0">
<title>Test</title>
</head>
<body>
<form id="f" name="f">
<input id="i" name="i" type="text" >
</form>
<div id="o"></div>
</body>
</html>