JavaScript заметки
8.56K subscribers
2.75K photos
4 videos
1.27K links
Регулярные заметки по практическому JavaScript. Обучащию посты позволят прокачать навыки во Frontend-разработке.

Можно почитать пока компилируется проект :)

Сотрудничество: @noname_media

Канал на бирже: telega.in/channels/notesjs/card?r=Wj7h1mbl
Download Telegram
Внимание, полоса прокрутки

В иллюстрации выше намеренно продемонстрирован самый сложный и полный случай, когда у элемента есть ещё и полоса прокрутки. Некоторые браузеры (не все) отбирают место для неё, забирая его у области, отведённой для содержимого (помечена как «content width» выше).

Таким образом, без учёта полосы прокрутки ширина области содержимого (content width) будет 300px, но если предположить, что ширина полосы прокрутки равна 16px (её точное значение зависит от устройства и браузера), тогда остаётся только 300 - 16 = 284px, и мы должны это учитывать. Вот почему примеры в этой главе даны с полосой прокрутки. Без неё некоторые вычисления будут проще.

#браузер #документ #размеры
👍5🔥1
Метрики

Вот общая картина с геометрическими свойствами. Значениями свойств являются числа, подразумевается, что они в пикселях.

К ней мы часто будем возвращаться в следующих постах и описывать отдельные составляющие. А пока просто изучите, что за что примерно отвечает.

#браузер #документ #размеры
👍3🔥3
offsetParent, offsetLeft/Top

Эти свойства редко используются, но так как они являются «самыми внешними» метриками, мы начнём с них.

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

То есть, ближайший предок, который удовлетворяет следующим условиям:
- Является CSS-позиционированным (CSS-свойство position равно absoluterelativefixed или sticky),
- или <td><th><table>,
- или <body>.

Свойства offsetLeft/offsetTop содержат координаты x/y относительно верхнего левого угла offsetParent.

В примере выше внутренний <div> имеет элемент <main> в качестве offsetParent, а свойства offsetLeft/offsetTop являются сдвигами относительно верхнего левого угла (180).

#браузер #документ #размеры
👍4🔥2
Вот так выглядят свойства offsetParent, offsetLeft/Top

Подробное описание можете посмотреть постом выше: https://t.me/notesjs/567

#браузер #документ #размеры
👍4🔥1
offsetWidth/Height

Теперь переходим к самому элементу.

Эти два свойства – самые простые. Они содержат «внешнюю» ширину/высоту элемента, то есть его полный размер, включая рамки.

Для нашего элемента:
- offsetWidth = 390 – внешняя ширина блока, её можно получить сложением CSS-ширины (300px), внутренних отступов (2 * 20px) и рамок (2 * 25px).
- offsetHeight = 290 – внешняя высота блока.

#браузер #документ #размеры
👍2🔥1
Метрики для не показываемых элементов равны нулю.

Координаты и размеры в JavaScript устанавливаются только для видимых элементов.

Если элемент (или любой его родитель) имеет display:none или отсутствует в документе, то все его метрики равны нулю (или null, если это offsetParent).

Например, свойство offsetParent равно null, а offsetWidth и offsetHeight равны 0, когда мы создали элемент, но ещё не вставили его в документ, или если у элемента (или у его родителя) display:none.

Мы можем использовать это, чтобы делать проверку на видимость.

Заметим, что функция isHidden также вернёт true для элементов, которые в принципе показываются, но их размеры равны нулю (например, пустые <div>).

#браузер #документ #размеры
👍4🔥1
clientTop/Left

Пойдём дальше. Внутри элемента у нас рамки (border).

Для них есть свойства-метрики clientTop и clientLeft.

В нашем примере:
- clientLeft = 25 – ширина левой рамки
- clientTop = 25 – ширина верхней рамки

Но на самом деле эти свойства – вовсе не ширины рамок, а отступы внутренней части элемента от внешней.

#браузер #документ #размеры
🔥1
scrollWidth/Height

Эти свойства – как clientWidth/clientHeight, но также включают в себя прокрученную (которую не видно) часть элемента.

На рисунке выше:
- scrollHeight = 723 – полная внутренняя высота, включая прокрученную область.
- scrollWidth = 324 – полная внутренняя ширина, в данном случае прокрутки нет, поэтому она равна clientWidth.

Эти свойства можно использовать, чтобы «распахнуть» элемент на всю ширину/высоту.

#браузер #документ #размеры
👍1🔥1
matches

Предыдущие методы искали по DOM.

Метод elem.matches(css) ничего не ищет, а проверяет, удовлетворяет ли elem CSS-селектору, и возвращает true или false.

Этот метод удобен, когда мы перебираем элементы (например, в массиве или в чём-то подобном) и пытаемся выбрать те из них, которые нас интересуют.

#браузер #документ #поиск
👍3🔥31
closest

Предки элемента – родитель, родитель родителя, его родитель и так далее. Вместе они образуют цепочку иерархии от элемента до вершины.

Метод elem.closest(css) ищет ближайшего предка, который соответствует CSS-селектору. Сам элемент также включается в поиск.

Другими словами, метод closest поднимается вверх от элемента и проверяет каждого из родителей. Если он соответствует селектору, поиск прекращается. Метод возвращает либо предка, либо null, если такой элемент не найден.

#браузер #документ #поиск
👍5🔥3
getElementsBy*

Существуют также другие методы поиска элементов по тегу, классу и так далее.

На данный момент, они скорее исторические, так как querySelector более чем эффективен.

Здесь мы рассмотрим их для полноты картины, также вы можете встретить их в старом коде.

elem.getElementsByTagName(tag) - ищет элементы с данным тегом и возвращает их коллекцию. Передав "*" вместо тега, можно получить всех потомков.

elem.getElementsByClassName(className) - возвращает элементы, которые имеют данный CSS-класс.

document.getElementsByName(name) - возвращает элементы с заданным атрибутом name. Очень редко используется.

P.S. На картинке пример поиска всех input в таблице.

#браузер #документ #поиск
👍3🔥1
Живые коллекции

Все методы "getElementsBy*" возвращают живую коллекцию. Такие коллекции всегда отражают текущее состояние документа и автоматически обновляются при его изменении.

В приведённом выше примере есть два скрипта.
- Первый создаёт ссылку на коллекцию <div>. На этот момент её длина равна 1.
- Второй скрипт запускается после того, как браузер встречает ещё один <div>, теперь её длина – 2.

#браузер #документ #поиск
👍4🔥2
Статические коллекции

querySelectorAll возвращает статическую коллекцию. Это похоже на фиксированный массив элементов.

Если мы будем использовать его в примере выше, то оба скрипта вернут длину коллекции, равную 1.

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

#браузер #документ #поиск
👍3🔥1
Итого по поиску в DOM

Есть 6 основных методов поиска элементов в DOM (см. изображение выше).

Безусловно, наиболее часто используемыми в настоящее время являются методы querySelector и querySelectorAll, но и методы getElement(s)By* могут быть полезны в отдельных случаях, а также встречаются в старом коде.

Кроме того:
- Есть метод elem.matches(css), который проверяет, удовлетворяет ли элемент CSS-селектору.
- Метод elem.closest(css) ищет ближайшего по иерархии предка, соответствующему данному CSS-селектору. Сам элемент также включён в поиск.

И, напоследок, давайте упомянем ещё один метод, который проверяет наличие отношений между предком и потомком:
- elemA.contains(elemB) вернёт true, если elemB находится внутри elemA (elemB потомок elemA) или когда elemA==elemB.

#браузер #документ #поиск
👍8
Классы DOM-узлов

У разных DOM-узлов могут быть разные свойства. Например, у узла, соответствующего тегу <a>, есть свойства, связанные со ссылками, а у соответствующего тегу <input> – свойства, связанные с полем ввода и т.д. Текстовые узлы отличаются от узлов-элементов. Но у них есть общие свойства и методы, потому что все классы DOM-узлов образуют единую иерархию.

Каждый DOM-узел принадлежит соответствующему встроенному классу.

Корнем иерархии является EventTarget, от него наследует Node и остальные DOM-узлы.

На рисунке выше изображены основные классы.

#браузер #документ #свойства_узлов
👍5🔥1
EventTarget – это корневой «абстрактный» класс. Объекты этого класса никогда не создаются. Он служит основой, благодаря которой все DOM-узлы поддерживают так называемые «события», о которых мы поговорим позже.

P.S. На картинке описание интерфейса на TypeScipt.

#браузер #документ #свойства_узлов
👍8
Node – также является «абстрактным» классом, и служит основой для DOM-узлов. Он обеспечивает базовую функциональность: parentNodenextSiblingchildNodes и т.д. (это геттеры). Объекты класса Node никогда не создаются. Но есть определённые классы узлов, которые наследуют от него: Text – для текстовых узлов, Element – для узлов-элементов и более экзотический Comment – для узлов-комментариев.

#браузер #документ #свойства_узлов
👍2🔥1
Element – это базовый класс для DOM-элементов. Он обеспечивает навигацию на уровне элементов: nextElementSiblingchildren и методы поиска: getElementsByTagNamequerySelector. Браузер поддерживает не только HTML, но также XML и SVG. Класс Element служит базой для следующих классов: SVGElementXMLElement и HTMLElement.

#браузер #документ #свойства_узлов
👍3
HTMLElement – является базовым классом для всех остальных HTML-элементов.

От него наследуют конкретные элементы:
- HTMLInputElement – класс для тега <input>,
- HTMLBodyElement – класс для тега <body>,
- HTMLAnchorElement – класс для тега <a>,
…и т.д, каждому тегу соответствует свой класс, который предоставляет определённые свойства и методы.

#браузер #документ #свойства_узлов
👍4🔥2
Как узнать имя класса DOM-узла?

Есть 2 способа сделать это:
- вспомним, что обычно у объекта есть свойство constructor. Оно ссылается на конструктор класса, и в свойстве constructor.name содержится его имя
- мы можем просто привести его к строке

Например, для тега <body> JavaScript-класс HTMLBodyElement.

#браузер #документ #свойства_узлов
👍4🔥1