Уникальный идентификатор элемента, даже если у элемента его нет

Я пишу сценарий GreaseMonkey, в котором я перебираю несколько элементов. Для каждого элемента мне нужен идентификатор строки, который я могу использовать для ссылки на этот элемент позже. Сам элемент не имеет атрибута id, и я не могу изменить исходный документ, чтобы получить его (хотя я могу вносить изменения в DOM в моем скрипте). Я не могу сохранить ссылки в моем скрипте, потому что, когда они мне понадобятся, сам скрипт GreaseMonkey выйдет из области видимости. Есть ли способ, например, получить «внутренний» идентификатор, который использует браузер? Подходит только для Firefox; кросс-браузерное решение, которое может быть применено в других сценариях, было бы здорово.

Редактировать:

  • Если сценарий GreaseMonkey находится вне области видимости, как вы будете ссылаться на элементы позже? Они сценария GreaseMonkey добавляют события в объекты DOM. Я не могу сохранить ссылки в массиве или каком-либо другом подобном механизме, потому что, когда событие сработает, массив исчезнет, ​​потому что скрипт GreaseMonkey выйдет из области видимости. Таким образом, событию нужен какой-то способ узнать ссылку на элемент, которая была в сценарии, когда событие было присоединено. И рассматриваемый элемент не тот, к которому он прикреплен.

  • Разве вы не можете просто использовать пользовательское свойство для элемента? Да, но проблема в поиске. Я должен был бы прибегнуть к переборам всех элементов, ища тот, у которого это пользовательское свойство установлено в желаемый идентификатор. Конечно, это сработает, но в больших документах это может занять очень много времени. Я ищу что-то, где браузер может выполнять работу поиска.

  • Подождите, вы можете или не можете изменить документ? Я не могу изменить исходный документ, но я могу внести изменения в DOM в сценарии. Я уточню в вопросе.

  • Разве вы не можете использовать замыкания? Закрытия оказались эффективными, хотя я изначально думал, что они не будут. Смотрите мой следующий пост.

Звучит как ответ на вопрос: «Могу ли я использовать какой-нибудь внутренний идентификатор браузера?» это «Нет».

31
задан 03.10.2019, 10:33

9 ответов

ОБНОВЛЕНИЕ: Закрытия являются действительно ответом. Таким образом, после игры с ним еще немного, я выяснил, почему закрытия были первоначально проблематичны и как зафиксировать его. Хитрая вещь с закрытием - Вы, должны быть осторожными при итерации через элементы для не окончания со всеми закрытиями, ссылающимися на тот же элемент. Например, это не работает:

for (var i = 0; i < elements.length; i++) {
    var element = elements[i];
    var button = document.createElement("button");
    button.addEventListener("click", function(ev) {
        // do something with element here
    }, false)
}

, Но это делает:

var buildListener = function(element) {
    return function(ev) {
        // do something with event here
    };
};

for (var i = 0; i < elements.length; i++) {
    var element = elements[i];
    var button = document.createElement("button");
    button.addEventListener("click", buildListener(element), false)
}

Так или иначе, я решил не выбрать один ответ, потому что вопрос имел два ответа: 1) Нет, нет никаких внутренних идентификаторов, которые можно использовать; 2) необходимо использовать закрытия для этого. Так я просто upvoted первые люди, которые скажут, были ли внутренние идентификаторы или кто рекомендовал генерировать идентификаторы плюс кто-либо, кто упомянул закрытия. Спасибо за справку!

5
ответ дан 03.10.2019, 10:36
  • 1
    Наоборот, я думаю, что эта ссылка обеспечивает большой понимание относительно того, почему использование char const* не имеет никакого отношения к кодировке символов. – Alexandre C. 23.10.2019, 01:35

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

http://www.prototypejs.org/api/element/identify

Моей любимой библиотекой JavaScript является jQuery. К сожалению, jQuery не имеет функции, любят, определяют. Однако можно все еще установить идентификационный атрибут на значение, которое Вы генерируете самостоятельно.

http://docs.jquery.com/Attributes/attr#keyfn

Вот является частичным отрывком из документов jQuery, который устанавливает идентификатор для отделений на основе положения на странице:

  $(document).ready(function(){

    $("div").attr("id", function (arr) {
          return "div-id" + arr;
        });
  });
2
ответ дан 03.10.2019, 10:34

