在Jquery中获取元素的唯一select器

我想创build一个跟踪用户所有操作的logging器。 为此,我需要识别用户与之交互的元素,以便在稍后的会话中引用这些元素。

用伪代码说话,我想能够做到像下面这样的东西

示例HTML(可能是任何复杂的):

<html> <body> <div class="example"> <p>foo</p> <span><a href="bar">bar</a></span> </div> </body> </html> 

用户点击一些东西,如链接。 现在我需要确定被单击的元素并将其位置保存在DOM树中以供以后使用:

 (any element).onclick(function() { uniqueSelector = $(this).getUniqueSelector(); }) 

现在,uniqueSelector应该是这样的(我不介意,如果它是XPath或CSSselect器样式):

 html > body > div.example > span > a 

这将提供保存该select器string并在以后使用它的可能性,以重放用户所做的动作。

这怎么可能?

更新

得到我的答案: 获取元素的jQueryselect器

我会自己回答,因为我find了一个解决scheme,我不得不修改。 以下脚本正在工作,并基于Blixt的脚本 :

 jQuery.fn.extend({ getPath: function () { var path, node = this; while (node.length) { var realNode = node[0], name = realNode.localName; if (!name) break; name = name.toLowerCase(); var parent = node.parent(); var sameTagSiblings = parent.children(name); if (sameTagSiblings.length > 1) { allSiblings = parent.children(); var index = allSiblings.index(realNode) + 1; if (index > 1) { name += ':nth-child(' + index + ')'; } } path = name + (path ? '>' + path : ''); node = parent; } return path; } }); 

类似于@Alp的解决scheme,但与多个jQuery元素兼容。

jQuery('.some-selector')可以导致一个或多个DOM元素。 @不幸的是,阿尔卑斯的解决scheme只有第一个。 我的解决scheme将它们连接在一起。

如果你只想处理第一个元素,就像这样:

 jQuery('.some-selector').first().getPath(); // or jQuery('.some-selector:first').getPath(); 

改良版

 jQuery.fn.extend({ getPath: function() { var pathes = []; this.each(function(index, element) { var path, $node = jQuery(element); while ($node.length) { var realNode = $node.get(0), name = realNode.localName; if (!name) { break; } name = name.toLowerCase(); var parent = $node.parent(); var sameTagSiblings = parent.children(name); if (sameTagSiblings.length > 1) { allSiblings = parent.children(); var index = allSiblings.index(realNode) +1; if (index > 0) { name += ':nth-child(' + index + ')'; } } path = name + (path ? ' > ' + path : ''); $node = parent; } pathes.push(path); }); return pathes.join(','); } }); 
 (any element).onclick(function() { uniqueSelector = $(this).getUniqueSelector(); }) 

this 单击元素的唯一select器和path。 为什么不使用它? 你可以利用jquery的$.data()方法来设置jqueryselect器。 或者只需要推送您将来需要使用的元素:

 var elements = []; (any element).onclick(function() { elements.push(this); }) 

如果你确实需要xpath,你可以使用下面的代码来计算它:

  function getXPath(node, path) { path = path || []; if(node.parentNode) { path = getXPath(node.parentNode, path); } if(node.previousSibling) { var count = 1; var sibling = node.previousSibling do { if(sibling.nodeType == 1 && sibling.nodeName == node.nodeName) {count++;} sibling = sibling.previousSibling; } while(sibling); if(count == 1) {count = null;} } else if(node.nextSibling) { var sibling = node.nextSibling; do { if(sibling.nodeType == 1 && sibling.nodeName == node.nodeName) { var count = 1; sibling = null; } else { var count = null; sibling = sibling.previousSibling; } } while(sibling); } if(node.nodeType == 1) { path.push(node.nodeName.toLowerCase() + (node.id ? "[@id='"+node.id+"']" : count > 0 ? "["+count+"]" : '')); } return path; }; 

参考: http : //snippets.dzone.com/posts/show/4349

我认为更好的解决scheme是生成一个随机的id,然后访问基于该id的元素:

