Використання querySelector з ідентифікаторами, які є числами


94

Наскільки я розумію, специфікація HTML5 дозволяє використовувати ідентифікатори, які є такими цифрами.

<div id="1"></div>
<div id="2"></div>

Я можу отримати доступ до цих прекрасних за допомогою, getElementByIdале не за допомогою querySelector. Якщо я спробую зробити наступне, я отримую SyntaxError: DOM Exception 12 у консолі.

document.querySelector("#1")

Мені просто цікаво, чому використання чисел як ідентифікаторів не працює, querySelectorколи специфікація HTML5 говорить, що вони дійсні. Я спробував кілька браузерів.


1
Я не думаю, що специфікація HTML5 каже, що вони дійсні. Я ще раз перевірю ...
beautifulcoder

3
@beautifulcoder Вони дійсні
dsgriffin

1
Не зважайте, згідно validator.w3.org/check допустимо використовувати цифри. Можливо, сучасні браузери не зовсім реалізували стандарт?
beautifulcoder

Відповіді:


108

Він дійсний, але вимагає спеціального поводження. Звідси: http://mathiasbynens.be/notes/css-escapes

Провідні цифри

Якщо перший символ ідентифікатора є числовим, вам потрібно буде уникнути його на основі його кодової точки Unicode. Наприклад, кодовою точкою для символу 1 є U + 0031, тому вам слід уникнути його як \ 000031 або \ 31.

По суті, щоб уникнути будь-якого числового символу, просто додайте йому префікс \ 3 і додайте пробіл (). Yay Unicode!

Отже, ваш код закінчиться як (спочатку CSS, другий JS):

#\31  {
    background: hotpink;
}

document.getElementById('1');
document.querySelector('#\\31 ');

Яким би був синтаксис для значень, більших за 9? Я не можу змусити це працювати з ідентифікаторами, такими як 10.
Berry Blue

5
Вам потрібен пробіл після першого символу: #\\31 0- Ви можете звернутися до mothereffingcssescapes.com
Денніс

Дякуємо за подальші дії та посилання!
Berry Blue

1
Зверніть увагу, що пробіл необхідний лише в тому випадку, якщо символ, що є шістнадцятковою цифрою, відразу ж слідує за послідовністю екранування, щоб відрізнити цей символ від послідовності екранування. Детальніше див. У w3.org/TR/CSS21/syndata.html#characters .
BoltClock

83

Оскільки вони є дійсними в специфікації HTML5, вони не є дійсними в CSS, що означає « селектор запитів ».

Натомість вам довелося б зробити це:, document.querySelector("[id='1']")що є дуже довготривалим, враховуючи, що ви могли б дати йому значущий ідентифікатор, як- message1небудь;)


1
Вам не "потрібно" - є спосіб використовувати селектор ідентифікатора з провідною цифрою. Однак я погоджуюсь, що краще мати значущий ідентифікатор.
Денніс

9
UUID-адреси можуть починатися з числа.
Альфонсо Нісікава

20

Мені потрібен був автоматизований підхід. Нещодавня зміна означала, що використовувані значення id більше не були простими алфавітними символами та включали цифри та спеціальні символи.

У підсумку я використав CSS.escape: https://developer.mozilla.org/en-US/docs/Web/API/CSS/escape

console.log(CSS.escape('1'));

По-перше, це невдалий випадок:

const theId = "1";
document.querySelector(`#${theId}`);
const el = document.querySelector(`#${theId}`);
el.innerHTML = "After";
<div id="1">Before</div>

А тепер використовуємо CSS.escape:

const theId = "1";
const el = document.querySelector(`#${CSS.escape(theId)}`);
el.innerHTML = "After";
<div id="1">Before</div>

Подивіться, як правильно змінюється показ After, демонструючи, як працював селектор!


На сьогоднішній день, коли вам потрібно мати справу з якимсь дивним ідентифікатором, яким ви не керуєте, це найчистіше рішення, ще й тому, що це підтримується всіма сучасними браузерами.
LasaleFamine

3

З документації W3C Синтаксис селекторів атрибутів

Значення атрибута мають бути дійсними ідентифікаторами CSS або рядком.

Таким чином, цифри або буквено-цифрові рядки з початковою цифрою не відповідають дійсним ідентифікаторам.

Якщо ви використовуєте утиліту генератора ідентифікаторів для генерації ідентифікатора, у вас можуть вийти буквено-цифрові ідентифікатори з провідними цифрами.

Швидким виправленням було б опустити цифри з SEED генератора (якщо його можна змінити) або завжди додати рядок до згенерованого ідентифікатора.


2

Ось функція, яку я зараз зробив для роботи з провідними ідентифікаторами номерів у селекторах CSS, і це безпечно для IE, оскільки CSS.escape - ні.

Перед використанням пропустіть селектор через цю функцію cleanSelector:

var cleanSelector = function(selector){
    (selector.match(/(#[0-9][^\s:,]*)/g) || []).forEach(function(n){
        selector = selector.replace(n, '[id="' + n.replace("#", "") + '"]');
    });
    return selector;
};

var myselector = ".dog #980sada_as div span#aside:hover div.apple#05crab:nth-of-type(2), .ginger #2_green_div, div.cupcake #darwin p#23434-346365-53453";

var clean_myselector = cleanSelector(myselector);

// print to show difference
console.log(myselector);
console.log(clean_myselector);

//use the new selector like normal
var elems = document.querySelectorAll( clean_myselector ); 

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.