Закрытие является способом пойти. Таким образом, у Вас будет точная ссылка на элемент, который даже переживет некоторую перестановку DOM.

Пример для тех, кто не знает закрытия:

var saved_element = findThatDOMNode();

document.body.onclick = function() 
{
   alert(saved_element); // it's still there!
}

, Если необходимо было сохранить его в cookie, тогда я рекомендую вычислительный XPath для него (например, идите по DOM подсчет предыдущих одноуровневых элементов, пока Вы не найдете элемент с идентификатором, и Вы закончите с чем-то как [@id=foo]/div[4]/p[2]/a).

XPointer является решением W3C той проблемы.

6
ответ дан 03.10.2019, 10:35

Немного перепутанный формулировкой Вашего вопроса - Вы говорите "необходимость в идентификаторе строки, который можно использовать для ссылки на тот элемент позже", но что Вы "не можете сохранить ссылки в [своем] сценарии, потому что при необходимости в них сам сценарий GreaseMonkey выйдет из объема".

, Если сценарий выйдет из объема, то, как Вы ссылаетесь на них позже?!

я собираюсь проигнорировать то, что я смущен тем, что Вы достигаете и говорите Вам, что я пишу, что сценарии Механика довольно часто и могут изменять элементы DOM, к которым я получаю доступ, чтобы дать им свойство ID. Это - код, который можно использовать для получения псевдоуникального значения для временного использования:

var PseudoGuid = new (function() {
    this.empty = "00000000-0000-0000-0000-000000000000";
    this.GetNew = function() {
        var fourChars = function() {
            return (((1 + Math.random()) * 0x10000)|0).toString(16).substring(1).toUpperCase();
        }
        return (fourChars() + fourChars() + "-" + fourChars() + "-" + fourChars() + "-" + fourChars() + "-" + fourChars() + fourChars() + fourChars());
    };
})();

// usage example:
var tempId = PseudoGuid.GetNew();
someDomElement.id = tempId;

, Который работает на меня, я просто протестировал его в сценарии Механика сам.

<час>

ОБНОВЛЕНИЕ: Закрытия являются способом пойти - лично как жесткий разработчик JavaScript, я не знаю, как Вы не сделали , сразу думают о тех.:)

myDomElement; // some DOM element we want later reference to

someOtherDomElement.addEventListener("click", function(e) {
   // because of the closure, here we have a reference to myDomElement
   doSomething(myDomElement);
}, false);

Теперь, myDomElement один из элементов, которые Вы, по-видимому, из Вашего описания, уже имеете вокруг (так как Вы думали о добавлении идентификатора к нему, или безотносительно).

, Возможно, при регистрации примера того, что Вы пытаетесь сделать, было бы легче помочь Вам, предположив, что это не делает.

6
ответ дан 03.10.2019, 10:35
  • 1
    @ErikE - Насколько я вспоминаю, и it' s дольше, чем я хочу признать, проблема утечки памяти происходит, когда Вам присоединили обработчики событий к элементам DOM, которые удалены из DOM и больше не ссылаются никакими переменными. – Jason Bunting 03.10.2019, 10:36
  • 2
    Don' t закрытия по элементам DOM вызывают утечки браузера, по крайней мере, в IE? – ErikE 03.10.2019, 10:36
  • 3
    Да, я обычно использовал бы закрытия в сценарии как это. I' m не уверенный, почему я didn' t думают о них в этом случае. Я рисую мелом его до слишком многих ночей, работая поздно.:) – Robert J. Walker 03.10.2019, 10:36
  • 4
    Верный - я склонен забывать некоторые подробные сведения спецификаций, так как большинство браузеров является так удобно прощающим.:) Я использовал этот шаблон долгое время в моем собственном коде JavaScript без проблемы, но теперь, когда Вы упоминаете его, я думаю, что внесу изменения для обеспечения законности..., возможно.: P – Jason Bunting 03.10.2019, 10:37
  • 5
    Великие умы мыслят одинаково. Придеритесь к мелочам: DOM id' s должен запуститься с символа A-Z, таким образом, это повреждает HTML (работы хотя).:-) – Borgar 03.10.2019, 10:37
  • 6
    - 1: Я думаю, добавляя ссылку (большая ссылка, btw.) без любого объяснения на то, как это коснулось бы исключений C++, делает ничто для помощи ответ вопрос. (Это могло бы помочь изучить в контексте некоторые проблемы кодирования, но это, что комментарии для, нет?) Это особенно верно, если OP на самом деле должен прочитать ссылку. – Martin Ba 23.10.2019, 01:36

