我正在尝试使 textarea 看起来像密码字段。在 webkit 浏览器中,我找到了以下属性来制作它
-webkit-text-security : circle
但它不适用于其他浏览器。任何跨浏览器的替代品...?
我正在尝试使 textarea 看起来像密码字段。在 webkit 浏览器中,我找到了以下属性来制作它
-webkit-text-security : circle
但它不适用于其他浏览器。任何跨浏览器的替代品...?
您可以为此使用 JS,定义一个变量并在其中存储 textarea 值,并用任何特殊字符替换 textarea 中的内容。您将在 JS 变量中有实际值,可用于提交表单或验证等。
为此,您可以为keydown
事件编写一个函数。
您可以使用 jQuery 插件,例如:http ://blog.decaf.de/2009/07/iphone-like-password-fields-using-jquery/
可以做到,但实现起来并不简单。这个想法是使用不可见的password=true
输入元素作为您的文本区域的密码屏蔽版本的状态/代理,并使用 JS 在显示/隐藏时将密码屏蔽(假)文本区域与真实文本区域切换。
不幸的是,这很快就变得丑陋了。一个普通的密码字段还允许在中间进行修改、复制剪切粘贴、拖放以及可能其他我想不到的行为。忠实地模仿所有这些,即使可能,也可能不值得麻烦。
我的实现通过在密码屏蔽(假)文本区域中通过单击或箭头键以编程方式禁用文本导航来避免这种复杂性。然而,真正的文本区域可以在其中导航和编辑,因此在 UX 方面几乎没有丢失。
在下面查看我的实现:
// element handles
const inp = document.getElementById("input-el");
const fta = document.getElementById("fake-textarea-el");
const ftac = document.getElementById("fake-textarea-el-content");
const rta = document.getElementById("real-textarea-el");
const toggle = document.getElementById("pw-toggle");
// initial text element height
const initialHeightPx = fta.clientHeight + 'px';
// show/hide content flag
let hideContent = true;
// util for minimum textarea height workaround
function textWidth(text) {
const tag = document.createElement('div');
tag.classList.add('hidden');
tag.style.whiteSpace = 'nowrap';
tag.innerHTML = text;
document.body.appendChild(tag);
const result = tag.clientWidth;
document.body.removeChild(tag);
return result;
}
function setTextArea(content = '') {
// update all text elements
ftac.innerHTML = content.replace(/./g, '•');
inp.value = content;
rta.value = content;
// workaround to use CSS height for minimum
// textarea height
let newHeight = initialHeightPx;
if (textWidth(content) > rta.clientWidth) {
rta.style.height = 'auto';
newHeight = rta.scrollHeight + 'px';
}
rta.style.height = newHeight;
}
function handleInput(e) {
const {target: {value}} = e;
setTextArea(value);
}
inp.oninput = handleInput;
rta.oninput = handleInput;
fta.onfocus = e => {
inp.focus();
fta.classList.add('has-focus');
ftac.classList.remove('has-selectall');
}
inp.onblur = e => {
// deselect input contents
inp.selectionStart = inp.selectionEnd = -1;
fta.classList.remove('has-focus');
ftac.classList.remove('has-selectall');
}
inp.onkeydown = e => {
const {charCode, keyCode, target: {value}} = e;
const code = keyCode || charCode;
// prevent arrow keys
if (code >= 37 && code <= 40) {
e.preventDefault();
}
// handle ctrl/meta key combinations
if ((e.metaKey || e.ctrlKey)) {
switch (e.key) {
case 'a':
e.preventDefault();
inp.setSelectionRange(0, inp.value.length)
fta.classList.remove('has-focus');
ftac.classList.add('has-selectall');
break;
default:
}
} else if (ftac.classList.contains('has-selectall')) {
fta.classList.add('has-focus');
ftac.classList.remove('has-selectall');
}
}
// handle show/hide toggle
toggle.onclick = e => {
hideContent = !hideContent;
if (hideContent) {
rta.classList.add('hidden');
fta.classList.remove('hidden');
toggle.innerHTML = 'Show';
} else {
fta.classList.add('hidden');
rta.classList.remove('hidden');
toggle.innerHTML = 'Hide';
}
}
/* SETUP BEGIN */
* {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}
main {
align-items: center;
display: flex;
height: 100vh;
justify-content: center;
}
button {
height: 24px;
margin: 18px;
width: 60px;
}
/* SETUP END */
#fake-textarea-el, #real-textarea-el {
border: none; /* remove user-agent textarea border */
box-shadow: 0 0 0 1px black;
box-sizing: border-box;
display: block;
height: 24px;
line-height: 18px;
margin: 0;
padding: 2px;
resize: none;
width: 150px;
word-wrap: break-word;
}
#fake-textarea-el {
height: auto;
min-height: 24px;
}
.hidden {
position: absolute;
bottom: 0px;
z-index: -1000;
opacity: 0;
pointer-events: none;
}
.has-selectall {
/* default selection bg on MacOS + Chrome */
background: #ACCEF7;
}
.cursor {
border-right: 1px solid transparent;
height: 1rem;
}
.has-focus .cursor {
animation: cursorBlink 1.14s forwards infinite;
}
@keyframes cursorBlink {
0% {
border-color: transparent;
}
50% {
border-color: transparent;
}
51% {
border-color: black;
}
100% {
border-color: black;
}
}
<main>
<input id="input-el" class="hidden" type="password" />
<div id="fake-textarea-el" contenteditable>
<span id="fake-textarea-el-content"></span><span class="cursor"></span>
</div>
<textarea id="real-textarea-el" class="hidden"></textarea>
<button id="pw-toggle">Show</button>
</main>