簡體   English   中英

在使用Rangy保存位置時,Caret在Firefox中消失了

[英]Caret disappears in Firefox when saving its position with Rangy

這只發生在Firefox中。

重要提示:我使用rangy.saveSelection()保存插入符號的位置:

  • 單擊內容可編輯div時
  • 在keyup上
  • 將外部html元素(作為節點)添加到內容可編輯div時

我需要通過多種方式不斷保存的位置,以便能夠在點擊時插入html元素(我有一些標簽)。

當我點擊contentEditable div並且div為空(第一個焦點,讓我們說)時,除非我開始輸入,否則我看不到插入符號。 如果插入符號在最后,我也看不到它。

另一個奇怪的行為是我無法使用箭頭在contentEditable 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>

我的方法/功能

            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);
                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);

                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);
            },

正如您在saveCursorLocation()中看到的那樣,我試圖解決您在contentEditable div中單擊的情況,並且沒有插入符號 - 這對用戶來說很困惑。

                // if(this.input_length == 0 && this.typed == false){
                //  var div = this.$refs.divInput;
                //  var sel = rangy.getSelection();
                //  sel.collapse(div, 0);
                // }

這是一個死胡同 - 很可能是因為我對Rangy的理解不足以及我應該如何使用這些功能。

預期的行為與Firefox上的實際結果

當我點擊contentEditable div時,我希望出現插入符號(在后台保存我的位置)。 鍵入時,我希望插入符號出現在最后一個鍵入的字符之后,同時也在鍵盤上顯示以保存插入符號的位置。 此外,我希望能夠通過左/右箭頭導航文本,並在執行此操作時查看插入符號。

所有這些都是由...生成的

v-on:click="..... saveCursorLocation($event);"

@keyup="saveCursorLocation($event);....."

如果有人認為它會有所幫助,我可以在Firefox中記錄內容可編輯div及其行為。

編輯:我設法隔離問題,並將其重現為JSFiddle - https://jsfiddle.net/Darkkz/6Landbj5/13

要找什么?

  • 在Firefox中打開小提琴鏈接,然后按下其中一個藍色按鈕(SI,SAU,NU),然后查看輸入,不顯示插入符號。
  • 單擊輸入,不顯示插入符號
  • 輸入輸入時,不顯示插入符號。 雖然,如果單擊內容之間的單詞/中,將顯示插入符號

顯然,rangy的選擇保存和恢復模塊不能用於跟蹤當前選擇,同時用戶可以像您想要的那樣與contenteditable交互。

我深入研究了一下,問題是rangy將隱藏的<span> s作為標記插入,並將選擇更新為標記之后 ,而不是將其保留在用戶編輯的#text節點內:

 <div contenteditable>
    #text [This is something I typed <!-- selection is moved from here -->] 
    <span class="rangySelectionBoundary"/>
    <!-- to here -->
 </div>

在這種情況下,Firefox無法顯示插入符號(我沒有發現有關此特定問題的錯誤,但是這里有一個類似的選項,當選擇在兩個<span>之間時不顯示插入符號 )。

評論這個代碼似乎解決了消失的插入符號的問題。 我不清楚為什么需要這個代碼 - 它在1.0之前在大型提交中添加,其消息說: “修復了控制范圍和多個范圍選擇的保存/恢復問題。為保存/恢復和CSS類應用程序添加了演示模塊“。 - 所以我不建議在rangy中修復它(並且由於它幾年沒有維護,我沒有太多的希望得到它的作者的輸入)。

所以我試圖弄清楚為什么你首先需要這個,建議不涉及rangy.saveSelection其他解決方案(例如,rangy的Text Range模塊提供了getSelection().saveCharacterRanges(containerNode) ,它可以在不修改DOM的情況下工作。

看來你有一個<div contenteditable>和一些“按鈕”( <span> s),點擊它會在插入位置插入一些HTML。 您試圖解決的問題是,當單擊“按鈕”時,選擇從“ contenteditable移動到按鈕,您無法檢測到插入位置。

您可以使user-select: none - 而不是存儲和恢復選擇,這將使插入符號保持在滿足。

為了測試這個,我注釋掉了對rangy.saveSelectionrangy.restoreSelection所有引用並更改了this.$refs.divInput.focus(); 調用“按鈕”的onclick處理程序,只有當contenteditable尚未通過將其包裝在if (!this.$refs.divInput.contains(document.activeElement)) 看看這個如何在這個更新的小提琴中工作:
https://jsfiddle.net/fjxsgvm2/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM