当选择一个文本块(可能跨越许多DOM节点)时,是否可以使用Javascript提取所选文本和节点?
想象一下这个HTML代码:
Hello World
Hi there!
如果用户发起了一个从"World ..."开始的mouseDown事件,然后是一个mouseUp甚至就在"那里!"之后,我希望它会返回:
Text : { selectedText: "WorldHi there!" }, Nodes: [ { node: "h1", offset: 6, length: 5 }, { node: "p", offset: 0, length: 16 }, { node: "p > b", offset: 0, length: 6 } ]
我已经尝试将HTML放入textarea但这只会让我获得selectedText.我没有尝试过该元素,但这可能是另一种选择.
如果不是JavaScript,有没有办法使用Firefox扩展?
你是一个颠簸的旅程,但这很有可能.主要问题是IE和W3C为选择提供了完全不同的接口,所以如果你想要跨浏览器功能,那么你基本上必须把整个事情写两次.此外,两个接口都缺少一些基本功能.
Mozilla开发人员连接有关于W3C选择的故事.Microsoft 在MSDN上记录了他们的系统.我建议从PPK的范围介绍开始.
以下是一些我认为有用的基本功能:
// selection objects will differ between browsers function getSelection () { return ( msie ) ? document.selection : ( window.getSelection || document.getSelection )(); } // range objects will differ between browsers function getRange () { return ( msie ) ? getSelection().createRange() : getSelection().getRangeAt( 0 ) } // abstract getting a parent container from a range function parentContainer ( range ) { return ( msie ) ? range.parentElement() : range.commonAncestorContainer; }
我的Rangy库将通过统一IE <9和所有其他主流浏览器中的不同API,并通过getNodes()
在其Range对象上提供一个函数来获得您的一部分:
function getSelectedNodes() { var selectedNodes = []; var sel = rangy.getSelection(); for (var i = 0; i < sel.rangeCount; ++i) { selectedNodes = selectedNodes.concat( sel.getRangeAt(i).getNodes() ); } return selectedNodes; }
在所有浏览器中获取所选文本都非常简单.在Rangy,它只是
var selectedText = rangy.getSelection().toString();
没有朗伊:
function getSelectedText() { var sel, text = ""; if (window.getSelection) { text = "" + window.getSelection(); } else if ( (sel = document.selection) && sel.type == "Text") { text = sel.createRange().text; } return text; }
对于字符偏移,您可以node
对选择中的任何节点执行类似的操作.请注意,这不一定代表文档中的可见文本,因为它不考虑折叠的空格,通过CSS隐藏的文本,通过CSS定位在正常文档流之外的文本,隐含的
和/块元素的换行符,以及其他细微之处.
var sel = rangy.getSelection(); var selRange = sel.getRangeAt(0); var rangePrecedingNode = rangy.createRange(); rangePrecedingNode.setStart(selRange.startContainer, selRange.startOffset); rangePrecedingNode.setEndBefore(node); var startIndex = rangePrecedingNode.toString().length; rangePrecedingNode.setEndAfter(node); var endIndex = rangePrecedingNode.toString().length; alert(startIndex + ", " + endIndex);