Если Вы можете запись к DOM (я уверен, что Вы можете). Я решил бы это как это:

Имеют функциональный возврат или генерируют идентификатор:

//(function () {

  var idCounter = new Date().getTime();
  function getId( node ) {
    return (node.id) ? node.id : (node.id = 'tempIdPrefix_' + idCounter++ );
  }

//})();

Использование это для получения идентификатора по мере необходимости:

var n = document.getElementById('someid');
getId(n);  // returns "someid"

var n = document.getElementsByTagName('div')[1];
getId(n);  // returns "tempIdPrefix_1224697942198"

Этот способ, которым Вы не должны волноваться о том, на что похож HTML, когда сервер вручает его Вам.

4
ответ дан 03.10.2019, 10:36
  • 1
    @Alexandre: но для читателя здесь на Так, there' s никакой признак , почему я должен прочитать эту длинную статью о внешнем сайте. Поскольку @Martin сказал, don' t просто отправляют ссылки, отправляют краткое изложение и/или объяснение , почему ссылка релевантна. – jalf 23.10.2019, 01:35

Если Вы не изменяете DOM, можно получить их всех согласно индексируемому порядку:

( Прототип пример)

myNodes = document.body.descendants()
alert(document.body.descendants()[1].innerHTML)

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

3
ответ дан 03.10.2019, 10:37
  • 1
    Это - Ваше мнение, и в то время как я уважаю Ваше мнение I don' t совместно используют его. Даже если эти what() вывод только хранится к файлу журнала, это находится на некотором уровне " представленный user" и потребности не быть мусором. – John Dibling 23.10.2019, 01:37

Можно также использовать pguid (уникальный идентификатор страницы) для поколения уникального идентификатора:

 pguid = b9j.pguid.next() // A unique id (suitable for a DOM element)
                          // is generated
                          // Something like "b9j-pguid-20a9ff-0"
 ...
 pguid = b9j.pguid.next() // Another unique one... "b9j-pguid-20a9ff-1"

 // Build a custom generator
 var sequence = new b9j.pguid.Sequence({ namespace: "frobozz" })
 pguid = sequence.next() "frobozz-c861e1-0"

http://appengine.bravo9.com/b9j/documentation/pguid.html

1
ответ дан 03.10.2019, 10:38
  • 1
    +1: Существует распространенное заблуждение о кодировании. – ereOn 23.10.2019, 01:38

В JavaScript Вы могли присоединить пользовательское поле ID к узлу

if(node.id) {
  node.myId = node.id;
} else {
  node.myId = createId();
}

// store myId

, Это - немного взлома, но это даст каждому узлу идентификатор, который можно использовать. Конечно, document.getElementById() не обратит внимание на него.

0
ответ дан 03.10.2019, 10:39
  • 1
    date.js библиотека кажется багги, и у меня были проблемы при реализации его при использовании jQuery ui datepicker, это кажется лучшим поддерживаемым решением. – Liam 03.10.2019, 03:24
  • 2
    Да, но проблема находится на конце поиска позже. Единственным путем I' d должны найти, что элемент снова должен выполнить итерации всех элементов в документе и сравнить то пользовательское свойство. В зависимости от размера документа, который мог быть действительно медленным. – Robert J. Walker 03.10.2019, 10:40

Ответ не, нет внутреннего идентификатора, к которому можно получить доступ. Opera и IE (возможно, Safari?) поддержка .sourceIndex (который изменяется, если DOM делает), но Firefox не имеет ничего из этого вида.

можно моделировать исходный индекс путем генерации Xpath к данному узлу или нахождения индекса узла от document.getElementsByTagName('*'), который будет всегда возвращать элементы в исходном порядке.

Все это требует абсолютно статического файла, конечно. Изменения в DOM повредят поиск.

то, Что я не понимаю, - то, как можно освободить ссылки на узлы, но не на (теоретический) внутренний идентификатор? Или закрытия и присвоения работают, или они не делают. Или я пропускаю что-то?

7
ответ дан 03.10.2019, 10:41
  • 1
    @Koushik: Да, ofstream (и другой " concrete" потоковые типы), подвижны и выгружаемы. – Howard Hinnant 27.12.2013, 05:33

Теги

Похожие вопросы