Range
對象和document.execCommand
可以操作的選擇很容易地。你的情況的主要問題是以文本格式保存範圍對象。
基本上你需要的是獲得startContainer
,startOffset
,endContainer
和endOffset
,它們是創建Range對象所需的值。 Offsets
是數字,所以它非常簡單。容器是節點,你不能直接保存爲字符串,所以這是主要問題。你可以做的一件事是添加鍵到你的DOM並保存密鑰。但是,由於範圍容器是文本節點,因此您需要保存文本節點的索引。這樣的事情應該讓來標記鍵的DOM,使用遞歸函數:
function addKey(element) {
if (element.children.length > 0) {
Array.prototype.forEach.call(element.children, function(each, i) {
each.dataset.key = key++;
addKey(each)
});
}
};
addKey(document.body);
一旦做到這一點,你可以範圍對象轉換爲一個對象,你可以保存爲一個字符串。像這樣:
function rangeToObj(range) {
return {
startKey: range.startContainer.parentNode.dataset.key,
startTextIndex: Array.prototype.indexOf.call(range.startContainer.parentNode.childNodes, range.startContainer),
endKey: range.endContainer.parentNode.dataset.key,
endTextIndex: Array.prototype.indexOf.call(range.endContainer.parentNode.childNodes, range.endContainer),
startOffset: range.startOffset,
endOffset: range.endOffset
}
}
使用此功能,您可以將用戶創建的每個選擇保存到數組中。像這樣:
document.getElementById('textToSelect').addEventListener('mouseup', function(e) {
if (confirm('highlight?')) {
var range = document.getSelection().getRangeAt(0);
selectArray.push(rangeToObj(range));
document.execCommand('hiliteColor', false, 'yellow')
}
});
要保存高亮區,請將每個對象保存爲JSON。爲了測試這個,你可以從你的範圍對象數組中獲取JSON字符串。像這樣的(這是在頂部使用get Seletion按鈕):
document.getElementById('getSelectionString').addEventListener('click', function() {
alert('Copy string to save selections: ' + JSON.stringify(selectArray));
});
然後裝入空的HTML時,您可以使用,這將創建一個從你的JSON保存的對象範圍內的逆轉。像這樣:
function objToRange(rangeStr) {
range = document.createRange();
range.setStart(document.querySelector('[data-key="' + rangeStr.startKey + '"]').childNodes[rangeStr.startTextIndex], rangeStr.startOffset);
range.setEnd(document.querySelector('[data-key="' + rangeStr.endKey + '"]').childNodes[rangeStr.endTextIndex], rangeStr.endOffset);
return range;
}
因此,您可以將字符串中的範圍數組轉換爲對象,然後將其轉換爲可添加的Range對象。然後使用execCommand,設置一些格式。
document.getElementById('setSelection').addEventListener('click', function() {
var selStr = prompt('Paste string');
var selArr = JSON.parse(selStr);
var sel = getSelection();
selArr.forEach(function(each) {
sel.removeAllRanges();
sel.addRange(objToRange(each));
document.execCommand('hiliteColor', false, 'yellow')
})
});
參見:https://jsfiddle.net/sek4tr2f/3/
注意,有些情況下,這將無法正常工作的情況下,主要是這樣的(這是在頂部使用組選擇按鈕,刷新小提琴之後做到這一點)有問題的情況是用戶在已經突出顯示的內容中選擇了內容。這些情況可以處理,但您需要更多條件。
你爲什麼不救突出顯示的單詞的數組索引,並且它們的長度? –
我同意@mohammedessam,創建一個數組,以便突出'xyz'的用戶將數組添加'xyz',並且還會包含一個索引來指示'xyz'的具體實例是什麼(即如果它是第3個'xyz'的實例,那麼索引將是3. – tamak
我懷疑'innerHTML.indexOf(text)'會傳遞任何東西,更不用說索引了。'ReferenceError'更可能。 – KooiInc