在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,这种方法是行不通的。