在Jquery中获取元素的唯一选择器

Alp*_*Alp 54 html javascript jquery css-selectors

我想创建像记录器一样跟踪用户的所有动作.为此,我需要识别用户与之交互的元素,以便我可以在以后的会话中引用这些元素.

用伪代码说,我希望能够做类似以下的事情

示例HTML(可能有任何复杂性):

<html>
<body>
  <div class="example">
    <p>foo</p>
    <span><a href="bar">bar</a></span>
  </div>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

用户点击某些内容,例如链接.现在我需要识别被点击的元素并将其位置保存在DOM树中以供以后使用:

(any element).onclick(function() {
  uniqueSelector = $(this).getUniqueSelector();
})
Run Code Online (Sandbox Code Playgroud)

现在,uniqueSelector应该是这样的(我不介意它是xpath还是css选择器样式):

html > body > div.example > span > a
Run Code Online (Sandbox Code Playgroud)

这将提供保存该选择器字符串并在以后使用它来重放用户所做的操作的可能性.

怎么可能?

更新

得到了我的答案:为元素获取jQuery选择器

Alp*_*Alp 38

我自己会回答这个问题,因为我找到了一个必须修改的解决方案.以下脚本正在运行,它基于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) { 
                var allSiblings = parent.children();
                var index = allSiblings.index(realNode) + 1;
                if (index > 1) {
                    name += ':nth-child(' + index + ')';
                }
            }

            path = name + (path ? '>' + path : '');
            node = parent;
        }

        return path;
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 只是一个注意事项 - 如果您希望选择器对页面结构的变化具有鲁棒性,并且有10个以上的库([比较](http://stackoverflow.com/questions/2068272/getting-),问题会比看起来更复杂. a-jquery-selector-for-an-element/32218234#32218234))实现此功能. (4认同)

alg*_*thm 18

与@Alp中的那个解决方案相同,但与多个jQuery元素兼容.

jQuery('.some-selector')可以导致一个或多个DOM元素.不幸的是,@ Alp的解决方案仅适用于第一个解决方案.我的解决方案将它们连接在一起,.

如果你只想处理第一个元素,请执行以下操作:

jQuery('.some-selector').first().getPath();

// or
jQuery('.some-selector:first').getPath();
Run Code Online (Sandbox Code Playgroud)

改良版

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)
                {
                    var 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(',');
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 如何投票以关闭此问题作为您发布的问题的副本[相同答案](http://stackoverflow.com/questions/2068272/getting-a-jquery-selector-for-an-element/26763360#26763360 ) 至? (6认同)

Rap*_*nah 6

纯 JavaScript 解决方案

注意:这里使用Array.fromArray.prototype.filter,两者都需要在 IE11 中进行 polyfill。

function getUniqueSelector(node) {
  let selector = "";
  while (node.parentElement) {
    const siblings = Array.from(node.parentElement.children).filter(
      e => e.tagName === node.tagName
    );
    selector =
      (siblings.indexOf(node)
        ? `${node.tagName}:nth-of-type(${siblings.indexOf(node) + 1})`
        : `${node.tagName}`) + `${selector ? " > " : ""}${selector}`;
    node = node.parentElement;
  }
  return `html > ${selector.toLowerCase()}`;
}
Run Code Online (Sandbox Code Playgroud)

用法

getUniqueSelector(document.getElementsByClassName('SectionFour')[0]);

getUniqueSelector(document.getElementById('content'));
Run Code Online (Sandbox Code Playgroud)


Eli*_*Eli 5

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

分配唯一的ID:

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

根据唯一ID选择:

// 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 + '"]');
Run Code Online (Sandbox Code Playgroud)

  • 重新加载页面后,这将无法正常工作。我希望能够识别用户在上一个会话中引用的元素 (5认同)

Gar*_*een 5

(any element).onclick(function() {
  uniqueSelector = $(this).getUniqueSelector();
})
Run Code Online (Sandbox Code Playgroud)

this 唯一的选择器和该被点击元素的路径.为什么不使用它?您可以使用jquery的$.data()方法来设置jquery选择器.或者,只需按下您将来需要使用的元素:

var elements = [];
(any element).onclick(function() {
  elements.push(this);
})
Run Code Online (Sandbox Code Playgroud)

如果您确实需要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;
  };
Run Code Online (Sandbox Code Playgroud)

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