2014-12-22 59 views
3

我有一个Web应用程序,单击HTML中的任何节点后,需要检索其父节点的childNodes数组中的该节点的索引。但是,我无法通过onclick事件获取当前选定的节点。该事件的返回目标是元素中包含的element而不是具体的node获取HTML节点(不一定是元素)在点击

<div>This is Node 1<span>node 2</span>, node 3, and <span>node 4</span></div> 

如果你点击了跨度为节点2或节点4,它是直接地知道你在哪里:当存在文本节点,如这种差异是很重要的。但是,如果您单击节点1和节点3的文本,我似乎无法找到事件将帮助您确定哪些部分实际内容被点击的位置。

这种情况很重要,因为后面的操作需要检查文档中的某些属性,无论是前进还是后退,直到第一次匹配。所以,如果节点2和节点4都是匹配的搜索,我需要知道我是否在节点1或节点3中,以便知道哪一个返回。例如,如果向右搜索,则从节点1开始意味着应该返回节点2,并且从节点3开始意味着应该返回节点4。显然,这是一个简化,但它表明了这个问题。有谁知道这个标准的解决方案?如果我能得到节点对象或索引,那应该就足够了。 jquery很好,但没有必要。

+0

在得到这个问题之后,在摆弄这段时间和一段时间之后,似乎jquery onclick事件可能通过以下方式获得了此信息:event.originalEvent.explicitOriginalTarget。但是,我不确定是否有人使用此目的。 – Namey

+0

到目前为止,这实际上看起来可能会起作用,尽管我目前只在FireFox上进行了测试。跨浏览器兼容性的任何输入都是有价值的。 – Namey

+0

我正在查看chrome dev工具中的event.originalEvent,但看不到任何东西。只是再次检查,它绝对不存在于Chrome中(google-chrome for linux,build 36.0.1985.125) –

回答

0

你需要让你的节点在一些容器中。如果您点击“节点1”文本,功能将返回您一个<div>元素。但是,如果你想改变这个你代码:

<div> 
    <span>This is Node 1</span> 
    <span>node 2</span> 
    <span>, node 3, and </span> 
    <span>node 4</span> 
</div> 

它会工作,并返回<span>容器。我认为不可能以其他方式。

您最终可以制作一些JavaScript split()或正则表达式操作。

+0

不幸的是,由于底层HTML的任意性质,不可能以这种方式来包装它。具有讽刺意味的是,我也正在取代一些依赖非常脆弱的正则表达式来执行类似工作的东西。它打破了很多时间。 – Namey

+0

你会对此说什么:http://jsfiddle.net/huqzm6c4/? –

+0

不幸的是,这个HTML是可以直接编辑的,最终被保存起来,然后在其他地方使用。每个使用该方法添加的跨度稍后都需要被剥离(但不会删除任何其他跨度)。我通过使用webcomponents.js声明自己的跨度子类型来研究这个问题,但它确实很笨重,并且会成为一个需要维护的问题。 – Namey

0

如果你只是试图找出你点击的元素的文本,减去子节点的文本,我有一个解决办法:

$('body').on('click', function(e) { 
    alert('Node Text: '+$(e.target).clone().children().remove().end().text()); 
}); 

http://jsfiddle.net/xoegujqu/1/

从本质上讲,委托点击事件您希望为此运行的最高级别元素(在此示例中,它只是使用body,但您可能希望更具体)。使用$(e.target)来获取实际点击的元素,.clone()克隆它,以便在不影响实际页面内容的情况下修改它,.children().remove()删除所有它的后代元素,.end()返回到先前的jQuery选择器对象,然后最后.text()获取剩余的文字内容。

+0

不幸的是,我需要知道实际的元素引用或索引本身,而不仅仅是文本。 – Namey

+0

然后只是函数体内的'$(e.target)':) 编辑:没关系 - 我看你在你的问题中提到过。 –

+0

我可以问你的用例是什么吗?这可能有助于我们提供一种不同的方法。 –

0

这是不可能做到这一点,据我所知。您不能:

  1. 检测文本节点上的事件。
  2. 检测文本节点相对于窗口或页面的位置。

This answer给出了一些很好的见解,但没有做你想做的事情(返回节点的索引)。

我相信你运气不好,除非你能找到一种方法来使用上面的解决方案来确定索引。

+0

呃。我当然希望这不是唯一的解决方案,尽管这是可能的。该路径下的解决方案是:1)将每个字符包括在一个跨度中,2)找到所点击的一个的索引,3)找出父元素中每个节点的边界索引,4)报告索引落入哪个bin 。可能,虽然非常扭曲。 – Namey

+0

@Namey看到[这个评论](http://stackoverflow.com/questions/27599018/get-html-node-not-necessarily-element-on-click/27599416?noredirect=1#comment43622615_27599161):我认为它提供通过轮询元素位置更容易解决问题。 – Makaze

1

也许就像这个演示的财产以后可以帮助您了一点:

document.getElementsByTagName('div')[0].addEventListener('click', function() { 
    var fullStr = this.innerHTML.replace(/<[^>]*>/g, ''), 
     sel = window.getSelection(), 
     str = sel.anchorNode.data, 
     clickPos = sel.focusOffset, 
     wordPosLeft = str.slice(0, clickPos + 1).search(/\S+$/), 
     wordPosRight = str.slice(clickPos).search(/\s/), 
     wordClicked, 
     nextWordRegex, 
     nextWordPosLeft, 
     nextWord; 

    if(wordPosRight < 0) { 
     wordClicked = str.slice(wordPosLeft); 
    } else { 
     wordClicked = str.slice(wordPosLeft, wordPosRight + clickPos); 
    } 
    nextWordRegex = new RegExp(wordClicked); 
    nextWordPosLeft = fullStr.search(nextWordRegex) + wordClicked.length; 
    nextWord = fullStr.slice(nextWordPosLeft).match(/^\s*(\S*)\s*.*$/)[1];  

    console.log('wordClicked: ' + wordClicked); 
    console.log('nextWord: ' + nextWord); 
}); 

this fiddle

+0

这真是太棒了 - 不知道这是可能的。不知道它是否解决了OP问题,因为我看不到如何获得被点击的实际文本节点,但仍然很棒。 –

+0

有趣的是:如果你在最后一个字符结束后点击一个或者两个像素的空间,它会认为下一个单词是“That”(句首),不管你点击了哪个空间,而是单击几个单词像素转换成空间字符,它将检测到单击的单词作为空间后面的单词。如果放大到〜250%+,最简单的方法就是测试并重现这一点。 (google-chrome for Linux 39.0.2171.71) –

+0

是的,它有一些错误;)fullStr.search(nextWordRegex)发现它的第一次出现。所以“是”会在“this”中找到,等等。但我仍然希望它能帮助OP。 – Ferret