2012-01-31 2 views
4

Я пишу расширение Chrome, и мне нужно передать значение, которое пользователь выбрал на веб-сайте, на мой сервер. Я использую код window.getSelection(), который возвращает объект диапазона. Я использую JSON, чтобы передать объект диапазона обратно на мой сервер, но он не работает. Я новичок в этом, но я думаю, что проблема заключается в том, что вы можете передавать только текст с помощью JSON, а объект диапазона включает в себя как структуру DOM (которая не является текстом), так и фактический выбор текста (который является текстом) , Я прав? Есть ли альтернатива?Объект диапазона с JSON

var selection = window.getSelection(); 
$.getJSON(url, {data:selection}, function(moot) { 
    alert("done"); 
}); 

ответ

4

Простым обходным путем является не сериализация и отправка всего объекта, а для сохранения начального и конечного значений nts как XPaths (вместе с их смещениями). Что-то вроде этого будет делать:

function makeXPath (node, currentPath) { 
    /* this should suffice in HTML documents for selectable nodes, XML with namespaces needs more code */ 
    currentPath = currentPath || ''; 
    switch (node.nodeType) { 
    case 3: 
    case 4: 
     return makeXPath(node.parentNode, 'text()[' + (document.evaluate('preceding-sibling::text()', node, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotLength + 1) + ']'); 
    case 1: 
     return makeXPath(node.parentNode, node.nodeName + '[' + (document.evaluate('preceding-sibling::' + node.nodeName, node, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotLength + 1) + ']' + (currentPath ? '/' + currentPath : '')); 
    case 9: 
     return '/' + currentPath; 
    default: 
     return ''; 
    } 
} 

function restoreSelection() { 
     var selection = window.getSelection(); 
     selection.removeAllRanges(); 
     var range = document.createRange(); 
     range.setStart(document.evaluate(selectionDetails[0], document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue, Number(selectionDetails[1])); 
     range.setEnd(document.evaluate(selectionDetails[2], document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue, Number(selectionDetails[3])); 
     selection.addRange(range); 
    } 
} 

function getSelection() { 
    var selection = window.getSelection(); 
    var range = selection.getRangeAt(0); 
    var selectObj = { 
     'startXPath': makeXPath(range.startContainer), 
     'startOffset': range.startOffset, 
     'endXPath': makeXPath(range.endContainer), 
     'endOffset': range.endOffset 
    } 

    return selectObj 
} 

Не тщательно протестирован, но общая идея здесь.

Источники: This и That

0

Вы попробовали window.getSelection().toString()? Это должно получить только текстовое значение само по себе.

MDN в настоящее время вниз, но вы можете проверить документацию DOMSelection там: https://developer.mozilla.org/En/DOM/Selection

EDIT

Вы также можете попробовать использовать anchorNode и focusNode свойства, чтобы захватить узлы, в которых начинается отбор и останавливается. Если вам действительно нужен необработанный html, вы можете сделать что-то вроде focusNode.parentNode.outerHTML, чтобы получить весь блок (похоже, вы не можете делать externalHTML на фокусе или anchorNodes напрямую).

т.е.

var selection = window.getSelection(); 
var payload = { 
    selectedText: selection.toString(), 
    startHTML: selection.anchorNode.parentNode.outerHTML, 
    endHTML: selection.focusNode.parentNode.outerHTML 
} 

, а затем разобрать его на другой стороне. Вы также можете очистить другую информацию от узлов, чтобы вам не пришлось передавать целые строки html через провод.

+0

Я не пробовал .ToString() еще. Я попробую это немного. Я обеспокоен тем, что мне нужно сохранить структуру DOM, поскольку я буду использовать этот выбор позже. – Jon

+0

Я дал .toString() попытку, и она действительно вернула только текстовое значение сама по себе :) То, что мне было нужно, также является структурой DOM. Причина этого в том, что мне нужно будет отобразить текст, который пользователь выделил позже, и единственный способ, которым я решил, как это сделать, - найти текст с помощью структуры DOM. – Jon

+0

Вы также можете попробовать использовать свойства anchorNode и focusNode. Я обновлю ответ. – Gopherkhan

0

Если вам нужно отправить выбранные пользователем на странице

var selection = window.getSelection(); 

for(i=0;i<selection.rangeCount;i++) 
a[i]=selection.getRangeAt(i); 

$.getJSON(url, {data:a.toString()}, function(moot) { 
    alert("done"); 
}); 

Примечание: вместо toString(), вы можете использовать join('<separator>'), а на основе ваших потребностей

Использование window.getSelection().toString() бы объединить все выборы без сепаратора

Смежные вопросы