Марейн Хавербеке - Выразительный JavaScript
- Название:Выразительный JavaScript
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:978-1593275846
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Марейн Хавербеке - Выразительный JavaScript краткое содержание
В процессе чтения вы познакомитесь с основами программирования и, в частности, языка JavaScript, а также выполните несколько небольших проектов. Один из самых интересных проектов — создание своего языка программирования.
Выразительный JavaScript - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Для этого надо не только удалить картинки, но и добавить новые текстовые узлы им на замену. Для этого мы используем метод document.createTextNode
.
Это в
.
Заменить
function replaceImages() {
var images = document.body.getElementsByTagName("img");
for (var i = images.length - 1; i >= 0; i--) {
var image = images[i];
if (image.alt) {
var text = document.createTextNode(image.alt);
image.parentNode.replaceChild(text, image);
}
}
}
Получая строку, createTextNode
даёт нам тип 3 узла DOM (текстовый), который мы можем вставить в документ, чтобы он был показан на экране.
Цикл по картинкам начинается в конце списка узлов. Это сделано потому, что список узлов, возвращаемый методом getElementsByTagName
(или свойством childNodes
) постоянно обновляется при изменениях документа. Если б мы начали с начала, удаление первой картинки привело бы к потере списком первого элемента, и во время второго прохода цикла, когда i
равно 1, он бы остановился, потому что длина списка стала бы также равняться 1.
Если вам нужно работать с фиксированным списком узлов вместо «живого», можно преобразовать его в настоящий массив при помощи метода slice
.
var arrayish = {0: "один", 1: "два", length: 2};
var real = Array.prototype.slice.call(arrayish, 0);
real.forEach(function(elt) { console.log(elt); });
// → один
// два
Для создания узлов-элементов (тип 1) можно использовать document.createElement
. Метод принимает имя тега и возвращает новый пустой узел заданного типа. Следующий пример определяет инструмент elt
, создающий узел-элемент и использующий остальные аргументы в качестве его детей. Эта функция потом используется для добавления дополнительной информации к цитате.
Никакая книга не может быть закончена. Во время работы над ней мы узнаём достаточно для того, чтобы найти её незрелой сразу же после того, как мы отвлеклись от неё.
function elt(type) {
var node = document.createElement(type);
for (var i = 1; i < arguments.length; i++) {
var child = arguments[i];
if (typeof child == "string")
child = document.createTextNode(child);
node.appendChild(child);
}
return node;
}
document.getElementById("quote").appendChild(
elt("footer", "—",
elt("strong", "Карл Поппер"),
", предисловие ко второму изданию ",
elt("em", "Открытое общество и его враги "),
", 1950"));
Атрибуты
К некоторым элементам атрибутов, типа href
у ссылок, можно получить доступ через одноимённое свойство объекта. Это возможно для ограниченного числа часто используемых стандартных атрибутов.
Но HTML позволяет назначать узлам любые атрибуты. Это полезно, т. к. позволяет вам хранить дополнительную информацию в документе. Если вы придумаете свои названия атрибутов, их не будет среди свойств узла-элемента. Вместо этого вам надо будет использовать методы getAttribute
и setAttribute
для работы с ними.
Код запуска 00000000.
У кошки четыре ноги.
var paras = document.body.getElementsByTagName("p");
Array.prototype.forEach.call(paras, function(para) {
if (para.getAttribute("data-classified") == "secret")
para.parentNode.removeChild(para);
});
Рекомендую перед именами придуманных атрибутов ставить data-
, чтобы быть уверенным, что они не конфликтуют с любыми другими. В качестве простого примера мы напишем подсветку синтаксиса, который ищет теги
data-language
(язык) и довольно грубо пытается подсветить ключевые слова в языке.function highlightCode(node, keywords) {
var text = node.textContent;
node.textContent = ""; // Очистим узел
var match, pos = 0;
while (match = keywords.exec(text)) {
var before = text.slice(pos, match.index);
node.appendChild(document.createTextNode(before));
var strong = document.createElement("strong");
strong.appendChild(document.createTextNode(match[0]));
node.appendChild(strong);
pos = keywords.lastIndex;
}
var after = text.slice(pos);
node.appendChild(document.createTextNode(after));
}
Функция
highlightCode
принимает узел и регулярку (с включённой настройкой global), совпадающую с ключевым словом языка программирования, которое содержит элемент.Свойство
textContent
используется для получения всего текста узла, а затем устанавливается в пустую строку, что приводит к очищению узла. Мы в цикле проходим по всем вхождениям выражения keyword, добавляем между ними текст в виде простых текстовых узлов, а совпавший текст (ключевые слова) добавляем, заключая их в элементы (жирный шрифт).Мы можем автоматически подсветить весь код страницы, перебирая в цикле все элементы , у которых есть атрибут
data-language
, и вызывая на каждом highlightCodeс
правильной регуляркой.var languages = {
javascript: /\b(function|return|var)\b/g /* … etc */
};
function highlightAllCode() {
var pres = document.body.getElementsByTagName("pre");
for (var i = 0; i < pres.length; i++) {
var pre = pres[i];
var lang = pre.getAttribute("data-language");
if (languages.hasOwnProperty(lang))
highlightCode(pre, languages[lang]);
}
}
Вот пример:
А вот и она, функция идентификации:
function id(x) { return x; }
Есть один часто используемый атрибут,
class
, имя которого является ключевым словом в JavaScript. По историческим причинам, когда старые реализации JavaScript не умели обращаться с именами свойств, совпадавшими с ключевыми словами, этот атрибут доступен через свойство под названием className
. Вы также можете получить к нему доступ по его настоящему имени class
через методы getAttribute
и setAttribute
.Расположение элементов (layout)
Вы могли заметить, что разные типы элементов располагаются по-разному. Некоторые, типа параграфов
и заголовков
растягиваются на всю ширину документа и появляются на отдельных строках. Такие элементы называют блочными. Другие, как ссылки или жирный текст появляются на одной строчке с окружающим их текстом. Они называются встроенными (inline).
Для любого документа браузеры могут построить расположение элементов, расклад, в котором у каждого будет размер и положение на основе его типа и содержимого. Затем этот расклад используется для создания внешнего вида документа.
Размер и положение элемента можно узнать через JavaScript. Свойства
offsetWidth
и offsetHeight
выдают размер в пикселях, занимаемый элементом. Пиксель – основная единица измерений в браузерах, и обычно соответствует размеру минимальной точки экрана. Сходным образом, clientWidth
и clientHeight
дают размер внутренней части элемента, не включая ширину его границ (border).
Я в коробочке
var para = document.body.getElementsByTagName("p")[0];
console.log("clientHeight:", para.clientHeight);
console.log("offsetHeight:", para.offsetHeight);
Самый эффективный способ узнать точное расположение элемента на экране – метод
getBoundingClientRect
. Он возвращает объект со свойствами top
, bottom
, left
, и right
(сверху, снизу, слева и справа), которые содержат положение элемента относительно левого верхнего угла экрана в пикселях. Если вам надо получить эти данные относительно всего документа, вам надо прибавить текущую позицию прокрутки, которая содержится в глобальных переменных pageXOffset
и pageYOffset
.Разбор документа – задача сложная. В целях быстродействия браузерные движки не перестраивают документ каждый раз после его изменения, а ждут так долго, как это возможно. Когда программа JavaScript, изменившая документ, заканчивает работу, браузеру надо будет просчитать новую раскладку страницы, чтобы вывести изменённый документ на экран. Когда программа запрашивает позицию или размер чего-либо, читая свойства типа
offsetHeight
или вызывая getBoundingClientRect
, для предоставления корректной информации тоже необходимо рассчитывать раскладку.Программа, которая периодически считывает раскладку DOM и изменяет DOM, заставляет браузер много раз пересчитывать раскладку, и в связи с этим будет работать медленно. В следующем примере есть две разные программы, которые строят линию из символов X шириной в 2000 пикселей, и измеряют время работы.
function time(name, action) {
var start = Date.now(); // Текущее время в миллисекундах
action();
console.log(name, "заняло", Date.now() - start, "ms");
}
time("тупо", function() {
var target = document.getElementById("one");
while (target.offsetWidth < 2000)
target.appendChild(document.createTextNode("X"));
});
// → тупо заняло 32 ms
time("умно", function() {
var target = document.getElementById("two");
target.appendChild(document.createTextNode("XXXXX"));
var total = Math.ceil(2000 / (target.offsetWidth / 5));
for (var i = 5; i < total; i++)
target.appendChild(document.createTextNode("X"));
});
// → умно заняло 1 ms
Стили
Интервал:
Закладка: