Javascript поиск по тегу. Javascript и jquery выборка элемента по классу (атрибут class). Почему скрипт работал некорректно

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

VBS: wscript.sleep 1500 (остановка на 1.5 секунды)

PHP: sleep(10); (остановка на 10 секунд)

Во время подобных пауз исполняющая система (PHP или VBS) ничего не делает . Разработчик, попытавшись интуитивно использовать нечто подобное в Javascript, будет неприятно удивлён. Типичная ошибка при попытке создать паузу в Javascript выглядит так:

Function badtest() { for (var i=1; i < 10; i++) { window.setTimeout("document.getElementById("test1").value += " + i, 900) } }

Вы думаете, что, когда при прохождении цикла очередь дойдёт до рисования очередной цифры, ваш setTimeout честно остановит работу Javascript, подождёт 0.9 сек., добавит в конец поля ввода нужную цифру и потом продолжит работу. Но на самом деле это не так: setInterval и setTimeout в Javascript откладывают выполнение только того действия (или функции), которое указано в скобках. В нашем примере произойдёт следующее:

  • i = 1;
  • откладываем добавление цифры "1" к полю ввода на 0.9 секунды;
  • немедленно за постановкой этой задачи цикл идёт дальше: i=2;
  • откладываем добавление цифры "2" к полю ввода на 0.9 секунды;
  • Немедленно означает, например, 1 мс (то есть несоизмеримо мало, по сравнению с 900 мс): цикл прозведёт свою работу практически мгновенно, создав несколько отложенных задач от одной и той же точки времени. Это значит, все отложенные задачи по "рисованию" будут выполнены практически в одно и то же время, без пауз между добавлением новых цифр. Цикл запускается; всё замирает на 0.9 с; и ширрр – все цифры выстреливаются в ряд одна за другой.

    А как в подобном случае правильно применить setTimeout ? Это сложно. Придётся вызывать функцию рекурсивно (изнутри функции ту же самую функцию), а чтобы этот процесс не был бесконечным, задать условие остановки (например, величину печатаемого числа):

    Function welltest() { if (i < 9) { document.getElementById("test2").value += ++i window.setTimeout("welltest()", 400) } }

    И ещё переменную i придётся инициализировать вне функции – например, так:

    Вот теперь всё работает, как надо (мы уменьшили время задержки с 0.9 с до 0.4 с). Но для подобных задач логичнее всё-таки применять не setTimeout а setInterval (хотя при этом понадобится две функции):

    Function besttest() { window.i = 0 window.timer1 = window.setInterval("draw()", 400) } function draw() { document.getElementById("test3").value += ++i if (i >= 9) clearInterval(window.timer1) }

    Особенность метода Javascirpt setInterval в том, что он не проходит «сам собой», его надо останавливать специальным методом clearInterval . А чтобы было понятно, что именно останавливать, задаче по отложенному действию присваивается специальнй идентификатор – таймер: window.timer1 = window.setInterval(...) .

    Идентификаторы можно присваивать так же и задачам, создаваемым методом setTimeout . Все идентификаторы таймеров должны отличаться друг от друга (быть уникальными в пределах текущего окна браузера). Тогда можно создать в окне несколько разных задач, использующих отложенные действия, и эти задачи будут выполняться параллельно (вроде как одновременно, если у компьютера хватает ресурсов), что в принципе невозможно в PHP или VBS.

    Вот пример страницы с несколькими Javascript-таймерами, работающими одновременно: setinterval.htm (Javascript-функции в файле setinterval.js). Работу всех таймеров страницы (кроме меню) можно остановить клавишей Esc . Все таймеры примеров опираются на «естественный» (а не абстрактное i++ ) отсчёт – времени или расстояния. Все «часы» специально рассинхронизированы (для наглядности). Таймеры, зависящие от расстояния, используются в «индикаторе» и в выпадающем («выезжающем») меню.

    Выпадающее меню

    Наше выезжающее меню – реально выезжающее (из-под «шапки»): между элементами специально оставлены зазоры, чтобы видеть, как оно выезжает. Неожиданно оказалось, что мы не можем сделать одинаково плавный выезд для списков разной длины – вероятно, из-за низкой производительности компьютера (AMD Athlon 999 МГц).

    Достаточно очевидно, что для красоты и гармонии нужно, чтобы списки разных пунктов меню выпадали за одно и то же время. То есть более длинные списки должны выпадать с более высокой скоростью, более короткие – с меньшей скоростью. Казалось бы, это можно реализовать так:

  • Устанавливаем общее время «выезжания», например, в 200 мс.
  • Если выпадающий список имеет высоту 20 px, очевидно, что мы можем двигать его вниз по одному пикселу за интервал 10 мс – и тогда за 200 мс список вылезет весь.
  • Если выпадающий список имеет высоту 40 px, чтобы уложиться в то же время, мы должны двигать его вниз по одному пикселу за 5 мс.
  • По этой логике, если выпадающий список имеет высоту 200 px, мы должны двигать его вниз по одному пикселу за 1 мс. Но такая скорость на нашем компьютере не прокатывает – браузер просто не успевает отрисовывать новое положение списка за одну миллисекунду. Да. Javascript считать успевает (что там считать-то?), а браузер (Firefox) отображать не успевает. Типичная ситуация для веб.

    Поэтому более-менее уровнять время выезжания меню можно только с помощью костылей, и ещё неясно, как это будет работать на более быстром компьютере. Но мы ведь должны рассчитывать на самый медленный? Алгоритм (без учёта быстродействия компьютера) получается примерно такой:

  • Устанавливаем общее время выезжания списка: time = 224 (ms).
  • Устанавливаем минимальное время для одного интервала в цикле: delay = 3 (ms).
  • Устанавливаем минимальный шаг для движения списка: offset = 1 (px).
  • Меняем всё это в зависимости от высоты списка: 1) увеличиваем время задержки (интервала) обратно пропорционально высоте и прямо пропорционально общему времени time (при высоте 224 коэффициент равен 1); 2) если высота больше 40 px, увеличиваем минимальный шаг пропорционально высоте. Константа "40" получена опытным путём для наиболее медленного компьютера. Тесты на компьютере Pentium 4 CPU 2.53GHz выявили точно такое же число – 40. Иначе таймеры идут вразнос, списки выезжают не в ногу.
  • Вот теперь списки более-менее выезжают. За более-менее похожее время. На странице setinterval.htm .

    А вот и Брю-ус:

    Function slide_do(obj, maxtop, offset) { if (getTopLeft(obj).top < maxtop) { obj.style.top = getTopLeft(obj).top + offset } else { if (obj && obj.timer1) { clearInterval(obj.timer1) obj.timer1 = null } } }

    Сама функция, выдвигающая вложенные списки из меню, как видим, очень проста. Осталось только запустить её примерно такой строкой:

    Ts.timer1 = setInterval(function(){slide_do(ts, maxtop, offset)}, delay)

    Ну, а перед запуском только вычислить все эти maxtop и offset, а также поместить список в положение mintop. Чем и занимается «предварительная» функция slide() размером в 40 строк. А всё вместе - в файле setinterval.js . Да, и эта хрень ни хрена не будет работать без подключенного файла стилей

    Within the document that matches the specified selector, or group of selectors. If no matches are found, null is returned.

    Note : The matching is done using depth-first pre-order traversal of the document"s nodes starting with the first element in the document"s markup and iterating through sequential nodes by order of the number of child nodes.

    Syntax element = document.querySelector(selectors); Parameters selectors A DOMString containing one or more selectors to match. This string must be a valid CSS selector string; if it isn"t, a SYNTAX_ERR exception is thrown. See Locating DOM elements using selectors for more about selectors and how to manage them.

    Note: Characters that are not part of standard CSS syntax must be escaped using a backslash character. Since JavaScript also uses backslash escaping, be especially careful when writing string literals using these characters. See for more information.

    Return value Exceptions SYNTAX_ERR The syntax of the specified selectors is invalid. Usage notes

    If the specified selector matches an ID that is incorrectly used more than once in the document, the first element with that ID is returned.

    Escaping special characters

    To match against an ID or selectors that do not follow standard CSS syntax (by using a colon or space inappropriately, for example), you must escape the character with a backslash (" \ "). As the backslash is also an escape character in JavaScript, if you are entering a literal string, you must escape it twice (once for the JavaScript string, and another time for querySelector()):

    console.log("#foo\bar"); // "#fooar" (\b is the backspace control character) document.querySelector("#foo\bar"); // Does not match anything console.log("#foo\\bar"); // "#foo\bar" console.log("#foo\\\\bar"); // "#foo\\bar" document.querySelector("#foo\\\\bar"); // Match the first div document.querySelector("#foo:bar"); // Does not match anything document.querySelector("#foo\\:bar"); // Match the second div

    Examples Finding the first element matching a class

    In this example, the first element in the document with the class " myclass " is returned:

    Var el = document.querySelector(".myclass");

    A more complex selector

    Selectors can also be really powerful, as demonstrated in the following example. Here, the first element with the name "login" () located inside a whose class is "user-panel main" () in the document is returned:

    Var el = document.querySelector("div.user-panel.main input");

    Specifications Specification Status Comment
    DOM
    The definition of "document.querySelector()" in that specification.
    Living Standard
    Browser compatibility

    The compatibility table on this page is generated from structured data. If you"d like to contribute to the data, please check out https://github.com/mdn/browser-compat-data and send us a pull request.

    Update compatibility data on GitHub

    Desktop Mobile Chrome Edge Firefox Internet Explorer Opera Safari Android webview Chrome for Android Firefox for Android Opera for Android Safari on iOS Samsung Internet querySelector
    Chrome Full support 1 Edge Full support 12 Firefox Full support 3.5 IE Full support 8 Opera Full support 10 Safari Full support 3.2 WebView Android Full support Yes Chrome Android Full support Yes Firefox Android Full support Yes Opera Android Full support 10.1 Safari iOS Full support 3.2 Samsung Internet Android ?
    Legend Full support Full support Compatibility unknown Compatibility unknown

    Для того, чтобы скрипт мог работать с каким-то элементом страницы, этот элемент сначала нужно найти. Для Этого в JavaScript есть несколько способов. Найденный элемент обычно присваивается переменной, и в дальнейшем, через эту переменную сркипт обращается к элементу и производит с ним какие-то действия.

    Поиск по id

    Если в коде страницы элементу задан атрибут id , то элемент можно найти по id. Это самый простой способ. Поиск элемента производится с помощью метода getElementById() глобального объекта document.

    document.getElementById (id)

    Параметры:

    id - id элемента, который нужно найти. id - это строка, поэтому она должна быть в кавычках.

    Создадим страницу, добавим на неё элемент и зададим ему id , а в скрипте найдём этот элемент:

    HTML код:

    JavaScript:

    var block = document.getElementById("block"); console.log(block);

    Найденный элемент мы присвоили переменной block и вывели переменную в консоль. Откройте консоль браузера, в ней должен быть указан элемент.

    Так как посик по id - это самый простой и удобный способ, часто используют именно его. Если с каким-то элементом нужно работать в скрипте, то в коде страницы этому элементу устанавливают атрибут id , даже если он не был установлен ранее. И находят элемент по id.

    Поиск по классу

    Метод getElementsByClassName() позволяет найти все элементы, относящиеся к определённому классу.

    document.getElementsByClassName (класс)

    Параметры:

    класс - класс элементов, которые нужно найти

    Метод возвращает псевдомассив, содержащий найденные элементы. Псевдомассивом он называется потому, что для него не работают многие методы массивов. Но главное свойство остаётся - можно обратиться к любому элементу массива. Даже если найден только один элемент, он всё равно находится в массиве.

    Добавим на страницу элементы и зададим им класс. Часть элементов разместим внутри блока, который мы создали ранее. Другую часть создадим вне блока. Смысл этого будет понятен чуть позднее. Теперь страница будет выглядеть так:

    HTML код:

    JavaScript:

    Теперь найдены только те элементы, которые расположены в блоке.

    Поиск по тэгу

    Метод getElementsByTagName() находит все элементы с конкретным тэгом. Он также возвращает псевдомассив с найденными элементами.

    document.getElementsByTagName (тэг)

    Параметры:

    тэг - тэг элементов, которые нужно найти

    Найдём все тэги p , которые есть на странице:

    var p = document.getElementsByTagName("p"); console.log(p);

    Этот метод можно также применять не ко всему документу, а к конкретному элементу. Найдите все тэги p , находящиеся в блоке.

    Поиск по селектору

    Существуют методы querySelector() и querySelectorAll() , которые находят элементы соответсвующие определённому селектору. То есть, будут найдены элементы, к которым был бы применён стиль, если бы он был указан такому селектору. При этом, наличие такого селектора в стиле страницы совсем не обязательно. Эти методы никак не связаны с CSS. Метод querySelectorAll() находит все элементы, соответствующие селектору. А метод querySelector() находит один элемент, который является первым в коде страницы. Эти методы могут заменить все способы поиска элементов, рассмотренные ранее, ведь есть селектор по id, селектор по тэгу и многие другие.

    document.querySelector (селектор)

    document.querySelectorAll (селектор)

    Селекторы пишутся точно так же, как в CSS, только не забывайте ставить кавычки.

    Добавим на страницу список и найдём его по селектору. Мы ищем только один элемент и мы точно знаем, что он будет первый, потому что он один на странице. Поэтому в данном случае удобнее использовать метод querySelector() . Но при использовании этого метода нужно учитывать, что в дальнейшем на страницу могут быть добавлены такие же элементы. Впрочем, это касается большинства методов.

    HTML код:

    Данные методы также могут искать элементы не во всём документе, а внутри конеретного элемента.

    В примере мы использовали только селекторы по тэгу. Попробуйте найти элементы страницы с использованием других селекторов.

    Соседние элементы

    Для найденного элемента можно найти соседей. Каждый элемент является объектом, и соседние элементы можно получить через свойства этого объекта. Свойство previousElementSibling содкржит предыдущий элемент, а свойство nextElementSibling содержит следующий элемент.

    элемент.previousElementSibling

    элемент.nextElementSibling

    Найдём элемент, следующий за блоком:

    Дочерние элементы

    Свойство children содержит массив с дочерними элементами.

    элемент.children

    Найдём дочерние элементы блока.