Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   contendeditable и tabIndex (https://javascript.ru/forum/misc/85519-contendeditable-i-tabindex.html)

voraa 11.10.2023 13:42

Я в свое время где то надыбал такой селектор для поиска фокусируемых элементов
const sfocusable = [
    'a[href]:not([tabindex^="-"]):not([inert])',
    'area[href]:not([tabindex^="-"]):not([inert])',
    'input:not([disabled]):not([inert])',
    'select:not([disabled]):not([inert])',
    'textarea:not([disabled]):not([inert])',
    'button:not([disabled]):not([inert])',
    'iframe:not([tabindex^="-"]):not([inert])',
    'audio:not([tabindex^="-"]):not([inert])',
    'video:not([tabindex^="-"]):not([inert])',
    '[contenteditable]:not([tabindex^="-"]):not([inert])',
    '[tabindex]:not([tabindex^="-"]):not([inert])',
].join(',');

ruslan_mart 11.10.2023 14:04

voraa, спасибо

Про inert не знал

Но кажется, что это не совсем правильный селектор. Здесь как минимум некорректно проверять наличие атрибута disabled у элементов форм, потому что он может отсутствовать, но при этом состояние наследоваться от fieldset.

Про inert прочитал, он также может быть выставлен у родителя, чего здесь не учитывается :)

Вот такой селектор сделал:

const sfocusable = ':where(:any-link, :read-write, audio, button, input, select, video, details summary, [tabindex]):not(:disabled):not([tabindex^="-"])';


Но кажется, что селектором не получится исключить родительский inert без извращений.

Нужно по скорости проверить, что будет быстрее, селектор попроще + проверки на JS, или просто один сложный селектор.

P.S.: селектор :read-write покрывает сразу кейс с contenteditable и textarea

voraa 11.10.2023 14:18

Тут еще одна затыка может быть. Я не уверен, что алгоритм сортировки оставит элементы с одинаковым tabIndex в той же последовательности, какие они имели до сортировки.

ruslan_mart 11.10.2023 17:17

У меня все правильно работает:

const elements = [
  [-1, 'A'],
  [0, 'C'],
  [-1, 'B'],
  [0, 'D'],
  [0, 'E'],
  [1, 'F'],
  [2, 'G'],
];

const sorted = elements.toSorted((elementA, elementB) => {
	return elementA[0] - elementB[0];
});

console.log(sorted);


Или ты что-то другое имеешь ввиду?

Aetae 11.10.2023 18:21

ruslan_mart, на это полагаться никак нельзя. Алгоритм может произвольно меняться от реализации к реализации и от браузера к браузеру. Он гарантирует только сортировку и ничего более.

voraa 11.10.2023 18:30

Цитата:

Сообщение от ruslan_mart
У меня все правильно работает:

Ну хорошо если так всегда будет.

ruslan_mart 12.10.2023 18:15

Aetae, ох, ладно, свою сортировку значит напишу.

Спасибо всем!

Aetae 12.10.2023 21:20

Ну прям свою сортировку это перебор, достаточно сделать как-то так :) :
const elements = [
  [-1, 'A'],
  [0, 'C'],
  [-1, 'B'],
  [0, 'D'],
  [0, 'E'],
  [1, 'F'],
  [2, 'G'],
];

const sorted = elements
.map((arr, index) => [index, ...arr])
.sort((elementA, elementB) => {
	return elementA[1] - elementB[1] || elementA[0] - elementB[0];
})
.map((arr) => arr.slice(1));

console.log(sorted);

ruslan_mart 12.10.2023 23:45

Спасибо, поэкспериментирую.

Меня напрягает, что алгоритмическая сложность начинает расти. Все-таки элементов может быть достаточно много. Сам по себе sort работает не быстро O(n log n), и если еще дополнительные 2 мэпа и внутри каждого создается новый массив через slice. Как-то сложно получается. :)

В общем, нужно подумать, может одним reduce попробую решить.

Aetae 13.10.2023 00:20

Ну по сути он так и останется O(n log n), лишние n же не считаются.=)
А так тебе просто надо изначально формировать свой массив elements с индексами и всего делов.


Часовой пояс GMT +3, время: 17:15.