Dar*_*kkz 6 html javascript css rangy vue.js
我正在建立类似输入内容的可编辑div。您应该单击div外部的一些标签以将其添加到div中,同时也可以在所述标签周围输入内容。
我正在使用用户选择:none(正常和webkit)以防止选择标记按钮,因此失去了插入符号的位置。它可以在Firefox和Chrome中使用,但不能在Safari中使用(我知道-webkit-前缀并正在使用它)。
我的问题的根源是保持插入符号的位置,同时使内容可编辑div。
我以前曾尝试使用rangy,但在Firefox方面存在一些限制。从UX的角度来看,这些限制非常令人讨厌。您可以向我的用户选择检查我以前的问题以及如何将我带到这里:无解决方案- 当用Rangy保存其位置时,Caret在Firefox中消失了
这就是我采用用户选择的解决方案的方式:无。
我的组件/ JS:
new Vue({
el: "#app",
data(){
return {
filters_toggled: false,
fake_input_content: '',
input_length: 0,
typed: false,
boolean_buttons: [{
type: '1',
label: '?I',
tag: '?I',
img: 'https://i.imgur.com/feHin0S.png'
}, {
type: '2',
label: 'SAU',
tag: 'SAU',
img: 'https://i.imgur.com/vWJeJwb.png'
}, {
type: '3',
label: 'NU',
tag: 'NU',
img: 'https://i.imgur.com/NNg1spZ.png'
}],
saved_sel: 0,
value: null,
options: ['list', 'of', 'options']
}
},
name: 'boolean-input',
methods: {
inputLength($event){
this.input_length = $event.target.innerText.length;
if(this.input_length == 0)
this.typed = false;
},
addPlaceholder(){
if(this.input_length == 0 && this.typed == false){
this.$refs.divInput.innerHTML = 'Cuvinte cheie, cautare booleana..'
}
},
clearPlaceholder(){
if(this.input_length == 0 && this.typed == false){
this.$refs.divInput.innerHTML = '';
}
},
updateBooleanInput($event){
this.typed = true;
this.inputLength($event);
},
saveCursorLocation($event){
/*
if($event.which != 8){
if(this.saved_sel)
rangy.removeMarkers(this.saved_sel)
this.saved_sel = rangy.saveSelection();
}
*/
// if(this.input_length == 0 && this.typed == false){
// var div = this.$refs.divInput;
// var sel = rangy.getSelection();
// sel.collapse(div, 0);
// }
},
insertNode: function(node){
var selection = rangy.getSelection();
var range = selection.getRangeAt(0);
range.insertNode(node);
range.setStartAfter(node);
range.setEndAfter(node);
selection.removeAllRanges();
selection.addRange(range);
},
addBooleanTag($event){
// return this.$refs.ChatInput.insertEmoji($event.img);
if (!this.$refs.divInput.contains(document.activeElement)) {
this.$refs.divInput.focus();
}
console.log(this.input_length);
if(this.typed == false & this.input_length == 0){
this.$refs.divInput.innerHTML = ''
var space = '';
this.typed = true
//this.saveCursorLocation($event);
}
//rangy.restoreSelection(this.saved_sel);
console.log(getSelection().anchorNode, getSelection().anchorOffset, getSelection().focusNode, getSelection().focusOffset)
var node = document.createElement('img');
node.src = $event.img;
node.className = "boolean-button--img boolean-button--no-margin";
node.addEventListener('click', (event) => {
// event.currentTarget.node.setAttribute('contenteditable','false');
this.$refs.divInput.removeChild(node);
})
this.insertNode(node);
this.saveCursorLocation($event);
},
clearHtmlElem($event){
var i = 0;
var temp = $event.target.querySelectorAll("span, br");
if(temp.length > 0){
for(i = 0; i < temp.length; i++){
if(!temp[i].classList.contains('rangySelectionBoundary')){
if (temp[i].tagName == "br"){
temp[i].parentNode.removeChild(temp[i]);
} else {
temp[i].outerHTML = temp[i].innerHTML;
}
}
}
}
},
pasted($event){
$event.preventDefault();
var text = $event.clipboardData.getData('text/plain');
this.insert(document.createTextNode(text));
this.inputLength($event);
this.typed == true;
},
insert(node){
this.$refs.divInput.focus();
this.insertNode(node);
this.saveCursorLocation($event);
},
fixDelete(){
}
},
props: [ 'first'],
mounted() {
this.addPlaceholder()
}
})
Run Code Online (Sandbox Code Playgroud)
我的HTML
<div id="app">
<div class="input__label-wrap">
<span class="input__label">Cauta</span>
<div style="user-select: none; -webkit-user-select: none">
<span readonly v-on:click="addBooleanTag(b_button)" v-for="b_button in boolean_buttons" class="boolean-buttons">{{b_button.label}}</span>
</div>
</div>
<div class="input__boolean input__boolean--no-focus">
<div
@keydown.enter.prevent
@blur="addPlaceholder"
@keyup="saveCursorLocation($event); fixDelete(); clearHtmlElem($event);"
@input="updateBooleanInput($event); clearHtmlElem($event);"
@paste="pasted"
v-on:click="clearPlaceholder(); saveCursorLocation($event);"
class="input__boolean-content"
ref="divInput"
contenteditable="true">Cuvinte cheie, cautare booleana..</div>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
我的CSS
.filters__toggler
{
cursor: pointer;
padding: 2px;
transition: all 0.2s ease-in-out;
margin-left: 10px;
}
.filters__toggler path
{
fill: #314964;
}
.filters__toggler-collapsed
{
transform: rotate(-180deg);
}
.input__label
{
font-family: $roboto;
font-size: 14px;
color: #314964;
letter-spacing: -0.13px;
text-align: justify;
}
.input__boolean
{
width: 100%;
background: #FFFFFF;
border: 1px solid #AFB0C3;
border-radius: 5px;
padding: 7px 15px 7px;
font-family: $opensans;
font-size: 14px;
color: #082341;
min-height: 40px;
box-sizing: border-box;
margin-top: 15px;
display: flex;
flex-direction: row;
align-items: center;
line-height: 22px;
overflow: hidden;
}
.input__boolean-content
{
width: 100%;
height: 100%;
outline: none;
border: none;
position: relative;
padding: 0px;
word-break: break-word;
}
.input__boolean img
{
cursor: pointer;
margin-bottom: -6px;
}
.input__boolean--no-focus
{
color: #9A9AA6
}
.input__label-wrap
{
display: flex;
justify-content: space-between;
width: 100%;
position: relative;
}
.boolean-buttons
{
background-color: #007AFF;
padding: 3px 15px;
border-radius: 50px;
color: #fff;
font-family: $roboto;
font-size: 14px;
font-weight: 300;
cursor: pointer;
margin-left: 10px;
}
.boolean-button--img
{
height: 22px;
margin-left: 10px;
}
.boolean-button--no-margin
{
margin: 0;
}
.popper
{
background-color: $darkbg;
font-family: $opensans;
font-size: 12px;
line-height: 14px;
color: #fff;
padding: 4px 12px;
border-color: $darkbg;
box-shadow: 0 5px 12px 0 rgba(49,73,100,0.14);
border-radius: 8px;
}
.filters__helper
{
cursor: pointer;
margin-left: 10px;
margin-bottom: -3px;
}
.popper[x-placement^="top"] .popper__arrow
{
border-color: #082341 transparent transparent transparent;
}
Run Code Online (Sandbox Code Playgroud)
注意:忽略新的Vue,它是从Fiddle粘贴的。我建议使用小提琴来检查代码,重现问题。
在Safari(最新版本)中,如果我键入一个单词,然后单击该单词的某个位置,或者通过键盘箭头将该插入符号移动到该单词中,然后单击输入右侧的标签之一,则应在其中添加标签单击的单词的中间(在何处进行选择),但将其添加到单词的开头。
tl; dr:单击其中一个标签时,Safari不尊重插入符号的位置。它将标签添加到内容可编辑div的开头,而不是插入标记之前的位置。
小智 1
看来你自己基本上已经找到了答案。这是一个时间问题。
如果将事件更改为 mousedown,插入符号位置不会丢失,并且标签会插入到正确的位置。
<div id="app">
<div class="input__label-wrap">
<span class="input__label">Cauta</span>
<div style="user-select: none; -webkit-user-select: none">
<span readonly v-on:mousedown="addBooleanTag(b_button)" v-for="b_button in boolean_buttons" class="boolean-buttons">{{b_button.label}}</span>
</div>
</div>
<div class="input__boolean input__boolean--no-focus">
<div
@keydown.enter.prevent
@blur="addPlaceholder"
@keyup="saveCursorLocation($event); fixDelete(); clearHtmlElem($event);"
@input="updateBooleanInput($event); clearHtmlElem($event);"
@paste="pasted"
v-on:click="clearPlaceholder(); saveCursorLocation($event);"
class="input__boolean-content"
ref="divInput"
contenteditable="true">Cuvinte cheie, cautare booleana..</div>
</div>
</div>Run Code Online (Sandbox Code Playgroud)
https://jsfiddle.net/xmuzp20o/
如果您不想在 mousedown 上添加实际标签,那么您至少可以在该事件中保存插入符位置,以便在单击事件中仍然拥有正确的位置。
| 归档时间: |
|
| 查看次数: |
230 次 |
| 最近记录: |