分配唯一的ID:

 // or some other id-generating algorithm $(this).attr('id', new Date().getTime()); 

根据唯一ID进行select:

 // getting unique id var uniqueId = $(this).getUniqueId(); // or you could just get the id: var uniqueId = $(this).attr('id'); // selecting by id: var element = $('#' + uniqueId); // if you decide to use another attribute other than id: var element = $('[data-unique-id="' + uniqueId + '"]'); 

如果你有一个身份属性(例如id =“something”),你应该得到它的价值,

 var selector = "[id='" + $(yourObject).attr("id") + "']"; console.log(selector); //=> [id='something'] console.log($(selector).length); //=> 1 

如果你没有一个身份属性,你想获得它的select器,你可以创build一个身份属性。 像上面这样的东西,

 var uuid = guid(); $(yourObject).attr("id", uuid); // Set the uuid as id of your object. 

你可以使用你自己的guid方法,或者使用在这个答案中find的源代码,

 function guid() { function s4() { return Math.floor((1 + Math.random()) * 0x10000) .toString(16) .substring(1); } return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); } 

这个答案不符合原来的问题描述,但它确实回答了题目问题。 我来到这个问题寻找一种方式来获得一个元素的唯一select器,但我没有需要select器之间的页面加载有效。 所以,我的答案在页面加载之间不起作用。

我觉得修改DOM不是idel,但是这是一个很好的方法来构build一个没有代码的唯一的select器。 读完@ Eli的回答后,我得到了这个想法:

使用唯一值分配自定义属性。

 $(element).attr('secondary_id', new Date().getTime()) var secondary_id = $(element).attr('secondary_id'); 

然后使用该唯一的ID来build立一个CSSselect器。

 var selector = '[secondary_id='+secondary_id+']'; 

然后你有一个select器,将select你的元素。

 var found_again = $(selector); 

而且你很多人想检查一下,确保元素上没有secondary_id属性。

 if ($(element).attr('secondary_id')) { $(element).attr('secondary_id', (new Date()).getTime()); } var secondary_id = $(element).attr('secondary_id'); 

把它放在一起

 $.fn.getSelector = function(){ var e = $(this); // the `id` attribute *should* be unique. if (e.attr('id')) { return '#'+e.attr('id') } if (e.attr('secondary_id')) { return '[secondary_id='+e.attr('secondary_id')+']' } $(element).attr('secondary_id', (new Date()).getTime()); return '[secondary_id='+e.attr('secondary_id')+']' }; var selector = $('*').first().getSelector(); 

你可以做这样的事情:

 $(".track").click(function() { recordEvent($(this).attr("id")); }); 

它将一个onclick事件处理程序附加到每个具有该track类的对象。 每次点击一个对象时,它的id都被input到recordEvent()函数中。 你可以使这个函数logging每个对象的时间和id或任何你想要的。

 $(document).ready(function() { $("*").click(function(e) { var path = []; $.each($(this).parents(), function(index, value) { var id = $(value).attr("id"); var class = $(value).attr("class"); var element = $(value).get(0).tagName path.push(element + (id.length > 0 ? " #" + id : (class.length > 0 ? " .": "") + class)); }); console.log(path.reverse().join(">")); return false; }); }); 

工作示例: http : //jsfiddle.net/peeter/YRmr5/

使用*select器(非常慢)时可能会遇到问题,并停止事件冒泡,但不能没有更多的HTML代码真正的帮助。

你可以做那样的事(未经testing)

 function GetPathToElement(jElem) { var tmpParent = jElem; var result = ''; while(tmpParent != null) { var tagName = tmpParent.get().tagName; var className = tmpParent.get().className; var id = tmpParent.get().id; if( id != '') result = '#' + id + result; if( className !='') result = '.' + className + result; result = '>' + tagName + result; tmpParent = tmpParent.parent(); } return result; } 

这个函数将保存“path”的元素,现在再次find元素将是几乎不可能的方式HTML是因为在这个函数中我不保存每个元素的同分类指数,我只保存编号和类别。

所以除非你的html文档的每一个元素都有一个ID,这种方法是行不通的。