2017-03-07 30 views
3

我想創建一個熒光筆工具,它的工作原理是這樣的:更換HTML,然後添加一個文件片段回HTML

  • 用戶首先選擇的文本範圍。
  • 他們然後單擊顏色按鈕之一,所選文本的背景突出
  • 然後,他們選擇文本的另一個範圍...
  • 現在,當他們按一下按鈕所有的HTML被替換爲緩存版本的HTML(沒有亮點)
  • 然後,新突出顯示的新選定文本會被附加到新鮮的html中。

這樣一次只能突出顯示一個文本範圍。

問題:

我有一個很難理解的RangeSelectionNode API的

目前,我不能添加突出顯示的文本回新鮮的HTML ...我我只是將它附加到document.body。

我到目前爲止有:

https://jsfiddle.net/4mb39jd6/

(function(){ 

    var highlighter = { 

    /** 
    * 
    */ 
    init: function(){ 
     this.cacheDOM(); 
     this.bindEvents(); 
    }, 

    /** 
    * 
    */ 
    cacheDOM: function(){ 
     this.$html   = $('.content').html(); 
     this.$content  = $('.content'); 
     this.$highlighter = $('.highlighter'); 
    }, 

    /** 
    * 
    */ 
    bindEvents: function(){ 
     this.$highlighter.on('mousedown', this.highlightSelection.bind(this)); 
    }, 

    /** 
    * 
    */ 
    highlightSelection: function(e){ 

     var selection = window.getSelection();   // get selection 
     var text  = selection.toString();   // get selected text 
     var newNode = document.createElement('span'); // create node 

     newNode.style.backgroundColor = $(e.target).css('backgroundColor'); // set node properties 
     newNode.appendChild(document.createTextNode(text));     // append selection text to node 

     var range = selection.getRangeAt(0);  // 2 - get the selected range 
     range.deleteContents();     // delete the contents 
     range.insertNode(newNode);    // insert the new node with the replacement text 
     documentFragment = range.cloneContents(); // clone the node 

     this.$content.html(this.$html);    // refresh the content 
     document.body.appendChild(documentFragment); // add the new highlighted text 
    }, 
    }; 
    highlighter.init(); 

})(); 

問:

如何添加我的強調點......它看起來像這樣<span style="background-color: rgb(255, 255, 131);">some random text</span>回成新的html文檔,以便它處於相同的位置。

+0

任何具體的原因,你要克隆的全部內容? 'highlightSection'中最後三行的註釋似乎產生了所需的行爲... https://jsfiddle.net/wxrxf6r1/ – user3297291

+0

是的,原因是我只想在任何一個給定時刻選擇一段文本。 ..因爲它是我可以突出各地...我只想要能夠一次選擇一個範圍。 –

+1

你有沒有看過[mark.js](https://markjs.io/)? – dude

回答

1

如果目標是在一次只有一個亮點,我會去一個不太複雜的方法是:

  • 當增加一個亮點,
  • 檢查HTML前一個亮點,發現

時要做到這一點,你的標記彰顯<span> s的屬性或類(或更好,但存儲參考)

  • 刪除它:

    newNode.classList.add("js-highlight"); 
    

    添加一個方法來刪除這樣的元素:

    clearHighlight: function() { 
        var selection = document.querySelector(".js-highlight"); 
    
        if (selection) { 
        selection.parentElement.replaceChild(
         document.createTextNode(selection.innerText), 
         selection 
        ); 
        } 
    } 
    

    然後,更換前你range與突出顯示元素,稱之爲clearHighlight

    例子:https://jsfiddle.net/2tqdLfb1/

    一種替代方案:

    我也嘗試另一種方法是尊重你的 「緩存HTML」 的邏輯,卻發現它被過於複雜。該方法的基礎:

    • 檢查選擇
    • 商店開始索引和選擇
    • 的結束索引的parentElement查詢路徑通過緩存HTML字符串替換HTML
    • 通過存儲的查詢路徑查找新選中的選定父元素
    • 根據選擇開始和結束索引將其分成1,2或3個textNodes
    • 替換你的亮點表示選擇textNode <span>

    ,告訴您如何可以存儲你的範圍祖先查詢路徑的一個例子:

    function getPathUpToSelector(selector, element, path) { 
        var parent = element.parentElement; 
    
        if (parent && !element.matches(selector)) { 
        var index = Array.from(parent.children).indexOf(element) + 1; 
        path.push("*:nth-child(" + index + ")"); 
    
        return getPathUpToSelector(selector, parent, path); 
        } 
    
        return [selector].concat(path).join(" > "); 
    } 
    
  • +0

    謝謝!這是太棒了。我過於複雜的事情,這很好。現在唯一的問題是,如果我在兩個節點上選擇文本,那麼HTML標記將被銷燬......我在這裏開始了一個新問題:http://stackoverflow.com/questions/42656501/serializing-html-placing-span-elements -around選擇的文本,同時保留個 –