Как создать уникальный селектор css для элемента DOM?

Мне нужно создать уникальный селектор css для элементов.
В частности, у меня есть обработчик событий onclick, который должен помнить, какой целевой элемент был нажат и отправил эту информацию на мой сервер. Есть ли способ сделать это без внесения изменений DOM?

P. S. мой код Javascript должен быть запущен на разных
3-х партийные сайты, поэтому я не могу делать никаких предположений о html.

6 ответов


допустим у вас есть список ссылок для простоты: вы можете просто передать указатель пусковым элементом в коллекции все элементы

<a href="#">...</a>
<a href="#">...</a>    
<a href="#">...</a>

js (jQuery 1.7+, я использовал .on()в противном случае используйте bind() функция) может быть

var triggers = $('a');
triggers.on('click', function(e) {
   e.preventDefault();
   var index = triggers.index($(this));
   /* ajax call passing index value */
});

так что если вы нажмете на третий элемент, значение индекса будет 2. Индекса (на основе 0 ); конечно, это действительно до тех пор, пока код (DOM) не изменится. Позже вы можете использовать этот индекс для создания правила css для этот элемент, например, использует :nth-child

в противном случае, если каждый из ваших элементов имеет другой атрибут (например, id), вы можете передать этот атрибут

пример на JsFiddle : http://jsfiddle.net/t7J8T/


Да, вы могли бы это сделать. Но с некоторыми оговорками. Чтобы гарантировать уникальность селекторов, вам необходимо использовать :nth-child() который не поддерживается повсеместно. Если вы хотите поместить эти селекторы CSS в CSS-файлы, он не будет работать во всех браузерах.

Я бы сделал это что-то вроде этого:

function () {
    if (this.id) {
        return sendToServer('#' + this.id);
    }
    var parent = this.parentNode;
    var selector = '>' + this.nodeName + ':nth-child(' + getChildNumber(this) ')';
    while (!parent.id && parent.nodeName.toLowerCase() !== 'body') {
        selector = '>' + this.nodeName + ':nth-child(' + getChildNumber(parent) + ')' + selector;
        parent = parent.parentNode;
    }
    if (parent.nodeName === 'body') {
        selector = 'body' + selector;
    } else {
        selector = '#' + parent.id + selector;
    }
    return sendToServer(selector);
}

затем добавьте это в обработчик click для каждого элемента, который вы хотите смоделировать. Я оставлю вас, чтобы реализовать getChildNumber().

Edit: только что видел ваш комментарий о том, что это сторонний код... таким образом, вы можете добавить


эта функция создает длинный, но довольно практичный уникальный селектор, работает быстро.

const getCssSelector = (el) => {
  let path = [], parent;
  while (parent = el.parentNode) {
    path.unshift(`${el.tagName}:nth-child(${[].indexOf.call(parent.children, el)+1})`);
    el = parent;
  }
  return `${path.join(' > ')}`.toLowerCase();
};

пример результата:

html:nth-child(1) > body:nth-child(2) > div:nth-child(1) > div:nth-child(1) > main:nth-child(3) > div:nth-child(2) > p:nth-child(2)

следующий код создает немного более красивый и короткий селектор

const getCssSelectorShort = (el) => {
  let path = [], parent;
  while (parent = el.parentNode) {
    let tag = el.tagName, siblings;
    path.unshift(
      el.id ? `#${el.id}` : (
        siblings = parent.children,
        [].filter.call(siblings, sibling => sibling.tagName === tag).length === 1 ? tag :
        `${tag}:nth-child(${1+[].indexOf.call(siblings, el)})`
      )
    );
    el = parent;
  };
  return `${path.join(' > ')}`.toLowerCase();
};

пример результата:

html > body > div > div > main > div:nth-child(2) > p:nth-child(2)

вы, вероятно, могли бы пересечь дерево DOM от узла обратно к элементу body для создания селектора.

Firebug имеет функцию для этого, используя селекторы XPath и CSS.

посмотреть ответ


"use strict";
function getSelector(_context){
     var index, localName,pathSelector, that = _context, node;
     if(that =='null') throw 'not an  dom reference';
     index =  getIndex(that);

     while(that.tagName){
       pathSelector = that.localName+(pathSelector?'>'+pathSelector :'');
       that = that.parentNode;
     }
    pathSelector = pathSelector+':nth-of-type('+index+')';

    return pathSelector;
}

function getIndex(node){
    var i=1;
    var tagName = node.tagName;

    while(node.previousSibling){
    node = node.previousSibling;
        if(node.nodeType === 1 && (tagName.toLowerCase() == node.tagName.toLowerCase())){
            i++;
        }
    }
    return i;
}
document.addEventListener('DOMContentLoaded', function(){
   document.body.addEventListener('mouseover', function(e){
     var c = getSelector(e.target);
         var  element = document.querySelector(c);
          //console.log(element);
      console.log(c);
        //element.style.color = "red"

   });
});

вы можете попробовать это. без использования jquery.


проверьте эту библиотеку генератора селектора CSS @medv / finder

Build Status

  • генерирует самые короткие селекторы
  • уникальные селекторы на странице
  • стабильные и надежные селекторы
  • 2.9 kB gzip и уменьшить размер

пример сгенерированного селектора:

.blog > article:nth-child(3) .add-comment