minor renovations, beautify round 2 (final)

This commit is contained in:
Ilya Kantor 2015-03-12 10:26:02 +03:00
parent fad6615c42
commit 8410ce6421
212 changed files with 1981 additions and 1717 deletions

View file

@ -95,7 +95,7 @@ var border_left_width;
Есть причина и поважнее. Поскольку именно это имя переменной пришло в голову -- скорее всего, оно больше соответствует хранимым там данным, чем то, которое было мы придумали изначально. Исключения бывают, но в любом случае -- такое несовпадение -- это повод задуматься. Есть причина и поважнее. Поскольку именно это имя переменной пришло в голову -- скорее всего, оно больше соответствует хранимым там данным, чем то, которое было мы придумали изначально. Исключения бывают, но в любом случае -- такое несовпадение -- это повод задуматься.
Чтобы удобно переименовывать переменную, нужно использовать [хороший редактор JavaScript](/editors), тогда этот процесс будет очень простым и быстрым. Чтобы удобно переименовывать переменную, нужно использовать [хороший редактор JavaScript](/editor), тогда этот процесс будет очень простым и быстрым.
[smart header="Если коротко..."] [smart header="Если коротко..."]
Смысл имени переменной -- это "имя на коробке", по которому мы сможем максимально быстро находить нужные нам данные. Смысл имени переменной -- это "имя на коробке", по которому мы сможем максимально быстро находить нужные нам данные.

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View file

@ -15,7 +15,7 @@
<li>Все оставшиеся незачеркнутыми числа -- простые.</li> <li>Все оставшиеся незачеркнутыми числа -- простые.</li>
</ol> </ol>
Посмотрите также <a href="/files/tutorial/intro/array/sieve.gif">анимацию алгоритма</a>. Посмотрите также [анимацию алгоритма](sieve.gif).
Реализуйте "Решето Эратосфена" в JavaScript, используя массив. Реализуйте "Решето Эратосфена" в JavaScript, используя массив.

View file

@ -22,4 +22,4 @@ coffeeMachine.setOnReady(function() {
}); });
``` ```
Исходный код возьмите из решения [предыдущей задачи](/task/setter-onReady). Исходный код возьмите из решения [предыдущей задачи](/task/setter-onready).

View file

@ -10,7 +10,7 @@
var name = "Александр Пушкин"; var name = "Александр Пушкин";
name = name.replace(/([а-яё]+) ([а-яё]+)/i, "$2, $1"); name = name.replace(/([а-яё]+) ([а-яё]+)/i, "$2, $1");
alert(name); // Пушкин, Александр alert( name ); // Пушкин, Александр
``` ```
К скобочной группе можно также обратиться в самом шаблоне. К скобочной группе можно также обратиться в самом шаблоне.
@ -25,7 +25,7 @@ str = "He said:\"She's the one\"."
reg = /['"](.*?)['"]/g reg = /['"](.*?)['"]/g
alert( str.match(reg) ) // "She' alert(str.match(reg)) // "She'
``` ```
Как видно, регэксп нашёл открывающую кавычку <code class="match">"</code>, затем текст, вплоть до новой кавычки <code class="match">'</code>, которая закрывает соответствие. Как видно, регэксп нашёл открывающую кавычку <code class="match">"</code>, затем текст, вплоть до новой кавычки <code class="match">'</code>, которая закрывает соответствие.
@ -38,7 +38,7 @@ str = "He said:\"She's the one\"."
reg = /(['"])(.*?)\1/g reg = /(['"])(.*?)\1/g
alert( str.match(reg) ) // "She's the one" alert(str.match(reg)) // "She's the one"
``` ```
Теперь работает верно! Теперь работает верно!

View file

@ -14,7 +14,7 @@ var reg = /html|php|css|java(script)?/gi
var str = "Сначала появился HTML, затем CSS, потом JavaScript" var str = "Сначала появился HTML, затем CSS, потом JavaScript"
alert( str.match(reg) ) // 'HTML', 'CSS', 'JavaScript' alert(str.match(reg)) // 'HTML', 'CSS', 'JavaScript'
``` ```
**Альтернация имеет очень низкий приоритет.** **Альтернация имеет очень низкий приоритет.**

View file

@ -16,7 +16,7 @@
```js ```js
//+ run //+ run
var str = '100500 попугаев съели 500100 бананов!'; var str = '100500 попугаев съели 500100 бананов!';
alert( str.match( /\d+/ig ) // 100500, 500100 (все числа) alert(str.match(/\d+/ig) // 100500, 500100 (все числа)
``` ```
А с кареткой: А с кареткой:
@ -24,7 +24,7 @@ alert( str.match( /\d+/ig ) // 100500, 500100 (все числа)
```js ```js
//+ run //+ run
var str = '100500 попугаев съели 500100 бананов!'; var str = '100500 попугаев съели 500100 бананов!';
alert( str.match( /^\d+/ig ) // 100500 (только в начале строки)*!* alert(str.match(/^\d+/ig) // 100500 (только в начале строки)*!*
``` ```
Знак доллара <code class="pattern">$</code> используют, чтобы указать, что паттерн должен заканчиваться в конце текста. Знак доллара <code class="pattern">$</code> используют, чтобы указать, что паттерн должен заканчиваться в конце текста.
@ -34,7 +34,7 @@ alert( str.match( /^\d+/ig ) // 100500 (только в начале строк
```js ```js
//+ run //+ run
var str = '100500 попугаев съели 500100 бананов!'; var str = '100500 попугаев съели 500100 бананов!';
alert( str.match( /\d+$/ig ) // null (в начале строки чисел нет)*!* alert(str.match(/\d+$/ig) // null (в начале строки чисел нет)*!*
``` ```
Якоря используют одновременно, чтобы указать, что паттерн должен охватывать текст с начала и до конца. Обычно это требуется при валидации. Якоря используют одновременно, чтобы указать, что паттерн должен охватывать текст с начала и до конца. Обычно это требуется при валидации.
@ -46,7 +46,7 @@ alert( str.match( /\d+$/ig ) // null (в начале строки чисел
```js ```js
//+ run //+ run
var num = "ля-ля 12.34"; var num = "ля-ля 12.34";
alert( num.match( /\d+\.\d+/ig) ); // 12.34 alert( num.match(/\d+\.\d+/ig) ); // 12.34
``` ```
Если мы хотим проверить, что `num` *целиком* соответствует паттерну <code class="pattern">\d+\.\d+</code>, то укажем якоря по обе стороны от него: Если мы хотим проверить, что `num` *целиком* соответствует паттерну <code class="pattern">\d+\.\d+</code>, то укажем якоря по обе стороны от него:
@ -54,9 +54,9 @@ alert( num.match( /\d+\.\d+/ig) ); // 12.34
```js ```js
//+ run //+ run
var num = "ля-ля 12.34"; var num = "ля-ля 12.34";
alert( num.match( /^\d+\.\d+$/ig) ); // null, не дробь alert( num.match(/^\d+\.\d+$/ig) ); // null, не дробь
var num = "12.34"; var num = "12.34";
alert( num.match( /^\d+\.\d+$/ig) ); // 12.34, дробь! alert( num.match(/^\d+\.\d+$/ig) ); // 12.34, дробь!
``` ```

View file

@ -15,7 +15,7 @@ var str = '1е место: Винни-пух\n' +
'2е место: Пятачок\n' + '2е место: Пятачок\n' +
'33е место: Слонопотам'; '33е место: Слонопотам';
alert( str.match(/^\d+/gm ) ); // 1, 2, 33*!* alert( str.match(/^\d+/gm) ); // 1, 2, 33*!*
``` ```
Обратим внимание -- без флага <code class="pattern">/m</code> было бы только первое число: Обратим внимание -- без флага <code class="pattern">/m</code> было бы только первое число:
@ -26,7 +26,7 @@ var str = '1е место: Винни-пух\n' +
'2е место: Пятачок\n' + '2е место: Пятачок\n' +
'33е место: Слонопотам'; '33е место: Слонопотам';
alert( str.match(/^\d+/g ) ); // 1 alert( str.match(/^\d+/g) ); // 1
``` ```
Это потому что в обычном режиме каретка <code class="pattern">^</code> -- это только начало текста. Это потому что в обычном режиме каретка <code class="pattern">^</code> -- это только начало текста.

View file

@ -6,7 +6,7 @@ For example, <code class=pattern">\bdog\b</code> matches a standalone <code clas
```js ```js
//+ run //+ run
showMatch( "doggy catdog dog", /\bdog\b/ ) // "dog" showMatch("doggy catdog dog", /\bdog\b/) // "dog"
``` ```
Here, <code class="match">dog</code> matches, because the previous char is a space (non-wordly), and the next position is text end. Here, <code class="match">dog</code> matches, because the previous char is a space (non-wordly), and the next position is text end.
@ -16,14 +16,14 @@ If the word is long enough, it may match multiple times:
```js ```js
//+ run //+ run
showMatch( "Boombaroom", /\w{4}/g) // 'Boom', 'baro' showMatch("Boombaroom", /\w{4}/g) // 'Boom', 'baro'
``` ```
Appending <code class="pattern">\b</code> causes <code class="pattern">\w{4}\b</code> to match only at word end: Appending <code class="pattern">\b</code> causes <code class="pattern">\w{4}\b</code> to match only at word end:
```js ```js
//+ run //+ run
showMatch( "Because life is awesome", /\w{4}\b/g) // 'ause', 'life', 'some' showMatch("Because life is awesome", /\w{4}\b/g) // 'ause', 'life', 'some'
``` ```
**The word boundary <code class="pattern">\b</code> like <code class="pattern">^</code> and <code class="pattern">$</code> doesn't match a char. It only performs the check.** **The word boundary <code class="pattern">\b</code> like <code class="pattern">^</code> and <code class="pattern">$</code> doesn't match a char. It only performs the check.**
@ -32,7 +32,7 @@ Let's add the check from another side, <code class="pattern">\b\w{4}\b</code>:
```js ```js
//+ run //+ run
showMatch( "Because life is awesome", /\b\w{4}\b/g) // 'life' showMatch("Because life is awesome", /\b\w{4}\b/g) // 'life'
``` ```
Now there is only one result <code class="match">life</code>. Now there is only one result <code class="match">life</code>.

View file

@ -112,7 +112,7 @@ alert( result.index ); // undefined
var str = "Ой-йой-йой"; var str = "Ой-йой-йой";
// результат match не всегда массив! // результат match не всегда массив!
alert( str.match( /лю/gi ).length ) // ошибка! нет свойства length у null alert(str.match(/лю/gi).length) // ошибка! нет свойства length у null
``` ```
[/warn] [/warn]
@ -124,7 +124,7 @@ alert( str.match( /лю/gi ).length ) // ошибка! нет свойства l
```js ```js
//+ run //+ run
alert( '12-34-56'.split('-') ) // [12, 34, 56] alert('12-34-56'.split('-')) // [12, 34, 56]
``` ```
Можно передать в него и регулярное выражение, тогда он разобьёт строку по всем совпадениям. Можно передать в него и регулярное выражение, тогда он разобьёт строку по всем совпадениям.
@ -133,7 +133,7 @@ alert( '12-34-56'.split('-') ) // [12, 34, 56]
```js ```js
//+ run //+ run
alert( '12-34-56'.split(/-/) ) // [12, 34, 56] alert('12-34-56'.split(/-/)) // [12, 34, 56]
``` ```
## str.replace(reg, str|func) ## str.replace(reg, str|func)
@ -145,7 +145,7 @@ alert( '12-34-56'.split(/-/) ) // [12, 34, 56]
```js ```js
//+ run //+ run
// заменить дефис на двоеточие // заменить дефис на двоеточие
alert( '12-34-56'.replace("-", ":") ) // 12:34-56 alert('12-34-56'.replace("-", ":")) // 12:34-56
``` ```
**При вызове со строкой замены `replace` всегда заменяет только первое совпадение.** **При вызове со строкой замены `replace` всегда заменяет только первое совпадение.**
@ -198,7 +198,7 @@ alert( '12-34-56'.replace( *!*/-/g*/!*, ":" ) ) // 12:34:56
//+ run //+ run
var str = "Василий Пупкин"; var str = "Василий Пупкин";
alert( str.replace( /(Василий) (Пупкин)/ ,'$2, $1') ) // Пупкин, Василий alert(str.replace(/(Василий) (Пупкин)/, '$2, $1')) // Пупкин, Василий
``` ```
Ещё пример, с использованием `$&`: Ещё пример, с использованием `$&`:
@ -207,7 +207,7 @@ alert( str.replace( /(Василий) (Пупкин)/ ,'$2, $1') ) // Пупки
//+ run //+ run
var str = "Василий Пупкин"; var str = "Василий Пупкин";
alert( str.replace( /Василий Пупкин/ ,'Великий $&!') ) // Великий Василий Пупкин! alert(str.replace(/Василий Пупкин/, 'Великий $&!')) // Великий Василий Пупкин!
``` ```
**Для ситуаций, который требуют максимально "умной" замены, в качестве второго аргумента предусмотрена функция.** **Для ситуаций, который требуют максимально "умной" замены, в качестве второго аргумента предусмотрена функция.**
@ -221,9 +221,9 @@ alert( str.replace( /Василий Пупкин/ ,'Великий $&!') ) // В
var i = 0; var i = 0;
// заменить каждое вхождение "ой" на результат вызова функции // заменить каждое вхождение "ой" на результат вызова функции
alert( "ОЙ-Ой-ой".replace( /ой/gi, function() { alert("ОЙ-Ой-ой".replace(/ой/gi, function() {
return ++i; return ++i;
}) ); // 1-2-3 })); // 1-2-3
``` ```
В примере выше функция просто возвращала числа по очереди, но обычно она основывается на поисковых данных. В примере выше функция просто возвращала числа по очереди, но обычно она основывается на поисковых данных.
@ -245,12 +245,12 @@ alert( "ОЙ-Ой-ой".replace( /ой/gi, function() {
//+ run //+ run
// вывести и заменить все совпадения // вывести и заменить все совпадения
function replacer(str, offset, s) { function replacer(str, offset, s) {
alert("Найдено: " + str + " на позиции: " + offset + " в строке: " + s); alert( "Найдено: " + str + " на позиции: " + offset + " в строке: " + s );
return str.toLowerCase(); return str.toLowerCase();
} }
var result = "ОЙ-Ой-ой".replace( /ой/gi, replacer); var result = "ОЙ-Ой-ой".replace(/ой/gi, replacer);
alert('Результат: ' + result); // Результат: ой-ой-ой alert( 'Результат: ' + result ); // Результат: ой-ой-ой
``` ```
С двумя скобочными выражениями -- аргументов уже 5: С двумя скобочными выражениями -- аргументов уже 5:
@ -260,8 +260,8 @@ alert('Результат: ' + result); // Результат: ой-ой-ой
function replacer(str, name, surname, offset, s) { function replacer(str, name, surname, offset, s) {
return surname + ", " + name; return surname + ", " + name;
} }
alert( str.replace( /(Василий) (Пупкин)/ , replacer) ) // Пупкин, Василий alert(str.replace(/(Василий) (Пупкин)/, replacer)) // Пупкин, Василий
``` ```
Функция -- это самый мощный инструмент для замены, какой только может быть. Она владеет всей информацией о совпадении и имеет доступ к замыканию, поэтому может всё. Функция -- это самый мощный инструмент для замены, какой только может быть. Она владеет всей информацией о совпадении и имеет доступ к замыканию, поэтому может всё.
@ -319,14 +319,14 @@ var str = 'Многое по JavaScript можно найти на сайте ht
var regexp = /javascript/ig; var regexp = /javascript/ig;
alert("Начальное значение lastIndex: " + regexp.lastIndex); alert( "Начальное значение lastIndex: " + regexp.lastIndex );
while( result = regexp.exec(str) ) { while (result = regexp.exec(str)) {
alert('Найдено: ' + result[0] + ' на позиции:' + result.index); alert( 'Найдено: ' + result[0] + ' на позиции:' + result.index );
alert('Свойство lastIndex: ' + regexp.lastIndex); alert( 'Свойство lastIndex: ' + regexp.lastIndex );
} }
alert('Конечное значение lastIndex: ' + regexp.lastIndex); alert( 'Конечное значение lastIndex: ' + regexp.lastIndex );
``` ```
Здесь цикл продолжается до тех пор, пока `regexp.exec` не вернёт `null`, что означает "совпадений больше нет". Здесь цикл продолжается до тех пор, пока `regexp.exec` не вернёт `null`, что означает "совпадений больше нет".

View file

@ -114,21 +114,21 @@ alert( str.replace(/\D/g, "") ); // 79031234567
```js ```js
//+ run //+ run
alert( "1 - 5".match (/\d-\d/) ); // null, нет совпадений! alert( "1 - 5".match(/\d-\d/) ); // null, нет совпадений!
``` ```
Поправим это, добавив в регэксп пробелы: Поправим это, добавив в регэксп пробелы:
```js ```js
//+ run //+ run
alert( "1 - 5".match (/\d - \d/) ); // работает, пробелы вокруг дефиса alert( "1 - 5".match(/\d - \d/) ); // работает, пробелы вокруг дефиса
``` ```
В регулярные выражения также не надо вставлять лишние пробелы. Все символы имеют значение: В регулярные выражения также не надо вставлять лишние пробелы. Все символы имеют значение:
```js ```js
//+ run //+ run
alert( "1-5".match( /\d - \d/ ) ); // null, так как в строке 1-5 нет пробелов alert( "1-5".match(/\d - \d/) ); // null, так как в строке 1-5 нет пробелов
``` ```
## Класс точка ## Класс точка
@ -159,7 +159,7 @@ alert( "CS 4".match(re) ); // найдено "CS 4" (пробел тоже си
```js ```js
//+ run //+ run
alert( "CS4".match (/CS.4/) ); // нет совпадений, так как для точки нет символа alert( "CS4".match(/CS.4/) ); // нет совпадений, так как для точки нет символа
``` ```
## Экранирование специальных символов ## Экранирование специальных символов
@ -180,14 +180,14 @@ alert( "CS4".match (/CS.4/) ); // нет совпадений, так как д
```js ```js
//+ run //+ run
alert( "Глава 5.1".match( /\d\.\d/ ) ); // 5.1 alert( "Глава 5.1".match(/\d\.\d/) ); // 5.1
``` ```
Круглые скобки также являются специальными символами, так что для поиска именно скобки нужно использовать `\(`. Пример ниже ищет строку `"g()"`: Круглые скобки также являются специальными символами, так что для поиска именно скобки нужно использовать `\(`. Пример ниже ищет строку `"g()"`:
```js ```js
//+ run //+ run
alert( "function g()".match( /g\(\)/ ) ); // "g()" alert( "function g()".match(/g\(\)/) ); // "g()"
``` ```
Сам символ слэш `'/'`, хотя и не является специальными символом в регулярных выражениях, но открывает-закрывает регэксп в синтаксисе <code class="pattern">/...pattern.../</code>, поэтому его тоже нужно экранировать. Сам символ слэш `'/'`, хотя и не является специальными символом в регулярных выражениях, но открывает-закрывает регэксп в синтаксисе <code class="pattern">/...pattern.../</code>, поэтому его тоже нужно экранировать.
@ -196,7 +196,7 @@ alert( "function g()".match( /g\(\)/ ) ); // "g()"
```js ```js
//+ run //+ run
alert( "/".match( /\// ) ); // '/' alert( "/".match(/\//) ); // '/'
``` ```
Ну и, наконец, если нам нужно найти сам обратный слэш `\`, то его нужно просто задублировать. Ну и, наконец, если нам нужно найти сам обратный слэш `\`, то его нужно просто задублировать.
@ -205,7 +205,7 @@ alert( "/".match( /\// ) ); // '/'
```js ```js
//+ run //+ run
alert( "1\2".match( /\\/ ) ); // '\' alert( "1\2".match(/\\/) ); // '\'
``` ```
## Итого ## Итого

View file

@ -13,7 +13,7 @@
```js ```js
//+ run //+ run
// найти [г или т], а затем "оп" // найти [г или т], а затем "оп"
alert( "Гоп-стоп".match( /[гт]оп/gi ) ); // "Гоп", "топ" alert( "Гоп-стоп".match(/[гт]оп/gi) ); // "Гоп", "топ"
``` ```
Обратим внимание: несмотря на то, что в наборе указано несколько символов, в совпадении должен присутствовать *ровно один* из них. Обратим внимание: несмотря на то, что в наборе указано несколько символов, в совпадении должен присутствовать *ровно один* из них.
@ -23,7 +23,7 @@ alert( "Гоп-стоп".match( /[гт]оп/gi ) ); // "Гоп", "топ"
```js ```js
//+ run //+ run
// найти "В", затем [у или а], затем "ля" // найти "В", затем [у или а], затем "ля"
alert( "Вуаля".match( /В[уа]ля/ ) ); // совпадений нет alert( "Вуаля".match(/В[уа]ля/) ); // совпадений нет
``` ```
Поиск подразумевает: Поиск подразумевает:
@ -69,7 +69,7 @@ alert( "Exception 0xAF".match(/x[0-9A-F][0-9A-F]/g) );
//+ run //+ run
var str = "The sun is rising!"; var str = "The sun is rising!";
alert( str.match( /\w+/g ) ); // The, sun, is, rising*!* alert( str.match(/\w+/g) ); // The, sun, is, rising*!*
``` ```
А если есть слова и на русском? А если есть слова и на русском?
@ -78,7 +78,7 @@ alert( str.match( /\w+/g ) ); // The, sun, is, rising*!*
//+ run //+ run
var str = "Солнце встаёт!"; var str = "Солнце встаёт!";
alert( str.match( /\w+/g ) ); // null*!* alert( str.match(/\w+/g) ); // null*!*
``` ```
Ничего не найдено! Это можно понять, ведь <code class="pattern">\w</code> -- это именно английская букво-цифра, как можно видеть из аналога <code class="pattern">[a-zA-Z0-9_]</code>. Ничего не найдено! Это можно понять, ведь <code class="pattern">\w</code> -- это именно английская букво-цифра, как можно видеть из аналога <code class="pattern">[a-zA-Z0-9_]</code>.
@ -91,7 +91,7 @@ alert( str.match( /\w+/g ) ); // null*!*
//+ run //+ run
var str = "Солнце (the sun) встаёт!"; var str = "Солнце (the sun) встаёт!";
alert( str.match( /[\wа-я]+/gi ) ); // Солнце, the, sun, вста, т*!* alert( str.match(/[\wа-я]+/gi) ); // Солнце, the, sun, вста, т*!*
``` ```
...Присмотритесь внимательно к предыдущему примеру! Вы видите странность? Оно не находит букву <code class="match">ё</code>, более того -- считает её разрывом в слове. Причина -- в кодировке юникод, она подробно раскрыта в главе [](/string). ...Присмотритесь внимательно к предыдущему примеру! Вы видите странность? Оно не находит букву <code class="match">ё</code>, более того -- считает её разрывом в слове. Причина -- в кодировке юникод, она подробно раскрыта в главе [](/string).
@ -102,7 +102,7 @@ alert( str.match( /[\wа-я]+/gi ) ); // Солнце, the, sun, вста, т*!*
//+ run //+ run
var str = "Солнце (the sun) встаёт!"; var str = "Солнце (the sun) встаёт!";
alert( str.match( /[\wа-яё]+/gi ) ); // Солнце, the, sun, встаёт*!* alert( str.match(/[\wа-яё]+/gi) ); // Солнце, the, sun, встаёт*!*
``` ```
Теперь всё в порядке. Теперь всё в порядке.
@ -125,7 +125,7 @@ alert( str.match( /[\wа-яё]+/gi ) ); // Солнце, the, sun, встаёт*
```js ```js
//+ run //+ run
alert( "alice15@gmail.com".match( /[^\d\sA-Z]/gi ) ); // "@", "." alert( "alice15@gmail.com".match(/[^\d\sA-Z]/gi) ); // "@", "."
``` ```
## Не нужно экранирование ## Не нужно экранирование

View file

@ -4,6 +4,6 @@
```js ```js
//+ run //+ run
var reg = /\.{3,}/g; var reg = /\.{3,}/g;
alert("Привет!... Как дела?.....".match(reg)); // ..., ..... alert( "Привет!... Как дела?.....".match(reg) ); // ..., .....
``` ```

View file

@ -9,6 +9,6 @@
```js ```js
var reg = /ваше выражение/g; var reg = /ваше выражение/g;
alert("Привет!... Как дела?.....".match(reg)); // ..., ..... alert( "Привет!... Как дела?.....".match(reg) ); // ..., .....
``` ```

View file

@ -20,7 +20,7 @@
```js ```js
//+ run //+ run
alert( "Мне 12345 лет".match (/\d{5}/) ); // "12345" alert( "Мне 12345 лет".match(/\d{5}/) ); // "12345"
``` ```
</dd> </dd>
@ -29,14 +29,14 @@ alert( "Мне 12345 лет".match (/\d{5}/) ); // "12345"
```js ```js
//+ run //+ run
alert( "Мне не 12, а 1234 года".match( /\d{3,5}/ ) ); // "1234" alert( "Мне не 12, а 1234 года".match(/\d{3,5}/) ); // "1234"
``` ```
Последнее значение можно и не указывать. Тогда выражение <code class="pattern">\d{3,}</code> найдет числа, длиной от трех цифр: Последнее значение можно и не указывать. Тогда выражение <code class="pattern">\d{3,}</code> найдет числа, длиной от трех цифр:
```js ```js
//+ run //+ run
alert( "Мне не 12, а 345678 лет".match( /\d{3,5}/ ) ); // "345678" alert( "Мне не 12, а 345678 лет".match(/\d{3,5}/) ); // "345678"
``` ```
</dd> </dd>
</dl> </dl>
@ -47,7 +47,7 @@ alert( "Мне не 12, а 345678 лет".match( /\d{3,5}/ ) ); // "345678"
//+ run //+ run
var str = "+7(903)-123-45-67"; var str = "+7(903)-123-45-67";
alert( str.match( /\d{1,}/g ) ); // 7,903,123,45,67 alert( str.match(/\d{1,}/g) ); // 7,903,123,45,67
``` ```
@ -65,7 +65,7 @@ alert( str.match( /\d{1,}/g ) ); // 7,903,123,45,67
//+ run //+ run
var str = "+7(903)-123-45-67"; var str = "+7(903)-123-45-67";
alert( str.match( /\d+/g ) ); // 7,903,123,45,67 alert( str.match(/\d+/g) ); // 7,903,123,45,67
``` ```
</dd> </dd>
@ -80,7 +80,7 @@ alert( str.match( /\d+/g ) ); // 7,903,123,45,67
//+ run //+ run
var str = "Можно писать color или colour (британский вариант)"; var str = "Можно писать color или colour (британский вариант)";
alert( str.match( /colou?r/g ) ); // color, colour alert( str.match(/colou?r/g) ); // color, colour
``` ```
</dd> </dd>
@ -91,14 +91,14 @@ alert( str.match( /colou?r/g ) ); // color, colour
```js ```js
//+ run //+ run
alert( "100 10 1".match( /\d0*/g ) ); // 100, 10, 1 alert( "100 10 1".match(/\d0*/g) ); // 100, 10, 1
``` ```
Сравните это с `'+'` (один или более): Сравните это с `'+'` (один или более):
```js ```js
//+ run //+ run
alert( "100 10 1".match( /\d0+/g ) ); // 100, 10 alert( "100 10 1".match(/\d0+/g) ); // 100, 10
``` ```
</dd> </dd>
@ -115,7 +115,7 @@ alert( "100 10 1".match( /\d0+/g ) ); // 100, 10
В действии: В действии:
```js ```js
//+ run //+ run
alert( "0 1 12.345 7890".match( /\d+\.\d+/g ) ); // 123.45 alert( "0 1 12.345 7890".match(/\d+\.\d+/g) ); // 123.45
``` ```
</dd> </dd>
@ -124,7 +124,7 @@ alert( "0 1 12.345 7890".match( /\d+\.\d+/g ) ); // 123.45
```js ```js
//+ run //+ run
alert( "<BODY> ... </BODY>".match ( /<[a-z]+>/gi ) ); // <BODY> alert( "<BODY> ... </BODY>".match(/<[a-z]+>/gi) ); // <BODY>
``` ```
Это регулярное выражение ищет символ <code class="pattern">'&lt;'</code>, за которым идут одна или более букв английского алфавита, и затем <code class="pattern">'&gt;'</code>. Это регулярное выражение ищет символ <code class="pattern">'&lt;'</code>, за которым идут одна или более букв английского алфавита, и затем <code class="pattern">'&gt;'</code>.
@ -135,7 +135,7 @@ alert( "<BODY> ... </BODY>".match ( /<[a-z]+>/gi ) ); // <BODY>
```js ```js
//+ run //+ run
alert( "<h1>Привет!</h1>".match( /<[a-z][a-z0-9]*>/gi ) ); // <h1> alert( "<h1>Привет!</h1>".match(/<[a-z][a-z0-9]*>/gi) ); // <h1>
``` ```
</dd> </dd>
@ -144,7 +144,7 @@ alert( "<h1>Привет!</h1>".match( /<[a-z][a-z0-9]*>/gi ) ); // <h1>
```js ```js
//+ run //+ run
alert( "<h1>Привет!</h1>".match( /<\/?[a-z][a-z0-9]*>/gi ) ); // <h1>, </h1> alert( "<h1>Привет!</h1>".match(/<\/?[a-z][a-z0-9]*>/gi) ); // <h1>, </h1>
``` ```
</dd> </dd>

View file

@ -152,7 +152,7 @@ alert( str.match(reg) ); // witch, broom
```js ```js
//+ run //+ run
alert( "123 456".match ( /\d+ \d+?/g) ); // 123 4 alert( "123 456".match(/\d+ \d+?/g) ); // 123 4
``` ```
<ol> <ol>

View file

@ -4,7 +4,7 @@
У такого выделения есть два эффекта: У такого выделения есть два эффекта:
<ol> <ol>
<li>Он позволяет выделить часть совпадения в отдельный элемент массива при поиске через [:String#match] или [:RegExp#exec].</li> <li>Он позволяет выделить часть совпадения в отдельный элемент массива при поиске через [String#match](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/match) или [RegExp#exec](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec).</li>
<li>Если поставить квантификатор после скобки, то он применится *ко всей скобке*, а не всего лишь к одному символу.</li> <li>Если поставить квантификатор после скобки, то он применится *ко всей скобке*, а не всего лишь к одному символу.</li>
</ol> </ol>
@ -13,7 +13,7 @@
```js ```js
//+ run //+ run
alert( 'Gogogo now!'.match( /(go)+/i ); // "Gogogo" alert( 'Gogogo now!'.match(/(go)+/i ); // "Gogogo"
``` ```
Без скобок, шаблон <code class="pattern">/go+/</code> означал бы <code class="subject">g</code>, после которого идёт одна или более <code class="subject">o</code>, например: <code class="match">goooo</code>. Без скобок, шаблон <code class="pattern">/go+/</code> означал бы <code class="subject">g</code>, после которого идёт одна или более <code class="subject">o</code>, например: <code class="match">goooo</code>.
@ -25,17 +25,17 @@ alert( 'Gogogo now!'.match( /(go)+/i ); // "Gogogo"
Для удобства заключим его в скобки: <code class="pattern">&lt;(.*?)&gt;</code>. Тогда содержимое скобок можно будет получить отдельно. Для удобства заключим его в скобки: <code class="pattern">&lt;(.*?)&gt;</code>. Тогда содержимое скобок можно будет получить отдельно.
Используем метод [:String#match]. В результирующем массиве будет сначала всё совпадение, а далее -- скобочные группы, в данном случае -- только одна: Используем метод [String#match](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/match). В результирующем массиве будет сначала всё совпадение, а далее -- скобочные группы, в данном случае -- только одна:
```js ```js
//+ run //+ run
var str = '<h1>Привет, мир!</h1>' var str = '<h1>Привет, мир!</h1>'
var reg = /<(.*?)>/ var reg = /<(.*?)>/
alert( str.match(reg) ) // массив: <h1>, h1 alert(str.match(reg)) // массив: <h1>, h1
``` ```
Для поиска всех совпадений, как мы обсуждали ранее, используется метод [:RegExp#exec]. Для поиска всех совпадений, как мы обсуждали ранее, используется метод [RegExp#exec](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec).
**Скобки могут быть и вложенными. В этом случае нумерация также идёт слева направо.** **Скобки могут быть и вложенными. В этом случае нумерация также идёт слева направо.**
@ -49,7 +49,7 @@ var str = '<span class="my">';
reg = /<(([a-z])[a-z0-9]*).*?>/; reg = /<(([a-z])[a-z0-9]*).*?>/;
alert( str.match(reg) ); // <span class="my">, span, s alert( str.match(reg) ); // <span class="my">, span, s
``` ```
Вот так выглядят скобочные группы: Вот так выглядят скобочные группы:
@ -65,12 +65,12 @@ alert( str.match(reg) ); // <span class="my">, span, s
```js ```js
//+ run //+ run
match = 'a'.match( /a(z)?(c)?/ ) match = 'a'.match(/a(z)?(c)?/)
alert(match.length); // 3 alert( match.length ); // 3
alert(match[0]); // a alert( match[0] ); // a
alert(match[1]); // undefined alert( match[1] ); // undefined
alert(match[2]); // undefined alert( match[2] ); // undefined
``` ```
Массив получился длины `3`, но все скобочные группы -- `undefined`. Массив получился длины `3`, но все скобочные группы -- `undefined`.
@ -79,12 +79,12 @@ alert(match[2]); // undefined
```js ```js
//+ run //+ run
match = 'ack'.match( /a(z)?(c)?/ ) match = 'ack'.match(/a(z)?(c)?/)
alert(match.length); // 3 alert( match.length ); // 3
alert(match[0]); // ac, всё совпадение alert( match[0] ); // ac, всё совпадение
alert(match[1]); // undefined, для (z)? ничего нет alert( match[1] ); // undefined, для (z)? ничего нет
alert(match[2]); // c alert( match[2] ); // c
``` ```
Длина массива результатов по-прежнему `3`. Она постоянна. А вот для скобочной группы <code class="pattern">(z)?</code> в ней ничего нет. Длина массива результатов по-прежнему `3`. Она постоянна. А вот для скобочной группы <code class="pattern">(z)?</code> в ней ничего нет.

View file

@ -1,5 +1,3 @@
# Регулярные выражения [в работе] # Регулярные выражения [в работе]
Регулярные выражения -- мощный способ поиска и замены для строк. Регулярные выражения -- мощный способ поиска и замены для строк.
В JavaScript они поддерживаются в простом варианте, менее мощном, чем в большинстве других языков. Но зато нам будет проще их изучить.

View file

@ -13,11 +13,11 @@
alert( document.cookie ); alert( document.cookie );
``` ```
Эта строка состоит из пар `ключ=значение`, которые перечисляются через точку с запятой с пробелом `; `. Эта строка состоит из пар `ключ=значение`, которые перечисляются через точку с запятой с пробелом `"; "`.
Значит, чтобы прочитать cookie, достаточно разбить строку по `; `, и затем найти нужный ключ. Это можно делать либо через `split` и работу с массивом, либо через регулярное выражение. Значит, чтобы прочитать cookie, достаточно разбить строку по `"; "`, и затем найти нужный ключ. Это можно делать либо через `split` и работу с массивом, либо через регулярное выражение.
### Функция getCookie(name) ## Функция getCookie(name)
Следующая функция `getCookie(name)` возвращает cookie с именем `name`: Следующая функция `getCookie(name)` возвращает cookie с именем `name`:
@ -63,7 +63,7 @@ document.cookie = "userName=Vasya";
```js ```js
// +1 день от текущего момента // +1 день от текущего момента
var date = new Date; var date = new Date;
date.setDate( date.getDate() + 1 ); date.setDate(date.getDate() + 1);
alert( date.toUTCString() ); alert( date.toUTCString() );
``` ```
@ -78,8 +78,8 @@ alert( date.toUTCString() );
```js ```js
//+ run //+ run
var date = new Date( new Date().getTime() + 60*1000 ); var date = new Date(new Date().getTime() + 60 * 1000);
document.cookie="name=value; path=/; expires="+date.toUTCString(); document.cookie = "name=value; path=/; expires=" + date.toUTCString();
``` ```
Чтобы удалить это cookie: Чтобы удалить это cookie:
@ -87,12 +87,12 @@ document.cookie="name=value; path=/; expires="+date.toUTCString();
```js ```js
//+ run //+ run
var date = new Date(0); var date = new Date(0);
document.cookie="name=; path=/; expires="+date.toUTCString(); document.cookie = "name=; path=/; expires=" + date.toUTCString();
``` ```
При удалении значение не важно. Можно его не указывать, как сделано в коде выше. При удалении значение не важно. Можно его не указывать, как сделано в коде выше.
### Функция setCookie(name, value, options) ## Функция setCookie(name, value, options)
Если собрать все настройки воедино, вот такая функция ставит куки: Если собрать все настройки воедино, вот такая функция ставит куки:
@ -104,23 +104,23 @@ function setCookie(name, value, options) {
if (typeof expires == "number" && expires) { if (typeof expires == "number" && expires) {
var d = new Date(); var d = new Date();
d.setTime(d.getTime() + expires*1000); d.setTime(d.getTime() + expires * 1000);
expires = options.expires = d; expires = options.expires = d;
} }
if (expires && expires.toUTCString) { if (expires && expires.toUTCString) {
options.expires = expires.toUTCString(); options.expires = expires.toUTCString();
} }
value = encodeURIComponent(value); value = encodeURIComponent(value);
var updatedCookie = name + "=" + value; var updatedCookie = name + "=" + value;
for(var propName in options) { for (var propName in options) {
updatedCookie += "; " + propName; updatedCookie += "; " + propName;
var propValue = options[propName]; var propValue = options[propName];
if (propValue !== true) { if (propValue !== true) {
updatedCookie += "=" + propValue; updatedCookie += "=" + propValue;
} }
} }
document.cookie = updatedCookie; document.cookie = updatedCookie;
@ -137,7 +137,7 @@ function setCookie(name, value, options) {
<dt>expires</dt><dd>Время истечения cookie. Интерпретируется по-разному, в зависимости от типа: <dt>expires</dt><dd>Время истечения cookie. Интерпретируется по-разному, в зависимости от типа:
<ul> <ul>
<li>Число -- количество секунд до истечения. Например, `expires: 3600` -- кука на час.</li> <li>Число -- количество секунд до истечения. Например, `expires: 3600` -- кука на час.</li>
<li>Объект типа [:Date] -- дата истечения.</li> <li>Объект типа [Date](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Date) -- дата истечения.</li>
<li>Если expires в прошлом, то cookie будет удалено.</li> <li>Если expires в прошлом, то cookie будет удалено.</li>
<li>Если expires отсутствует или `0`, то cookie будет установлено как сессионное и исчезнет при закрытии браузера.</li> <li>Если expires отсутствует или `0`, то cookie будет установлено как сессионное и исчезнет при закрытии браузера.</li>
</ul> </ul>
@ -149,13 +149,15 @@ function setCookie(name, value, options) {
</dd> </dd>
</dl> </dl>
### Функция deleteCookie(name) ## Функция deleteCookie(name)
Здесь всё просто -- удаляем вызовом `setCookie` с датой в прошлом. Здесь всё просто -- удаляем вызовом `setCookie` с датой в прошлом.
```js ```js
function deleteCookie(name) { function deleteCookie(name) {
setCookie(name, "", { expires: -1 }) setCookie(name, "", {
expires: -1
})
} }
``` ```
@ -241,13 +243,13 @@ function deleteCookie(name) {
```js ```js
//+ run //+ run
if (!navigator.cookieEnabled) { if (!navigator.cookieEnabled) {
alert('Включите cookie для комфортной работы с этим сайтом'); alert( 'Включите cookie для комфортной работы с этим сайтом' );
} }
``` ```
...Конечно, предполагается, что включён JavaScript. Впрочем, посетитель без JS и cookie с большой вероятностью не человек, а бот.</li> ...Конечно, предполагается, что включён JavaScript. Впрочем, посетитель без JS и cookie с большой вероятностью не человек, а бот.</li>
</ul> </ul>
## Cookie.js ## Итого
Файл с функциями для работы с cookie: [cookie.js](/files/tutorial/browser/cookie/cookie.js). Файл с функциями для работы с cookie: [cookie.js](cookie.js).

View file

@ -11,7 +11,7 @@ animals.sort(function(a, b) {
}); });
*/!* */!*
alert(animals); // АИСТ,ёж,енот,ехидна,тигр,ЯК alert( animals ); // АИСТ,ёж,енот,ехидна,тигр,ЯК
``` ```
А вот, что было бы при обычном вызове `sort()`: А вот, что было бы при обычном вызове `sort()`:

View file

@ -9,7 +9,7 @@ var animals = ["тигр", "ёж", "енот", "ехидна", "АИСТ", "ЯК
// ... ваш код ... // ... ваш код ...
alert(animals); // АИСТ,ёж,енот,ехидна,тигр,ЯК alert( animals ); // АИСТ,ёж,енот,ехидна,тигр,ЯК
``` ```
В этом примере порядок сортировки не должен зависеть от регистра. В этом примере порядок сортировки не должен зависеть от регистра.

View file

@ -77,7 +77,7 @@
```js ```js
// создание // создание
var collator = new Intl.Collator([locales, [options] ]) var collator = new Intl.Collator([locales, [options]])
``` ```
Параметры: Параметры:
@ -131,7 +131,9 @@ alert( collator.compare("ёжик", "яблоко") ); // -1 (ёжик мень
var collator = new Intl.Collator(); var collator = new Intl.Collator();
alert( collator.compare("ЁжиК", "ёжик") ); // 1, разные alert( collator.compare("ЁжиК", "ёжик") ); // 1, разные
var collator = new Intl.Collator(undefined, { sensitivity: "accent" } ); var collator = new Intl.Collator(undefined, {
sensitivity: "accent"
});
alert( collator.compare("ЁжиК", "ёжик") ); // 0, одинаковые alert( collator.compare("ЁжиК", "ёжик") ); // 0, одинаковые
``` ```
@ -141,7 +143,7 @@ alert( collator.compare("ЁжиК", "ёжик") ); // 0, одинаковые
```js ```js
// создание // создание
var formatter = new Intl.DateFormatter([locales, [options] ]) var formatter = new Intl.DateFormatter([locales, [options]])
``` ```
Первый аргумент -- такой же, как и в `Collator`, а в объекте `options` мы можем определить, какие именно части даты показывать (часы, месяц, год...) и в каком формате. Первый аргумент -- такой же, как и в `Collator`, а в объекте `options` мы можем определить, какие именно части даты показывать (часы, месяц, год...) и в каком формате.
@ -281,13 +283,13 @@ alert( formatter.format(date) ); // 12/31/2014
var date = new Date(2014, 11, 31, 12, 30, 0); var date = new Date(2014, 11, 31, 12, 30, 0);
var formatter = new Intl.DateTimeFormat("ru", { var formatter = new Intl.DateTimeFormat("ru", {
weekday: "long", weekday: "long",
year: "numeric", year: "numeric",
month: "long", month: "long",
day: "numeric" day: "numeric"
}); });
alert( formatter.format(date) ); // среда, 31 декабря 2014 г. alert( formatter.format(date) ); // среда, 31 декабря 2014 г.
``` ```
Только время: Только время:
@ -297,12 +299,12 @@ alert( formatter.format(date) ); // среда, 31 декабря 2014 г.
var date = new Date(2014, 11, 31, 12, 30, 0); var date = new Date(2014, 11, 31, 12, 30, 0);
var formatter = new Intl.DateTimeFormat("ru", { var formatter = new Intl.DateTimeFormat("ru", {
hour: "numeric" , hour: "numeric",
minute: "numeric" , minute: "numeric",
second: "numeric" second: "numeric"
}); });
alert( formatter.format(date) ); // 12:30:00 alert( formatter.format(date) ); // 12:30:00
``` ```
## Числа: Intl.NumberFormat ## Числа: Intl.NumberFormat
@ -312,7 +314,7 @@ alert( formatter.format(date) ); // 12:30:00
Синтаксис: Синтаксис:
```js ```js
var formatter = new Intl.NumberFormat([locales [, options] ]); var formatter = new Intl.NumberFormat([locales[, options]]);
formatter.format(number); // форматирование formatter.format(number); // форматирование
``` ```
@ -398,7 +400,7 @@ formatter.format(number); // форматирование
```js ```js
//+ run //+ run
var formatter = new Intl.NumberFormat("ru"); var formatter = new Intl.NumberFormat("ru");
alert(formatter.format(1234567890.123)); // 1 234 567 890,123 alert( formatter.format(1234567890.123) ); // 1 234 567 890,123
``` ```
С ограничением значимых цифр (важны только первые 3): С ограничением значимых цифр (важны только первые 3):
@ -408,7 +410,7 @@ alert(formatter.format(1234567890.123)); // 1 234 567 890,123
var formatter = new Intl.NumberFormat("ru", { var formatter = new Intl.NumberFormat("ru", {
maximumSignificantDigits: 3 maximumSignificantDigits: 3
}); });
alert(formatter.format(1234567890.123)); // 1 230 000 000 alert( formatter.format(1234567890.123) ); // 1 230 000 000
``` ```
C опциями для валюты: C опциями для валюты:
@ -419,7 +421,7 @@ var formatter = new Intl.NumberFormat("ru", {
currency: "GBP" currency: "GBP"
}); });
alert( formatter.format(1234.5)); // 1 234,5 £ alert( formatter.format(1234.5) ); // 1 234,5 £
``` ```
С двумя цифрами после запятой: С двумя цифрами после запятой:
@ -431,7 +433,7 @@ var formatter = new Intl.NumberFormat("ru", {
minimumFractionDigits: 2 minimumFractionDigits: 2
}); });
alert( formatter.format(1234.5)); // 1 234,50 £ alert( formatter.format(1234.5) ); // 1 234,50 £
``` ```
## Методы в Date, String, Number ## Методы в Date, String, Number
@ -454,7 +456,7 @@ alert( str.localeCompare("яблоко", "ru") ); // -1
<dd>Форматирует дату в соответствии с локалью, например: <dd>Форматирует дату в соответствии с локалью, например:
```js ```js
//+ run //+ run no-beautify
var date = new Date(2014, 11, 31, 12, 00); var date = new Date(2014, 11, 31, 12, 00);
alert( date.toLocaleString("ru", { year: 'numeric', month: 'long' }) ); // Декабрь 2014 alert( date.toLocaleString("ru", { year: 'numeric', month: 'long' }) ); // Декабрь 2014

View file

@ -2,7 +2,7 @@
Регулярные выражения в javascript немного странные. Вроде - перловые, обычные, но с подводными камнями, на которые натыкаются даже опытные javascript-разработчики. Регулярные выражения в javascript немного странные. Вроде - перловые, обычные, но с подводными камнями, на которые натыкаются даже опытные javascript-разработчики.
Эта статья ставит целью перечислить неожиданные фишки и особенности [:RegExp] в краткой и понятной форме. Эта статья ставит целью перечислить неожиданные фишки и особенности `RegExp` в краткой и понятной форме.
[cut] [cut]
@ -18,12 +18,12 @@
//+ run //+ run
function bbtagit(text) { function bbtagit(text) {
text = text.replace(/\[u\](.*?)\[\/u\]/gim, '<u>$1</u>') text = text.replace(/\[u\](.*?)\[\/u\]/gim, '<u>$1</u>')
return text return text
} }
var line = "[u]мой\n текст[/u]" var line = "[u]мой\n текст[/u]"
alert( bbtagit(line) ) alert(bbtagit(line))
``` ```
Попробуйте запустить. Заменяет? Как бы не так! Попробуйте запустить. Заменяет? Как бы не так!
@ -38,12 +38,12 @@ alert( bbtagit(line) )
//+ run //+ run
function bbtagit(text) { function bbtagit(text) {
text = text.replace(/\[u\]([\s\S]*)\[\/u\]/gim, '<u>$1</u>') text = text.replace(/\[u\]([\s\S]*)\[\/u\]/gim, '<u>$1</u>')
return text return text
} }
var line = "[u]мой\n текст[/u]" var line = "[u]мой\n текст[/u]"
alert( bbtagit(line) ) alert(bbtagit(line))
``` ```
## Жадность ## Жадность
@ -103,7 +103,7 @@ alert(text)
//+ run //+ run
text = ' [b]a [u]b[/u] c [/b] ' text = ' [b]a [u]b[/u] c [/b] '
var reg = /\[([bus])\](.*?)\[\//*u*/\1/*/u*/\]/ var reg = /\[([bus])\](.*?)\[\// * u * /\1/ * /u*/\] /
text = text.replace(reg, '<$1>$2</$1>') text = text.replace(reg, '<$1>$2</$1>')
alert(text) alert(text)
``` ```
@ -120,7 +120,7 @@ P.S. Понятно, что при таком способе поиска bb-т
### Заменить все ### Заменить все
Для замены всех вхождений используется метод [:String#replace|]. Для замены всех вхождений используется метод [String#replace](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/replace).
Он интересен тем, что допускает первый аргумент - регэксп или строку. Он интересен тем, что допускает первый аргумент - регэксп или строку.
Если первый аргумент - строка, то будет осуществлен поиск подстроки, без преобразования в регулярное выражение. Если первый аргумент - строка, то будет осуществлен поиск подстроки, без преобразования в регулярное выражение.
@ -134,7 +134,7 @@ alert("2 ++ 1".replace("+", "*"))
Как видите, заменился только один плюс, а не оба. Как видите, заменился только один плюс, а не оба.
**Чтобы заменить все вхождения, [:String#replace|] обязательно нужно использовать с регулярным выражением.** **Чтобы заменить все вхождения, [String#replace](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/replace) обязательно нужно использовать с регулярным выражением.**
В режиме регулярного выражения плюс придётся экранировать, но зато <code>replace</code> заменит все вхождения (при указании флага <code>g</code>): В режиме регулярного выражения плюс придётся экранировать, но зато <code>replace</code> заменит все вхождения (при указании флага <code>g</code>):
@ -152,7 +152,7 @@ alert("2 ++ 1".replace(/\+/g, "*"))
Следующий пример произведет операции вычитания: Следующий пример произведет операции вычитания:
```js ```js
//+ run //+ run no-beautify
var str = "count 36 - 26, 18 - 9" var str = "count 36 - 26, 18 - 9"
str = str.replace(/(\d+) - (\d+)/g, function(a,b,c) { return b-c }) str = str.replace(/(\d+) - (\d+)/g, function(a,b,c) { return b-c })
alert(str) alert(str)
@ -161,32 +161,32 @@ alert(str)
### Найти всё ### Найти всё
В javascript нет одного универсального метода для поиска всех совпадений. В javascript нет одного универсального метода для поиска всех совпадений.
Для поиска без запоминания скобочных групп - можно использовать [:String#match|]: Для поиска без запоминания скобочных групп - можно использовать [String#match](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/match):
```js ```js
//+ run //+ run
var str = "count 36-26, 18-9" var str = "count 36-26, 18-9"
var re = /(\d+)-(\d+)/g var re = /(\d+)-(\d+)/g
result = str.match(re) result = str.match(re)
for(var i=0; i<result.length; i++) alert(result[i]) for (var i = 0; i < result.length; i++) alert(result[i])
``` ```
Как видите, оно исправно ищет все совпадения (флаг <code>'g'</code> у регулярного выражения обязателен), но при этом не запоминает скобочные группы. Эдакий "облегченный вариант". Как видите, оно исправно ищет все совпадения (флаг <code>'g'</code> у регулярного выражения обязателен), но при этом не запоминает скобочные группы. Эдакий "облегченный вариант".
### Найти всё с учётом скобочных групп ### Найти всё с учётом скобочных групп
В сколько-нибудь сложных задачах важны не только совпадения, но и скобочные группы. Чтобы их найти, предлагается использовать многократный вызов [:RegExp#exec|]. В сколько-нибудь сложных задачах важны не только совпадения, но и скобочные группы. Чтобы их найти, предлагается использовать многократный вызов [RegExp#exec](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec).
Для этого регулярное выражение должно использовать флаг <code>'g'</code>. Тогда результат поиска, запомненный в свойстве <code>lastIndex</code> объекта <code>RegExp</code> используется как точка отсчета для следующего поиска: Для этого регулярное выражение должно использовать флаг <code>'g'</code>. Тогда результат поиска, запомненный в свойстве <code>lastIndex</code> объекта <code>RegExp</code> используется как точка отсчета для следующего поиска:
```js ```js
//+ run //+ run
var str = "count 36-26, 18-9" var str = "count 36-26, 18-9"
var re = /(\d+)-(\d+)/g var re = /(\d+)-(\d+)/g
var res var res
while ( (res = re.exec(str)) != null) { while ((res = re.exec(str)) != null) {
alert("Найдено " + res[0] + ": ("+ res[1]+") и ("+res[2]+")") alert("Найдено " + res[0] + ": (" + res[1] + ") и (" + res[2] + ")")
alert("Дальше ищу с позиции "+re.lastIndex) alert("Дальше ищу с позиции " + re.lastIndex)
} }
``` ```

View file

@ -16,6 +16,7 @@
Пример: Пример:
```html ```html
<!--+ no-beautify -->
<div class="menu"> <div class="menu">
<span class="title"><%-title%></span> <span class="title"><%-title%></span>
<ul> <ul>
@ -129,6 +130,7 @@ alert( compiled() ); // <div>Привет</div>
Шаблон для меню в Handlerbars, к примеру, будет выглядеть так: Шаблон для меню в Handlerbars, к примеру, будет выглядеть так:
```html ```html
<!--+ no-beautify -->
<div class="menu"> <div class="menu">
<span class="title">{{title}}</span> <span class="title">{{title}}</span>
<ul> <ul>
@ -151,7 +153,7 @@ var compiled = Handlebars.compile(tmpl);
var result = compiled({ var result = compiled({
title: "Сладости", title: "Сладости",
items: [ "Торт", "Пирожное", "Пончик" ] items: ["Торт", "Пирожное", "Пончик"]
}); });
``` ```
@ -228,7 +230,7 @@ ko.applyBindings(user, document.body);
Например: Например:
```html ```html
<!--+ run --> <!--+ run no-beautify -->
<script src="http://knockoutjs.com/downloads/knockout-3.1.0.js"></script> <script src="http://knockoutjs.com/downloads/knockout-3.1.0.js"></script>
<script> <script>

View file

@ -17,7 +17,7 @@ CSS стоит изучать по одной из этих книг. Можно
<i>Эрик Мейер</i></li> <i>Эрик Мейер</i></li>
</ul> </ul>
Конечно, [стандарт CSS 2.1](http://specs.operafan.net/css2.1RU/CSS21/visuren.html) тоже будет вам в помощь. Подчас его скупая простота и точность гораздо понятнее, чем много страниц разъяснений. Конечно, [стандарты](http://www.w3.org/Style/CSS/) тоже будут полезны. Подчас их точность куда проще, чем много страниц разъяснений.
## JavaScript ## JavaScript

View file

@ -16,6 +16,7 @@
Полифилл для `setImmediate` через `postMessage`: Полифилл для `setImmediate` через `postMessage`:
```js ```js
//+ no-beautify
if (!window.setImmediate) window.setImmediate = (function() { if (!window.setImmediate) window.setImmediate = (function() {
var head = { }, tail = head; // очередь вызовов, 1-связный список var head = { }, tail = head; // очередь вызовов, 1-связный список

View file

@ -59,7 +59,7 @@ var func = bindLate(obj, "method");
Код: Код:
```js ```js
function bindLate(context, funcName) { function bindLate(context, funcName) {
return function() { return function() {
return context[funcName].apply(context, arguments); return context[funcName].apply(context, arguments);
}; };
@ -138,7 +138,7 @@ userSayHi(); // Метод работает: *!*Привет!*/!*
Обёртка для позднего связывания (без карринга): Обёртка для позднего связывания (без карринга):
```js ```js
function bindLate(context, funcName) { function bindLate(context, funcName) {
return function() { return function() {
return context[funcName].apply(context, arguments); return context[funcName].apply(context, arguments);
}; };

View file

@ -50,25 +50,25 @@ HTML:
</button> </button>
<script> <script>
function domRangeCreate() { function domRangeCreate() {
// Найдем корневой контейнер // Найдем корневой контейнер
var root = document.getElementById('ex2'); var root = document.getElementById('ex2');
// Найдем контейнеры граничных точек (в данном случае тестовые) // Найдем контейнеры граничных точек (в данном случае тестовые)
var start = root.getElementsByTagName('h2')[0].firstChild; var start = root.getElementsByTagName('h2')[0].firstChild;
var end = root.getElementsByTagName('p')[0].firstChild; var end = root.getElementsByTagName('p')[0].firstChild;
if (root.createRange) { if (root.createRange) {
// Создаем Range // Создаем Range
var rng = root.createRange(); var rng = root.createRange();
// Задаем верхнюю граничную точку, передав контейнер и смещение // Задаем верхнюю граничную точку, передав контейнер и смещение
rng.setStart( start, 3 ); rng.setStart(start, 3);
// Аналогично для нижней границы // Аналогично для нижней границы
rng.setEnd( end, 10 ); rng.setEnd(end, 10);
// Теперь мы можем вернуть текст, который содержится в полученной области // Теперь мы можем вернуть текст, который содержится в полученной области
return rng.toString(); return rng.toString();
} else { } else {
return 'Вероятно, у вас IE8-, смотрите реализацию TextRange ниже'; return 'Вероятно, у вас IE8-, смотрите реализацию TextRange ниже';
}
} }
}
</script> </script>
``` ```
@ -99,9 +99,9 @@ function domRangeCreate() {
```js ```js
var rng = document.createRange(); var rng = document.createRange();
// Установит верхнюю граничную точку по левой границе спана #s1 // Установит верхнюю граничную точку по левой границе спана #s1
rng.setStartBefore( document.getElementById('s1') ); rng.setStartBefore(document.getElementById('s1'));
// Установит нижнюю граничную точку по правой границе спана #s2 // Установит нижнюю граничную точку по правой границе спана #s2
rng.setEndAfter( document.getElementById('s2') ); rng.setEndAfter(document.getElementById('s2'));
``` ```
</li> </li>
@ -129,32 +129,32 @@ rng.setEndAfter( document.getElementById('s2') );
</div> </div>
<script> <script>
function domRangeHighlight(text) { function domRangeHighlight(text) {
// Получим текстовый узел // Получим текстовый узел
var root = document.getElementById('ex3').firstChild; var root = document.getElementById('ex3').firstChild;
// и его содержимое // и его содержимое
var content = root.nodeValue; var content = root.nodeValue;
// Проверим есть ли совпадения с переданным текстом // Проверим есть ли совпадения с переданным текстом
if ( ~content.indexOf( text ) ) { if (~content.indexOf(text)) {
if ( document.createRange ) { if (document.createRange) {
// Если есть совпадение, и браузер поддерживает Range, создаем объект // Если есть совпадение, и браузер поддерживает Range, создаем объект
var rng = document.createRange(); var rng = document.createRange();
// Ставим верхнюю границу по индексу совпадения, // Ставим верхнюю границу по индексу совпадения,
rng.setStart( root, content.indexOf( text ) ); rng.setStart(root, content.indexOf(text));
// а нижнюю по индексу + длина текста // а нижнюю по индексу + длина текста
rng.setEnd( root, content.indexOf( text ) + text.length ); rng.setEnd(root, content.indexOf(text) + text.length);
// Создаем спан с синим фоном // Создаем спан с синим фоном
var highlightDiv = document.createElement('span'); var highlightDiv = document.createElement('span');
highlightDiv.style.backgroundColor = 'blue'; highlightDiv.style.backgroundColor = 'blue';
// Обернем наш Range в спан // Обернем наш Range в спан
rng.surroundContents( highlightDiv ); rng.surroundContents(highlightDiv);
} else {
alert( 'Вероятно, у вас IE8-, смотрите реализацию TextRange ниже' );
}
} else { } else {
alert('Вероятно, у вас IE8-, смотрите реализацию TextRange ниже'); alert( 'Совпадений не найдено' );
} }
} else {
alert('Совпадений не найдено');
} }
}
</script> </script>
``` ```
@ -177,19 +177,19 @@ function domRangeHighlight(text) {
<input id="buttonId" type="button" value="Test button" onclick="alert( ieTextRangeCreate() );" /> <input id="buttonId" type="button" value="Test button" onclick="alert( ieTextRangeCreate() );" />
<script> <script>
function ieTextRangeCreate() { function ieTextRangeCreate() {
// Найдем кнопку // Найдем кнопку
var button = document.getElementById('buttonId'); var button = document.getElementById('buttonId');
// Если мы в ИЕ // Если мы в ИЕ
if ( button.createTextRange && button.createTextRange() != undefined ) { if (button.createTextRange && button.createTextRange() != undefined) {
// Создаем TextRange // Создаем TextRange
var rng = button.createTextRange(); var rng = button.createTextRange();
// И вернем текстовое содержимое полученного объекта // И вернем текстовое содержимое полученного объекта
return rng.text; return rng.text;
} else { } else {
return 'Вероятно, у вас не IE, смотрите реализацию Range выше'; return 'Вероятно, у вас не IE, смотрите реализацию Range выше';
}
} }
}
</script> </script>
``` ```
@ -239,30 +239,30 @@ function ieTextRangeCreate() {
</div> </div>
<script> <script>
function ieTextRangeHighlight(text) { function ieTextRangeHighlight(text) {
// Получим ссылку на элемент, в котором будет происходить поиск // Получим ссылку на элемент, в котором будет происходить поиск
var root = document.getElementById('ex4'); var root = document.getElementById('ex4');
// Получим значение его текстового потомка // Получим значение его текстового потомка
var content = root.firstChild.nodeValue; var content = root.firstChild.nodeValue;
// Если есть совпадение // Если есть совпадение
if ( ~content.indexOf(text) ) { if (~content.indexOf(text)) {
// и мы в MSIE // и мы в MSIE
if ( document.body.createTextRange ) { if (document.body.createTextRange) {
// Создадим объект TextRange // Создадим объект TextRange
var rng = document.body.createTextRange(); var rng = document.body.createTextRange();
// Свернем его до root // Свернем его до root
rng.moveToElementText( root ); rng.moveToElementText(root);
// Найдем текст и свернем диапазон до него // Найдем текст и свернем диапазон до него
if ( rng.findText( text ) ) if (rng.findText(text))
// Заменим текстовый фрагмент на span с синим фоном // Заменим текстовый фрагмент на span с синим фоном
rng.pasteHTML( '<span style="background:blue;">' + text + '</span>' ); rng.pasteHTML('<span style="background:blue;">' + text + '</span>');
} else {
alert( 'Вероятно, у вас не IE, смотрите реализацию Range выше' );
}
} else { } else {
alert('Вероятно, у вас не IE, смотрите реализацию Range выше'); alert( 'Совпадений не найдено' );
} }
} else {
alert('Совпадений не найдено');
} }
}
</script> </script>
``` ```
@ -281,6 +281,7 @@ function ieTextRangeHighlight(text) {
Эту задачу мы уже решали в самом начале статьи <a href="#demo-mix">в примере с миксом</a>. Теперь рассмотрим код: Эту задачу мы уже решали в самом начале статьи <a href="#demo-mix">в примере с миксом</a>. Теперь рассмотрим код:
```js ```js
//+ no-beautify
function getSelectionText() { function getSelectionText() {
var txt = ''; var txt = '';
if (txt = window.getSelection) // Не IE, используем метод getSelection if (txt = window.getSelection) // Не IE, используем метод getSelection
@ -342,21 +343,21 @@ IE предоставляет собственный интерфейс взаи
</div> </div>
<script> <script>
function setSelection() { function setSelection() {
var target = document.getElementById('ex5').getElementsByTagName('span')[0]; var target = document.getElementById('ex5').getElementsByTagName('span')[0];
var rng, sel; var rng, sel;
if ( document.createRange ) { if (document.createRange) {
rng = document.createRange(); rng = document.createRange();
rng.selectNode( target ) rng.selectNode(target)
sel = window.getSelection(); sel = window.getSelection();
sel.removeAllRanges(); sel.removeAllRanges();
sel.addRange( rng ); sel.addRange(rng);
} else { } else {
var rng = document.body.createTextRange(); var rng = document.body.createTextRange();
rng.moveToElementText( target ); rng.moveToElementText(target);
rng.select(); rng.select();
}
} }
}
</script> </script>
``` ```
@ -372,7 +373,7 @@ function clearSelection() {
try { try {
// современный объект Selection // современный объект Selection
window.getSelection().removeAllRanges(); window.getSelection().removeAllRanges();
} catch(e) { } catch (e) {
// для IE8- // для IE8-
document.selection.empty(); document.selection.empty();
} }
@ -393,15 +394,15 @@ function clearSelection() {
```js ```js
var range = getRangeObject(); var range = getRangeObject();
if(range) { if (range) {
alert(range); alert( range );
alert(range.startContainer.nodeValue); alert( range.startContainer.nodeValue );
alert(range.startOffset); alert( range.startOffset );
alert(range.endOffset); alert( range.endOffset );
} else { } else {
alert('Ничего не выделено'); alert( 'Ничего не выделено' );
}
} }
}
``` ```
В действии: В действии:

View file

@ -29,7 +29,7 @@ window.open('http://ya.ru');
```js ```js
//+ run //+ run
document.body.style.background = 'red'; document.body.style.background = 'red';
alert('Элемент BODY стал красным, а сейчас обратно вернётся'); alert( 'Элемент BODY стал красным, а сейчас обратно вернётся' );
document.body.style.background = ''; document.body.style.background = '';
``` ```
@ -57,7 +57,7 @@ BOM -- это объекты для работы с чем угодно, кро
Пример использования: Пример использования:
```js ```js
//+ run //+ run
alert(location.href); // выведет текущий адрес alert( location.href ); // выведет текущий адрес
``` ```
Большинство возможностей BOM стандартизированы в [HTML 5](http://www.w3.org/TR/html5/Overview.html), хотя различные браузеры и предоставляют зачастую что-то своё, в дополнение к стандарту. Большинство возможностей BOM стандартизированы в [HTML 5](http://www.w3.org/TR/html5/Overview.html), хотя различные браузеры и предоставляют зачастую что-то своё, в дополнение к стандарту.

View file

@ -57,21 +57,21 @@ var result = nodeA.compareDocumentPosition(nodeB);
</ul> </ul>
<script> <script>
var p = document.body.children[0]; var p = document.body.children[0];
var ul = document.body.children[1]; var ul = document.body.children[1];
var li = ul.children[0]; var li = ul.children[0];
// 1. <ul> находится после <p> // 1. <ul> находится после <p>
alert( ul.compareDocumentPosition( p ) ); // 2 = 10 alert( ul.compareDocumentPosition(p) ); // 2 = 10
// 2. <p> находится до <ul> // 2. <p> находится до <ul>
alert( p.compareDocumentPosition( ul ) ); // 4 = 100 alert( p.compareDocumentPosition(ul) ); // 4 = 100
// 3. <ul> родитель <li> // 3. <ul> родитель <li>
alert( ul.compareDocumentPosition( li ) ); // 20 = 10100 alert( ul.compareDocumentPosition(li) ); // 20 = 10100
// 4. <ul> потомок <body> // 4. <ul> потомок <body>
alert( ul.compareDocumentPosition( document.body ) ); // 10 = 1010 alert( ul.compareDocumentPosition(document.body) ); // 10 = 1010
</script> </script>
``` ```
@ -111,13 +111,13 @@ alert( 20..toString(2) );
</ul> </ul>
<script> <script>
var body = document.body; var body = document.body;
var li = document.body.children[0].children[0]; var li = document.body.children[0].children[0];
*!* *!*
if( body.compareDocumentPosition(li) & 16 ) { if (body.compareDocumentPosition(li) & 16) {
alert( body +' содержит ' + li ); alert( body + ' содержит ' + li );
} }
*/!* */!*
</script> </script>
``` ```
@ -139,18 +139,17 @@ if( body.compareDocumentPosition(li) & 16 ) {
```js ```js
// код с http://compatibility.shwups-cms.ch/en/polyfills/?&id=82 // код с http://compatibility.shwups-cms.ch/en/polyfills/?&id=82
(function(){ (function() {
var el = document.documentElement; var el = document.documentElement;
if( !el.compareDocumentPosition && el.sourceIndex !== undefined ){ if (!el.compareDocumentPosition && el.sourceIndex !== undefined) {
Element.prototype.compareDocumentPosition = function(other){ Element.prototype.compareDocumentPosition = function(other) {
return (this != other && this.contains(other) && 16) + return (this != other && this.contains(other) && 16) +
(this != other && other.contains(this) && 8) + (this != other && other.contains(this) && 8) +
(this.sourceIndex >= 0 && other.sourceIndex >= 0 ? (this.sourceIndex >= 0 && other.sourceIndex >= 0 ?
(this.sourceIndex < other.sourceIndex && 4) + (this.sourceIndex < other.sourceIndex && 4) +
(this.sourceIndex > other.sourceIndex && 2) (this.sourceIndex > other.sourceIndex && 2) : 1
: 1 ) + 0;
) + 0;
} }
} }
}()); }());

View file

@ -4,7 +4,7 @@
```html ```html
<div id="clock"> <div id="clock">
<span class="hour">hh</span>:<span class="min">mm</span>:<span class="sec">ss</span> <span class="hour">hh</span>:<span class="min">mm</span>:<span class="sec">ss</span>
</div> </div>
``` ```
@ -15,21 +15,21 @@
```js ```js
function update() { function update() {
var clock = document.getElementById('clock'); var clock = document.getElementById('clock');
*!* *!*
var date = new Date(); // (*) var date = new Date(); // (*)
*/!* */!*
var hours = date.getHours(); var hours = date.getHours();
if (hours < 10) hours = '0'+hours; if (hours < 10) hours = '0' + hours;
clock.children[0].innerHTML = hours; clock.children[0].innerHTML = hours;
var minutes = date.getMinutes(); var minutes = date.getMinutes();
if (minutes < 10) minutes = '0'+minutes; if (minutes < 10) minutes = '0' + minutes;
clock.children[1].innerHTML = minutes; clock.children[1].innerHTML = minutes;
var seconds = date.getSeconds(); var seconds = date.getSeconds();
if (seconds < 10) seconds = '0'+seconds; if (seconds < 10) seconds = '0' + seconds;
clock.children[2].innerHTML = seconds; clock.children[2].innerHTML = seconds;
} }
``` ```
@ -41,9 +41,9 @@ function update() {
Функция `clockStart` для запуска часов: Функция `clockStart` для запуска часов:
```js ```js
function clockStart() { // запустить часы function clockStart() { // запустить часы
setInterval(update, 1000); setInterval(update, 1000);
update(); // (*) update(); // (*)
} }
function clockStop() { function clockStop() {

View file

@ -18,6 +18,6 @@
var elem = document.body.children[0]; var elem = document.body.children[0];
elem.remove(); elem.remove();
</script> </script>
``` ```

View file

@ -16,12 +16,12 @@
<div>Элементы DOM</div> <div>Элементы DOM</div>
<script> <script>
/* ваш код полифилла */ /* ваш код полифилла */
var elem = document.body.children[0]; var elem = document.body.children[0];
*!* *!*
elem.remove(); // <-- вызов должен удалить элемент elem.remove(); // <-- вызов должен удалить элемент
*/!* */!*
</script> </script>
``` ```

View file

@ -9,9 +9,9 @@ function insertAfter(elem, refElem) {
var parent = refElem.parentNode; var parent = refElem.parentNode;
var next = refElem.nextSibling; var next = refElem.nextSibling;
if (next) { if (next) {
return parent.insertBefore(elem, next); return parent.insertBefore(elem, next);
} else { } else {
return parent.appendChild(elem); return parent.appendChild(elem);
} }
} }
``` ```
@ -20,7 +20,7 @@ function insertAfter(elem, refElem) {
```js ```js
function insertAfter(elem, refElem) { function insertAfter(elem, refElem) {
return refElem.parentNode.insertBefore(elem, refElem.nextSibling); return refElem.parentNode.insertBefore(elem, refElem.nextSibling);
} }
``` ```

View file

@ -20,8 +20,7 @@
insertAfter(elem, body.firstChild); // <--- должно работать insertAfter(elem, body.firstChild); // <--- должно работать
// вставить elem за последним элементом // вставить elem за последним элементом
insertAfter(elem, body.lastChild); // <--- должно работать insertAfter(elem, body.lastChild); // <--- должно работать
</script> </script>
``` ```

View file

@ -4,7 +4,7 @@
```js ```js
function removeChildren(elem) { function removeChildren(elem) {
for(var k=0; k<elem.childNodes.length;k++) { for (var k = 0; k < elem.childNodes.length; k++) {
elem.removeChild(elem.childNodes[k]); elem.removeChild(elem.childNodes[k]);
} }
} }
@ -20,7 +20,7 @@ function removeChildren(elem) {
```js ```js
function removeChildren(elem) { function removeChildren(elem) {
while(elem.lastChild) { while (elem.lastChild) {
elem.removeChild(elem.lastChild); elem.removeChild(elem.lastChild);
} }
} }
@ -44,8 +44,8 @@ function removeChildren(elem) {
function removeChildren(elem) { function removeChildren(elem) {
try { try {
elem.innerHTML = ''; elem.innerHTML = '';
} catch(e) { } catch (e) {
while(elem.firstChild) { while (elem.firstChild) {
elem.removeChild(elem.firstChild); elem.removeChild(elem.firstChild);
} }
} }

View file

@ -7,7 +7,9 @@
```html ```html
<table id="table"> <table id="table">
<tr> <tr>
<td>Это</td><td>Все</td><td>Элементы DOM</td> <td>Это</td>
<td>Все</td>
<td>Элементы DOM</td>
</tr> </tr>
</table> </table>

View file

@ -9,17 +9,17 @@
<table> <table>
aaa aaa
<tr> <tr>
<td>Test</td> <td>Test</td>
</tr> </tr>
</table> </table>
<script> <script>
var table = document.body.children[0]; var table = document.body.children[0];
alert(table); // таблица, пока всё правильно alert( table ); // таблица, пока всё правильно
document.body.removeChild( table ); document.body.removeChild(table);
// почему в документе остался текст? // почему в документе остался текст?
</script> </script>
``` ```

View file

@ -8,19 +8,19 @@
```js ```js
var data = { var data = {
"Рыбы":{ "Рыбы": {
"Форель":{}, "Форель": {},
"Щука":{} "Щука": {}
}, },
"Деревья":{ "Деревья": {
"Хвойные":{ "Хвойные": {
"Лиственница":{}, "Лиственница": {},
"Ель":{} "Ель": {}
}, },
"Цветковые":{ "Цветковые": {
"Берёза":{}, "Берёза": {},
"Тополь":{} "Тополь": {}
} }
} }
}; };

View file

@ -78,12 +78,10 @@ div.innerHTML = "<strong>Ура!</strong> Вы прочитали это важ
</ol> </ol>
<script> <script>
var newLi = document.createElement('li'); var newLi = document.createElement('li');
newLi.innerHTML = 'Привет, мир!'; newLi.innerHTML = 'Привет, мир!';
list.appendChild(newLi); list.appendChild(newLi);
</script> </script>
``` ```
@ -101,7 +99,6 @@ div.innerHTML = "<strong>Ура!</strong> Вы прочитали это важ
<li>2</li> <li>2</li>
</ol> </ol>
<script> <script>
var newLi = document.createElement('li'); var newLi = document.createElement('li');
newLi.innerHTML = 'Привет, мир!'; newLi.innerHTML = 'Привет, мир!';
@ -147,6 +144,7 @@ parentElem.appendChild(elem)
```html ```html
<!--+ height=150 run autorun --> <!--+ height=150 run autorun -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.1/css/bootstrap.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.1/css/bootstrap.css">
<body> <body>
<h3>Моя страница</h3> <h3>Моя страница</h3>
</body> </body>
@ -167,6 +165,7 @@ parentElem.appendChild(elem)
```html ```html
<!--+ height=150 run autorun --> <!--+ height=150 run autorun -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.1/css/bootstrap.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.1/css/bootstrap.css">
<body> <body>
<h3>Моя страница</h3> <h3>Моя страница</h3>
</body> </body>
@ -197,6 +196,7 @@ parentElem.appendChild(elem)
```html ```html
<!--+ height=200 run autorun --> <!--+ height=200 run autorun -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.1/css/bootstrap.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.1/css/bootstrap.css">
<body> <body>
<h3>Моя страница</h3> <h3>Моя страница</h3>
</body> </body>
@ -214,16 +214,15 @@ parentElem.appendChild(elem)
// копию можно подправить // копию можно подправить
div2.querySelector('strong').innerHTML = 'Супер!'; div2.querySelector('strong').innerHTML = 'Супер!';
// вставим её после текущего сообщения // вставим её после текущего сообщения
div.parentNode.insertBefore( div2, div.nextSibling ); div.parentNode.insertBefore(div2, div.nextSibling);
*/!* */!*
</script> </script>
``` ```
Обратите внимание на последнюю строку, которая вставляет `div2` после `div`: Обратите внимание на последнюю строку, которая вставляет `div2` после `div`:
```js ```js
div.parentNode.insertBefore( div2, div.nextSibling ); div.parentNode.insertBefore(div2, div.nextSibling);
``` ```
<ol> <ol>
@ -284,6 +283,7 @@ div.parentNode.insertBefore( div2, div.nextSibling );
```html ```html
<!--+ run --> <!--+ run -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.1/css/bootstrap.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.1/css/bootstrap.css">
<body> <body>
<h3>Сообщение пропадёт через секунду</h3> <h3>Сообщение пропадёт через секунду</h3>
</body> </body>
@ -321,12 +321,12 @@ div.parentNode.insertBefore( div2, div.nextSibling );
var div = document.createElement('div'); var div = document.createElement('div');
div.className = "alert alert-success"; div.className = "alert alert-success";
document.body.appendChild(div); document.body.appendChild(div);
*!* *!*
var text = prompt("Введите текст для сообщения", "Жили были <a> и <b>!"); var text = prompt("Введите текст для сообщения", "Жили были <a> и <b>!");
// вставится именно как текст, без HTML-обработки // вставится именно как текст, без HTML-обработки
div.appendChild( document.createTextNode(text) ); div.appendChild(document.createTextNode(text));
*/!* */!*
</script> </script>
``` ```

View file

@ -14,13 +14,14 @@
```js ```js
var ul = document.createElement('ul'); var ul = document.createElement('ul');
document.body.appendChild(ul); // сначала в документ document.body.appendChild(ul); // сначала в документ
for(...) ul.appendChild(li); // потом узлы for (...) ul.appendChild(li); // потом узлы
``` ```
</li> </li>
<li>Полностью создать список "вне DOM", а потом -- вставить в документ: <li>Полностью создать список "вне DOM", а потом -- вставить в документ:
```js ```js
//+ no-beautify
var ul = document.createElement('ul'); var ul = document.createElement('ul');
for(...) ul.appendChild(li); // сначала вставить узлы for(...) ul.appendChild(li); // сначала вставить узлы
document.body.appendChild(ul); // затем в документ document.body.appendChild(ul); // затем в документ
@ -115,14 +116,14 @@ elem.insertAdjacentHTML(where, html);
</ul> </ul>
<script> <script>
var ul = document.body.children[0]; var ul = document.body.children[0];
var li5 = ul.children[2]; var li5 = ul.children[2];
li5.insertAdjacentHTML("beforeBegin", "<li>3</li><li>4</li>"); li5.insertAdjacentHTML("beforeBegin", "<li>3</li><li>4</li>");
</script> </script>
``` ```
Единственный недостаток этого метода -- он не работает в Firefox до версии 8. Но его можно легко добавить, используя [полифилл insertAdjacentHTML для Firefox](insertAdjacentHTML.js). Единственный недостаток этого метода -- он не работает в Firefox до версии 8. Но его можно легко добавить, используя [полифилл insertAdjacentHTML для Firefox](insertAdjacentFF.js).
У этого метода есть "близнецы-братья", которые поддерживаются везде, кроме Firefox, но в него они добавляются тем же полифиллом: У этого метода есть "близнецы-братья", которые поддерживаются везде, кроме Firefox, но в него они добавляются тем же полифиллом:
@ -181,7 +182,7 @@ for (цикл по li) {
fragment.appendChild(list[i]); // вставить каждый LI в DocumentFragment fragment.appendChild(list[i]); // вставить каждый LI в DocumentFragment
} }
ul.appendChild(fragment); // вместо фрагмента вставятся элементы списка ul.appendChild(fragment); // вместо фрагмента вставятся элементы списка
``` ```
В современных браузерах эффект от такой оптимизации может быть различным, а на небольших документах иногда и отрицательным. В современных браузерах эффект от такой оптимизации может быть различным, а на небольших документах иногда и отрицательным.
@ -211,28 +212,30 @@ ul.appendChild(fragment); // вместо фрагмента вставятс
```html ```html
<!--+ run autorun height=80 --> <!--+ run autorun height=80 -->
<html> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<script src="https://cdn.polyfill.io/v1/polyfill.js?features=Element.prototype.mutation"></script> <script src="https://cdn.polyfill.io/v1/polyfill.js?features=Element.prototype.mutation"></script>
</head> </head>
<body> <body>
<script> <script>
// добавим элемент в конец <body> // добавим элемент в конец <body>
var p = document.createElement('p'); var p = document.createElement('p');
document.body.append(p); document.body.append(p);
var em = document.createElement('em'); var em = document.createElement('em');
em.append('Мир!'); em.append('Мир!');
// вставить в параграф текстовый и обычный узлы // вставить в параграф текстовый и обычный узлы
p.append("Привет, ", em); p.append("Привет, ", em);
// добавить элемент после <p> // добавить элемент после <p>
p.after(document.createElement('hr')) p.after(document.createElement('hr'))
</script> </script>
</body> </body>
</html> </html>
``` ```

View file

@ -13,11 +13,11 @@ HTML-документ ниже будет содержать `1 2 3`.
```html ```html
<!--+ run --> <!--+ run -->
<body> <body>
1 1
<script> <script>
document.write(2); document.write(2);
</script> </script>
3 3
</body> </body>
``` ```
@ -29,14 +29,18 @@ HTML-документ ниже будет содержать `1 2 3`.
```html ```html
<!--+ run --> <!--+ run -->
<script> <script>
document.write('<style> td { color: #F40 } </style>'); document.write('<style> td { color: #F40 } </style>');
</script> </script>
<table> <table>
<tr> <tr>
<script> document.write('<td>') </script> <script>
document.write('<td>')
</script>
Текст внутри TD. Текст внутри TD.
<script> document.write('</td>') </script> <script>
document.write('</td>')
</script>
</tr> </tr>
</table> </table>
``` ```
@ -93,7 +97,7 @@ HTML-документ ниже будет содержать `1 2 3`.
var url = 'http://ads.com/buyme?screen=' + screen.width + "x" + screen.height; var url = 'http://ads.com/buyme?screen=' + screen.width + "x" + screen.height;
// загрузить такой скрипт прямо сейчас // загрузить такой скрипт прямо сейчас
document.write('<script src="'+url+'"></scr'+'ipt>'); document.write('<script src="' + url + '"></scr' + 'ipt>');
</script> </script>
``` ```
@ -103,7 +107,7 @@ HTML-документ ниже будет содержать `1 2 3`.
Также используют запись: Также используют запись:
```js ```js
document.write('<script src="'+url+'"><\/script>'); document.write('<script src="' + url + '"><\/script>');
``` ```
Здесь `<\/script>` вместо `</script>`: обратный слеш `\` обычно используется для вставки спецсимволов типа `\n`, а если такого спецсимвола нет, в данном случае `\/` не является спецсимволом, то будет проигнорирован. Так что получается такой альтернативный способ безопасно вставить строку `</script>`. Здесь `<\/script>` вместо `</script>`: обратный слеш `\` обычно используется для вставки спецсимволов типа `\n`, а если такого спецсимвола нет, в данном случае `\/` не является спецсимволом, то будет проигнорирован. Так что получается такой альтернативный способ безопасно вставить строку `</script>`.

View file

@ -16,7 +16,7 @@
* @param options.className {string} CSS-класс * @param options.className {string} CSS-класс
* @param options.html {string} HTML-текст для показа * @param options.html {string} HTML-текст для показа
*/ */
function showNotification(options) { function showNotification(options) {
// ваш код // ваш код
} }
``` ```

View file

@ -21,6 +21,7 @@
**Для свойств, названия которых состоят из нескольких слов, используется вотТакаяЗапись:** **Для свойств, названия которых состоят из нескольких слов, используется вотТакаяЗапись:**
```js ```js
//+ no-beautify
background-color => elem.style.backgroundColor background-color => elem.style.backgroundColor
z-index => elem.style.zIndex z-index => elem.style.zIndex
border-left-width => elem.style.borderLeftWidth border-left-width => elem.style.borderLeftWidth
@ -73,15 +74,15 @@ setTimeout(function() {
```html ```html
<!--+ run height=100 --> <!--+ run height=100 -->
<body> <body>
<script> <script>
*!* *!*
document.body.style.margin = '20px'; document.body.style.margin = '20px';
alert(document.body.style.marginTop); // 20px! alert( document.body.style.marginTop ); // 20px!
*/!* */!*
*!* *!*
document.body.style.color = '#abc'; document.body.style.color = '#abc';
alert(document.body.style.color); // rgb(170, 187, 204) alert( document.body.style.color ); // rgb(170, 187, 204)
*/!* */!*
</script> </script>
</body> </body>
@ -146,7 +147,7 @@ setTimeout(function() {
Вот так `style` уже ничего не увидит: Вот так `style` уже ничего не увидит:
```html ```html
<!--+ run height=100 --> <!--+ run height=100 no-beautify -->
<head> <head>
<style> body { color: red; margin: 5px } </style> <style> body { color: red; margin: 5px } </style>
</head> </head>
@ -190,14 +191,17 @@ getComputedStyle(element[, pseudo])
```html ```html
<!--+ run height=100 --> <!--+ run height=100 -->
<style> <style>
body { margin: 10px } body {
margin: 10px
}
</style> </style>
<body> <body>
<script> <script>
var computedStyle = getComputedStyle(document.body); var computedStyle = getComputedStyle(document.body);
alert(computedStyle.marginTop); // выведет отступ в пикселях alert( computedStyle.marginTop ); // выведет отступ в пикселях
alert(computedStyle.color); // выведет цвет alert( computedStyle.color ); // выведет цвет
</script> </script>
</body> </body>
@ -264,10 +268,13 @@ function getStyle(elem) {
```html ```html
<!--+ run height=100 --> <!--+ run height=100 -->
<style> <style>
body { margin: 10% } body {
margin: 10%
}
</style> </style>
<body> <body>
<script> <script>
var elem = document.body; var elem = document.body;
function getStyle(elem) { function getStyle(elem) {
@ -275,7 +282,7 @@ function getStyle(elem) {
} }
var marginTop = getStyle(elem).marginTop; var marginTop = getStyle(elem).marginTop;
alert(marginTop); // IE8-: 10%, иначе пиксели alert( marginTop ); // IE8-: 10%, иначе пиксели
</script> </script>
</body> </body>
``` ```

View file

@ -4,9 +4,9 @@
//+ run //+ run
// создадим элемент с прокруткой // создадим элемент с прокруткой
var div = document.createElement('div'); var div = document.createElement('div');
div.style.overflowY = 'scroll'; div.style.overflowY = 'scroll';
div.style.width = '50px'; div.style.width = '50px';
div.style.height = '50px'; div.style.height = '50px';
// при display:none размеры нельзя узнать // при display:none размеры нельзя узнать

View file

@ -20,9 +20,9 @@ placeHolder.style.height = div.offsetHeight + 'px';
// можно и width, но в этом примере это не обязательно // можно и width, но в этом примере это не обязательно
// IE || другой браузер // IE || другой браузер
var computedStyle = div.currentStyle || getComputedStyle(div, ''); var computedStyle = div.currentStyle || getComputedStyle(div, '');
placeHolder.style.marginTop = computedStyle.marginTop; // (1) placeHolder.style.marginTop = computedStyle.marginTop; // (1)
placeHolder.style.marginBottom = computedStyle.marginBottom; placeHolder.style.marginBottom = computedStyle.marginBottom;
``` ```

View file

@ -5,7 +5,7 @@
Посмотрим следующий случай из жизни. Был текст, который, в частности, содержал `div` с зелеными границами: Посмотрим следующий случай из жизни. Был текст, который, в частности, содержал `div` с зелеными границами:
```html ```html
<!--+ run --> <!--+ run no-beautify -->
<style> <style>
#moving-div { #moving-div {
border: 5px groove green; border: 5px groove green;

View file

@ -12,8 +12,8 @@
var ball = document.getElementById('ball'); var ball = document.getElementById('ball');
var field = document.getElementById('field'); var field = document.getElementById('field');
ball.style.left = Math.round(field.clientWidth / 2)+'px'; ball.style.left = Math.round(field.clientWidth / 2) + 'px';
ball.style.top = Math.round(field.clientHeight / 2)+'px'; ball.style.top = Math.round(field.clientHeight / 2) + 'px';
``` ```
[iframe hide="Нажмите, чтобы посмотреть текущий результат" height=180 src="ball-half"] [iframe hide="Нажмите, чтобы посмотреть текущий результат" height=180 src="ball-half"]
@ -24,8 +24,8 @@ ball.style.top = Math.round(field.clientHeight / 2)+'px';
var ball = document.getElementById('ball'); var ball = document.getElementById('ball');
var field = document.getElementById('field'); var field = document.getElementById('field');
ball.style.left = Math.round(field.clientWidth/2 - ball.offsetWidth/2)+'px'; ball.style.left = Math.round(field.clientWidth / 2 - ball.offsetWidth / 2) + 'px';
ball.style.top = Math.round(field.clientHeight/2 - ball.offsetHeight/2)+'px'; ball.style.top = Math.round(field.clientHeight / 2 - ball.offsetHeight / 2) + 'px';
``` ```
**Внимание, подводный камень!** **Внимание, подводный камень!**

View file

@ -11,6 +11,7 @@
Мы будем использовать для примера вот такой элемент, у которого есть рамка (border), поля (padding), и прокрутка: Мы будем использовать для примера вот такой элемент, у которого есть рамка (border), поля (padding), и прокрутка:
```html ```html
<!--+ no-beautify -->
<div id="example"> <div id="example">
...Текст... ...Текст...
</div> </div>
@ -125,7 +126,7 @@
**Это дает нам замечательный способ для проверки, виден ли элемент**: **Это дает нам замечательный способ для проверки, виден ли элемент**:
```js ```js
function isHidden(elem) function isHidden(elem) {
return !elem.offsetWidth && !elem.offsetHeight; return !elem.offsetWidth && !elem.offsetHeight;
} }
``` ```
@ -265,7 +266,7 @@ alert( getComputedStyle(elem).width ); // вывести CSS-ширину для
<script> <script>
*!* *!*
alert( getComputedStyle(elem).width ); // auto alert( getComputedStyle(elem).width ); // auto
*/!* */!*
</script> </script>
``` ```

View file

@ -57,7 +57,7 @@ var scrollHeight = Math.max(
document.body.clientHeight, document.documentElement.clientHeight document.body.clientHeight, document.documentElement.clientHeight
); );
alert('Высота с учетом прокрутки: ' + scrollHeight); alert( 'Высота с учетом прокрутки: ' + scrollHeight );
``` ```
Почему так? Лучше и не спрашивайте, это одно из редких мест, где просто ошибки в браузерах. Глубокой логики здесь нет. Почему так? Лучше и не спрашивайте, это одно из редких мест, где просто ошибки в браузерах. Глубокой логики здесь нет.
@ -74,8 +74,8 @@ alert('Высота с учетом прокрутки: ' + scrollHeight);
```js ```js
//+ run //+ run
alert('Текущая прокрутка сверху: ' + window.pageYOffset); alert( 'Текущая прокрутка сверху: ' + window.pageYOffset );
alert('Текущая прокрутка слева: ' + window.pageXOffset); alert( 'Текущая прокрутка слева: ' + window.pageXOffset );
``` ```
Эти свойства: Эти свойства:
@ -92,7 +92,7 @@ alert('Текущая прокрутка слева: ' + window.pageXOffset);
//+ run //+ run
var scrollTop = window.pageYOffset || document.documentElement.scrollTop; var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
alert("Текущая прокрутка: " + scrollTop); alert( "Текущая прокрутка: " + scrollTop );
``` ```
## Изменение прокрутки: scrollTo, scrollBy, scrollIntoView [#window-scroll] ## Изменение прокрутки: scrollTo, scrollBy, scrollIntoView [#window-scroll]
@ -199,7 +199,7 @@ var body = document.body;
var scrollTop = html.scrollTop || body && body.scrollTop || 0; var scrollTop = html.scrollTop || body && body.scrollTop || 0;
scrollTop -= html.clientTop; // в IE7- <html> смещён относительно (0,0) scrollTop -= html.clientTop; // в IE7- <html> смещён относительно (0,0)
alert("Текущая прокрутка: " + scrollTop); alert( "Текущая прокрутка: " + scrollTop );
``` ```
</li> </li>

View file

@ -25,8 +25,8 @@ var coords3 = [coords.left + field.clientLeft, coords.top + field.clientTop];
```js ```js
var coords4 = [ var coords4 = [
coords.right - parseInt(getComputedStyle(field).borderRightWidth) , coords.right - parseInt(getComputedStyle(field).borderRightWidth),
coords.bottom - parseInt(getComputedStyle(field).borderBottomWidth) coords.bottom - parseInt(getComputedStyle(field).borderBottomWidth)
] ]
``` ```
@ -34,7 +34,7 @@ var coords4 = [
```js ```js
var coords4 = [ var coords4 = [
coords.left + elem.clientLeft + elem.clientWidth , coords.left + elem.clientLeft + elem.clientWidth,
coords.top + elem.clientTop + elem.clientHeight coords.top + elem.clientTop + elem.clientHeight
] ]
``` ```

View file

@ -46,9 +46,9 @@
Результат `getCoords`: объект с координатами `{left: .., top: ..}` Результат `getCoords`: объект с координатами `{left: .., top: ..}`
```js ```js
function getCoords(elem) { // кроме IE8- function getCoords(elem) { // кроме IE8-
var box = elem.getBoundingClientRect(); var box = elem.getBoundingClientRect();
return { return {
top: box.top + pageYOffset, top: box.top + pageYOffset,
left: box.left + pageXOffset left: box.left + pageXOffset
@ -64,23 +64,26 @@ function getCoords(elem) { // кроме IE8-
function getCoords(elem) { function getCoords(elem) {
// (1) // (1)
var box = elem.getBoundingClientRect(); var box = elem.getBoundingClientRect();
var body = document.body; var body = document.body;
var docEl = document.documentElement; var docEl = document.documentElement;
// (2) // (2)
var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop; var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;
var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft; var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft;
// (3) // (3)
var clientTop = docEl.clientTop || body.clientTop || 0; var clientTop = docEl.clientTop || body.clientTop || 0;
var clientLeft = docEl.clientLeft || body.clientLeft || 0; var clientLeft = docEl.clientLeft || body.clientLeft || 0;
// (4) // (4)
var top = box.top + scrollTop - clientTop; var top = box.top + scrollTop - clientTop;
var left = box.left + scrollLeft - clientLeft; var left = box.left + scrollLeft - clientLeft;
return { top: top, left: left }; return {
top: top,
left: left
};
} }
``` ```
@ -104,15 +107,19 @@ function getCoords(elem) {
```js ```js
//+ autorun //+ autorun
function getOffsetSum(elem) { function getOffsetSum(elem) {
var top = 0, left = 0; var top = 0,
left = 0;
while(elem) { while (elem) {
top = top + parseInt(elem.offsetTop); top = top + parseInt(elem.offsetTop);
left = left + parseInt(elem.offsetLeft); left = left + parseInt(elem.offsetLeft);
elem = elem.offsetParent; elem = elem.offsetParent;
} }
return {top: top, left: left}; return {
top: top,
left: left
};
} }
``` ```
@ -183,10 +190,10 @@ document.getElementById('getBoundingClientRectEx').onclick = function(event) {
```js ```js
//+ run //+ run
// общая ширина/высота // общая ширина/высота
alert( screen.width + ' x ' + screen.height ); alert( screen.width + ' x ' + screen.height );
// доступная ширина/высота (за вычетом таскбара и т.п.) // доступная ширина/высота (за вычетом таскбара и т.п.)
alert( screen.availWidth + ' x ' + screen.availHeight); alert( screen.availWidth + ' x ' + screen.availHeight );
// есть и ряд других свойств screen (см. документацию) // есть и ряд других свойств screen (см. документацию)
``` ```
@ -196,7 +203,7 @@ alert( screen.availWidth + ' x ' + screen.availHeight);
```js ```js
//+ run //+ run
alert("Браузер находится на " + window.screenX + "," + window.screenY); alert( "Браузер находится на " + window.screenX + "," + window.screenY );
``` ```
Они могут быть и меньше нуля, если окно частично вне экрана. </li> Они могут быть и меньше нуля, если окно частично вне экрана. </li>

View file

@ -5,14 +5,17 @@
```html ```html
<!--+ run --> <!--+ run -->
<html> <html>
<head> <head>
<script> <script>
alert(document.body); // null alert( document.body ); // null
</script> </script>
</head> </head>
<body> <body>
Привет, мир! Привет, мир!
</body> </body>
</html> </html>
``` ```

View file

@ -6,16 +6,19 @@
```html ```html
<html> <html>
<head> <head>
*!* *!*
<script> <script>
alert(document.body); // ? alert( document.body ); // ?
</script> </script>
*/!* */!*
</head> </head>
<body> <body>
Привет, мир! Привет, мир!
</body> </body>
</html> </html>
``` ```

View file

@ -13,15 +13,15 @@ DOM -- это представление документа в виде дере
Построим, для начала, дерево DOM для следующего документа. Построим, для начала, дерево DOM для следующего документа.
```html ```html
<!--+ run --> <!--+ run no-beautify -->
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<head> <head>
<title>О лосях</title> <title>О лосях</title>
</head> </head>
<body> <body>
Правда о лосях Правда о лосях
</body> </body>
</html> </html>
``` ```
@ -60,6 +60,7 @@ drawHtmlTree(node, 'div.domtree', 690, 350);
В остальных случаях всё честно -- если пробелы есть в документе, то они есть и в DOM, а если их убрать, то и в DOM их не будет, получится так: В остальных случаях всё честно -- если пробелы есть в документе, то они есть и в DOM, а если их убрать, то и в DOM их не будет, получится так:
```html ```html
<!--+ no-beautify -->
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html><head><title>О лосях</title></head><body>Правда о лосях</body></html> <html><head><title>О лосях</title></head><body>Правда о лосях</body></html>
``` ```
@ -86,6 +87,7 @@ drawHtmlTree(node, 'div.domtree', 690, 300);
Такой документ: Такой документ:
```html ```html
<!--+ no-beautify -->
<p>Привет <p>Привет
<li>Мама <li>Мама
<li>и <li>и
@ -98,7 +100,7 @@ drawHtmlTree(node, 'div.domtree', 690, 300);
<script> <script>
var node = {"name":"HTML","nodeType":1,"children":[{"name":"HEAD","nodeType":1,"children":[]},{"name":"BODY","nodeType":1,"children":[{"name":"P","nodeType":1,"children":[{"name":"#text","nodeType":3,"content":"Привет\n"}]},{"name":"LI","nodeType":1,"children":[{"name":"#text","nodeType":3,"content":"Мама\n"}]},{"name":"LI","nodeType":1,"children":[{"name":"#text","nodeType":3,"content":"и\n"}]},{"name":"LI","nodeType":1,"children":[{"name":"#text","nodeType":3,"content":"Папа\n"}]}]}]} var node = {"name":"HTML","nodeType":1,"children":[{"name":"HEAD","nodeType":1,"children":[]},{"name":"BODY","nodeType":1,"children":[{"name":"P","nodeType":1,"children":[{"name":"#text","nodeType":3,"content":"Привет\n"}]},{"name":"LI","nodeType":1,"children":[{"name":"#text","nodeType":3,"content":"Мама\n"}]},{"name":"LI","nodeType":1,"children":[{"name":"#text","nodeType":3,"content":"и\n"}]},{"name":"LI","nodeType":1,"children":[{"name":"#text","nodeType":3,"content":"Папа\n"}]}]}]}
drawHtmlTree(node, [].pop.call(document.querySelectorAll('div.domtree')), 690, 400); drawHtmlTree(node, 'div.domtree', 690, 400);
</script> </script>
[warn header="Таблицы всегда содержат `<tbody>`"] [warn header="Таблицы всегда содержат `<tbody>`"]
@ -107,6 +109,7 @@ drawHtmlTree(node, [].pop.call(document.querySelectorAll('div.domtree')), 690,
Например, для такого HTML: Например, для такого HTML:
```html ```html
<!--+ no-beautify -->
<table id="table"> <table id="table">
<tr><td>1</td></tr> <tr><td>1</td></tr>
</table> </table>
@ -123,6 +126,7 @@ drawHtmlTree(node, 'div.domtree', 600, 200);
Вы видите? Появился `<tbody>`, как будто документ был таким: Вы видите? Появился `<tbody>`, как будто документ был таким:
```html ```html
<!--+ no-beautify -->
<table> <table>
*!* *!*
<tbody> <tbody>
@ -145,16 +149,18 @@ drawHtmlTree(node, 'div.domtree', 600, 200);
```html ```html
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<body>
Правда о лосях <body>
<ol> Правда о лосях
<li>Лось — животное хитрое</li> <ol>
<li>Лось — животное хитрое</li>
*!* *!*
<!-- комментарий --> <!-- комментарий -->
*/!* */!*
<li>...и коварное!</li> <li>...и коварное!</li>
</ol> </ol>
</body> </body>
</html> </html>
``` ```
@ -198,10 +204,10 @@ drawHtmlTree(node, 'div.domtree', 690, 550);
```js ```js
//+ run //+ run
document.body.style.backgroundColor = 'red'; document.body.style.backgroundColor = 'red';
alert('Поменяли цвет BODY'); alert( 'Поменяли цвет BODY' );
document.body.style.backgroundColor = ''; document.body.style.backgroundColor = '';
alert('Сбросили цвет BODY'); alert( 'Сбросили цвет BODY' );
``` ```
DOM предоставляет возможность делать со страницей всё, что угодно. DOM предоставляет возможность делать со страницей всё, что угодно.
@ -216,6 +222,7 @@ IE8- не генерирует текстовые узлы, если они со
То есть, такие два документа дадут идентичный DOM: То есть, такие два документа дадут идентичный DOM:
```html ```html
<!--+ no-beautify -->
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html><head><title>О лосях</title></head><body>Правда о лосях</body></html> <html><head><title>О лосях</title></head><body>Правда о лосях</body></html>
``` ```
@ -225,12 +232,15 @@ IE8- не генерирует текстовые узлы, если они со
```html ```html
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<head>
<title>О лосях</title> <head>
</head> <title>О лосях</title>
<body> </head>
Правда о лосях
</body> <body>
Правда о лосях
</body>
</html> </html>
``` ```

View file

@ -7,21 +7,26 @@
```html ```html
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<head><meta charset="utf-8"></head>
<body>
<div>Пользователи:</div>
<ul>
<li>Маша</li>
<li>Вовочка</li>
</ul>
<!-- комментарий --> <head>
<meta charset="utf-8">
</head>
<script> <body>
// ... ваш код <div>Пользователи:</div>
</script> <ul>
<li>Маша</li>
<li>Вовочка</li>
</ul>
<!-- комментарий -->
<script>
// ... ваш код
</script>
</body>
</body>
</html> </html>
``` ```

View file

@ -1,12 +1,14 @@
Вначале нерабочие способы, которые могут прийти на ум: Вначале нерабочие способы, которые могут прийти на ум:
```js ```js
//+ no-beautify
if (!elem) { .. } if (!elem) { .. }
``` ```
Это не работает, так как `elem` всегда есть, и является объектом. Так что проверка `if (elem)` всегда верна, вне зависимости от того, есть ли у `elem` потомки. Это не работает, так как `elem` всегда есть, и является объектом. Так что проверка `if (elem)` всегда верна, вне зависимости от того, есть ли у `elem` потомки.
```js ```js
//+ no-beautify
if (!elem.childNodes) { ... } if (!elem.childNodes) { ... }
``` ```
@ -15,6 +17,7 @@ if (!elem.childNodes) { ... }
Несколько рабочих способов: Несколько рабочих способов:
```js ```js
//+ no-beautify
if (!elem.childNodes.length) { ... } if (!elem.childNodes.length) { ... }
if (!elem.firstChild) { ... } if (!elem.firstChild) { ... }

View file

@ -7,6 +7,7 @@
"Пустой" -- значит нет дочерних узлов, даже текстовых. "Пустой" -- значит нет дочерних узлов, даже текстовых.
```js ```js
//+ no-beautify
if (/*...ваш код проверки elem... */) { узел elem пуст } if (/*...ваш код проверки elem... */) { узел elem пуст }
``` ```

View file

@ -36,20 +36,23 @@ DOM позволяет делать что угодно с HTML-элементо
<!--+ run --> <!--+ run -->
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<head>
<script>
*!*
alert("Из HEAD: " + document.body); // null, body ещё нет
*/!*
</script>
</head>
<body>
<script>
alert("Из BODY: " + document.body); // body есть
</script>
</body> <head>
<script>
*!*
alert( "Из HEAD: " + document.body ); // null, body ещё нет
*/!*
</script>
</head>
<body>
<script>
alert( "Из BODY: " + document.body ); // body есть
</script>
</body>
</html> </html>
``` ```
[/warn] [/warn]
@ -76,6 +79,7 @@ DOM позволяет делать что угодно с HTML-элементо
<!--+ run --> <!--+ run -->
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<body> <body>
<div>Начало</div> <div>Начало</div>
@ -87,13 +91,14 @@ DOM позволяет делать что угодно с HTML-элементо
<script> <script>
*!* *!*
for(var i=0; i<document.body.childNodes.length; i++) { for (var i = 0; i < document.body.childNodes.length; i++) {
alert( document.body.childNodes[i] ); // Text, DIV, Text, UL, ..., SCRIPT alert( document.body.childNodes[i] ); // Text, DIV, Text, UL, ..., SCRIPT
} }
*/!* */!*
</script> </script>
... ...
</body> </body>
</html> </html>
``` ```
@ -146,9 +151,9 @@ elems.forEach(function(elem) { // нет такого метода!
var elems = document.documentElement.childNodes; var elems = document.documentElement.childNodes;
*!* *!*
[].forEach.call(elems, function(elem) { [].forEach.call(elems, function(elem) {
*/!* */!*
alert(elem); // HEAD, текст, BODY alert( elem ); // HEAD, текст, BODY
}); });
``` ```
@ -166,8 +171,8 @@ var elems = document.documentElement.childNodes;
elems = Array.prototype.slice.call(elems); // теперь elems - массив elems = Array.prototype.slice.call(elems); // теперь elems - массив
*/!* */!*
elems.forEach(function(elem) { elems.forEach(function(elem) {
alert(elem.tagName); // HEAD, текст, BODY alert( elem.tagName ); // HEAD, текст, BODY
}); });
``` ```
@ -188,8 +193,8 @@ elems.forEach(function(elem) {
//+ run //+ run
var elems = document.documentElement.childNodes; var elems = document.documentElement.childNodes;
for(var key in elems) { for (var key in elems) {
alert(key); // 0, 1, 2, length, item alert( key ); // 0, 1, 2, length, item
} }
``` ```
@ -242,6 +247,7 @@ for(var key in elems) {
<!--+ run --> <!--+ run -->
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<body> <body>
<div>Начало</div> <div>Начало</div>
@ -253,13 +259,14 @@ for(var key in elems) {
<script> <script>
*!* *!*
for(var i=0; i<document.body.children.length; i++) { for (var i = 0; i < document.body.children.length; i++) {
alert( document.body.children[i] ); // DIV, UL, DIV, SCRIPT alert( document.body.children[i] ); // DIV, UL, DIV, SCRIPT
} }
*/!* */!*
</script> </script>
... ...
</body> </body>
</html> </html>
``` ```
@ -267,7 +274,7 @@ for(var key in elems) {
```js ```js
elem.firstElementChild === elem.children[0] elem.firstElementChild === elem.children[0]
elem.lastElementChild === body.children[body.children.length-1] elem.lastElementChild === body.children[body.children.length - 1]
``` ```

View file

@ -3,7 +3,7 @@
```js ```js
var lis = document.getElementsByTagName('li'); var lis = document.getElementsByTagName('li');
for(i=0; i<lis.length; i++) { for (i = 0; i < lis.length; i++) {
... ...
} }
``` ```

View file

@ -102,17 +102,15 @@ var elements = document.getElementsByTagName('div');
</table> </table>
<script> <script>
*!* *!*
var tableElem = document.getElementById('age-table'); var tableElem = document.getElementById('age-table');
var elements = tableElem.getElementsByTagName('input'); var elements = tableElem.getElementsByTagName('input');
*/!* */!*
for (var i=0; i<elements.length; i++) { for (var i = 0; i < elements.length; i++) {
var input = elements[i]; var input = elements[i];
alert(input.value + ': ' + input.checked); alert( input.value + ': ' + input.checked );
} }
</script> </script>
``` ```
@ -181,8 +179,8 @@ var elems = document.getElementsByName('age');
<div class="long article">Длинная статья</div> <div class="long article">Длинная статья</div>
<script> <script>
var articles = document.getElementsByClassName('article'); var articles = document.getElementsByClassName('article');
alert( articles.length ); // 2, найдёт оба элемента alert( articles.length ); // 2, найдёт оба элемента
</script> </script>
``` ```
@ -214,8 +212,8 @@ alert( articles.length ); // 2, найдёт оба элемента
var elements = document.querySelectorAll('ul > li:last-child'); var elements = document.querySelectorAll('ul > li:last-child');
*/!* */!*
for (var i=0; i<elements.length; i++) { for (var i = 0; i < elements.length; i++) {
alert(elements[i].innerHTML ); // "тест", "пройден" alert( elements[i].innerHTML ); // "тест", "пройден"
} }
</script> </script>
``` ```
@ -248,11 +246,11 @@ alert( articles.length ); // 2, найдёт оба элемента
<script> <script>
var elems = document.body.children; var elems = document.body.children;
for(var i=0; i<elems.length; i++) { for (var i = 0; i < elems.length; i++) {
*!* *!*
if ( elems[i].matches('a[href$="zip"]') ) { if (elems[i].matches('a[href$="zip"]')) {
*/!* */!*
alert("Ссылка на архив: " + elems[i].href); alert( "Ссылка на архив: " + elems[i].href );
} }
} }
</script> </script>
@ -284,14 +282,14 @@ alert( articles.length ); // 2, найдёт оба элемента
var numberSpan = document.querySelector('.num'); var numberSpan = document.querySelector('.num');
// ближайший элемент сверху подходящий под селектор li // ближайший элемент сверху подходящий под селектор li
alert( numberSpan.closest('li').className ) // subchapter alert(numberSpan.closest('li').className) // subchapter
// ближайший элемент сверху подходящий под селектор .chapter // ближайший элемент сверху подходящий под селектор .chapter
alert( numberSpan.closest('.chapter').tagName ) // LI alert(numberSpan.closest('.chapter').tagName) // LI
// ближайший элемент сверху, подходящий под селектор span // ближайший элемент сверху, подходящий под селектор span
// это сам numberSpan, так как поиск включает в себя сам элемент // это сам numberSpan, так как поиск включает в себя сам элемент
alert( numberSpan.closest('span') === numberSpan ) // true alert(numberSpan.closest('span') === numberSpan) // true
</script> </script>
``` ```
@ -306,11 +304,12 @@ alert( articles.length ); // 2, найдёт оба элемента
Найдем заголовки с текстом `XPath` в текущем документе: Найдем заголовки с текстом `XPath` в текущем документе:
```js ```js
//+ run //+ run no-beautify
var result = document.evaluate("//h2[contains(., 'XPath')]", document.documentElement, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); var result = document.evaluate("//h2[contains(., 'XPath')]", document.documentElement, null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i=0; i<result.snapshotLength; i++) { for (var i = 0; i < result.snapshotLength; i++) {
alert(result.snapshotItem(i).outerHTML); alert( result.snapshotItem(i).outerHTML );
} }
``` ```

View file

@ -13,8 +13,8 @@
var lis = document.body.getElementsByTagName('li'); var lis = document.body.getElementsByTagName('li');
document.body.innerHTML = ""; document.body.innerHTML = "";
alert(lis.length); alert( lis.length );
</script> </script>
``` ```
@ -36,13 +36,12 @@
<li>Магазин</li> <li>Магазин</li>
</ul> </ul>
<script> <script>
var menu = document.getElementById('menu'); var menu = document.getElementById('menu');
var lis = menu.getElementsByTagName('li'); var lis = menu.getElementsByTagName('li');
document.body.innerHTML = ""; document.body.innerHTML = "";
alert(lis.length); alert( lis.length );
</script> </script>
``` ```

View file

@ -19,7 +19,7 @@ var lis = document.body.getElementsByTagName('li');
document.body.innerHTML = ""; document.body.innerHTML = "";
alert(lis.length); alert( lis.length );
``` ```
2. А такой код (вопрос посложнее)? 2. А такой код (вопрос посложнее)?
@ -30,6 +30,6 @@ var lis = menu.getElementsByTagName('li');
document.body.innerHTML = ""; document.body.innerHTML = "";
alert(lis.length); alert( lis.length );
``` ```

View file

@ -5,7 +5,7 @@
Для любого документа сделаем следующее: Для любого документа сделаем следующее:
```js ```js
var aList1 = document.getElementsByTagName('a'), var aList1 = document.getElementsByTagName('a');
var aList2 = document.querySelectorAll('a'); var aList2 = document.querySelectorAll('a');
``` ```

View file

@ -3,7 +3,7 @@
```js ```js
function bench(f, times) { function bench(f, times) {
var d = new Date(); var d = new Date();
for(var i=0; i<times; i++) f(); for (var i = 0; i < times; i++) f();
return new Date() - d; return new Date() - d;
} }
``` ```

View file

@ -42,12 +42,12 @@
var resultGet = document.getElementsByTagName('div'); var resultGet = document.getElementsByTagName('div');
var resultQuery = document.querySelectorAll('div'); var resultQuery = document.querySelectorAll('div');
alert(resultQuery.length + ', ' + resultGet.length); // 1, 1 alert( resultQuery.length + ', ' + resultGet.length ); // 1, 1
document.body.innerHTML = ''; // удалить всё содержимое BODY document.body.innerHTML = ''; // удалить всё содержимое BODY
*!* *!*
alert(resultQuery.length + ', ' + resultGet.length); // 1, 0 alert( resultQuery.length + ', ' + resultGet.length ); // 1, 0
*/!* */!*
</script> </script>
``` ```
@ -142,22 +142,22 @@ alert( elems.length );
```html ```html
<!--+ run --> <!--+ run -->
<script> <script>
for(var i=0; i<10000;i++) document.write('<span> </span>'); for (var i = 0; i < 10000; i++) document.write('<span> </span>');
var elements = document.body.getElementsByTagName('span'); var elements = document.body.getElementsByTagName('span');
var len = elements.length; var len = elements.length;
var d = new Date; var d = new Date;
*!* *!*
for(var i = 0; i<len; i++) elements[i]; for (var i = 0; i < len; i++) elements[i];
*/!* */!*
alert("Последовательно: "+ (new Date - d) + "мс"); // (1) alert( "Последовательно: " + (new Date - d) + "мс" ); // (1)
var d = new Date; var d = new Date;
*!* *!*
for(var i = 0; i<len; i+=2) elements[i], elements[len-i-1]; for (var i = 0; i < len; i += 2) elements[i], elements[len - i - 1];
*/!* */!*
alert("Вразнобой: "+ (new Date - d) + "мс"); // (2) alert( "Вразнобой: " + (new Date - d) + "мс" ); // (2)
</script> </script>
``` ```

View file

@ -7,11 +7,11 @@
```html ```html
<!--+ run --> <!--+ run -->
<body> <body>
<h1>Привет, мир!</h1> <h1>Привет, мир!</h1>
<script> <script>
alert( document.body.firstChild.innerHTML ); // undefined alert( document.body.firstChild.innerHTML ); // undefined
</script> </script>
</body> </body>
``` ```

View file

@ -5,12 +5,14 @@
```html ```html
<!--+ run height=60 --> <!--+ run height=60 -->
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<body>
<script> <body>
alert(document.body.lastChild.nodeType); <script>
</script> alert( document.body.lastChild.nodeType );
</body> </script>
</body>
</html> </html>
``` ```

View file

@ -6,12 +6,14 @@
```html ```html
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<body>
<script> <body>
alert(document.body.lastChild.nodeType); <script>
</script> alert( document.body.lastChild.nodeType );
</body> </script>
</body>
</html> </html>
``` ```

View file

@ -3,11 +3,11 @@
```html ```html
<!--+ run --> <!--+ run -->
<script> <script>
var body = document.body; var body = document.body;
body.innerHTML = "<!--" + body.tagName + "-->"; body.innerHTML = "<!--" + body.tagName + "-->";
alert(body.firstChild.data); // BODY alert( body.firstChild.data ); // BODY
</script> </script>
``` ```

View file

@ -6,11 +6,11 @@
```html ```html
<script> <script>
var body = document.body; var body = document.body;
body.innerHTML = "<!--" + body.tagName + "-->"; body.innerHTML = "<!--" + body.tagName + "-->";
alert(body.firstChild.data); // что выведет? alert( body.firstChild.data ); // что выведет?
</script> </script>
``` ```

View file

@ -45,16 +45,16 @@ alert( document.body ); // [object HTMLBodyElement]
Вот из него выдержка: Вот из него выдержка:
```js ```js
interface HTMLInputElement : HTMLElement { interface HTMLInputElement: HTMLElement {
attribute DOMString accept; attribute DOMString accept;
attribute DOMString alt; attribute DOMString alt;
attribute DOMString autocomplete; attribute DOMString autocomplete;
attribute boolean autofocus; attribute boolean autofocus;
... ...
attribute DOMString value; attribute DOMString value;
... ...
void select(); void select();
... ...
} }
``` ```
@ -84,18 +84,18 @@ interface HTMLInputElement : HTMLElement {
```js ```js
interface Node { interface Node {
// NodeType // NodeType
const unsigned short ELEMENT_NODE = 1; const unsigned short ELEMENT_NODE = 1;
const unsigned short ATTRIBUTE_NODE = 2; const unsigned short ATTRIBUTE_NODE = 2;
const unsigned short TEXT_NODE = 3; const unsigned short TEXT_NODE = 3;
const unsigned short CDATA_SECTION_NODE = 4; const unsigned short CDATA_SECTION_NODE = 4;
const unsigned short ENTITY_REFERENCE_NODE = 5; const unsigned short ENTITY_REFERENCE_NODE = 5;
const unsigned short ENTITY_NODE = 6; const unsigned short ENTITY_NODE = 6;
const unsigned short PROCESSING_INSTRUCTION_NODE = 7; const unsigned short PROCESSING_INSTRUCTION_NODE = 7;
const unsigned short COMMENT_NODE = 8; const unsigned short COMMENT_NODE = 8;
const unsigned short DOCUMENT_NODE = 9; const unsigned short DOCUMENT_NODE = 9;
const unsigned short DOCUMENT_TYPE_NODE = 10; const unsigned short DOCUMENT_TYPE_NODE = 10;
const unsigned short DOCUMENT_FRAGMENT_NODE = 11; const unsigned short DOCUMENT_FRAGMENT_NODE = 11;
const unsigned short NOTATION_NODE = 12; const unsigned short NOTATION_NODE = 12;
... ...
} }
``` ```
@ -112,20 +112,20 @@ interface Node {
<li>Вася</li> <li>Вася</li>
<li>Петя</li> <li>Петя</li>
</ul> </ul>
<!-- комментарий --> <!-- комментарий -->
<script> <script>
var childNodes = document.body.childNodes; var childNodes = document.body.childNodes;
for (var i=0; i<childNodes.length; i++) { for (var i = 0; i < childNodes.length; i++) {
*!* *!*
// отфильтровать не-элементы // отфильтровать не-элементы
if (childNodes[i].nodeType != 1) continue; if (childNodes[i].nodeType != 1) continue;
*/!* */!*
alert(childNodes[i]); alert( childNodes[i] );
} }
</script> </script>
@ -145,8 +145,8 @@ interface Node {
```js ```js
//+ run //+ run
alert( document.body.nodeName ); // BODY alert( document.body.nodeName ); // BODY
alert( document.body.tagName ); // BODY alert( document.body.tagName ); // BODY
``` ```
[smart header="В XHTML `nodeName` может быть не в верхнем регистре"] [smart header="В XHTML `nodeName` может быть не в верхнем регистре"]
@ -172,17 +172,18 @@ XML-режим включается, когда браузер получает
```html ```html
<!--+ run --> <!--+ run -->
<body><!-- комментарий --> <body>
<!-- комментарий -->
<script> <script>
// для комментария // для комментария
alert(document.body.firstChild.nodeName); // #comment alert( document.body.firstChild.nodeName ); // #comment
alert(document.body.firstChild.tagName); // undefined (в IE8- воскл. знак "!") alert( document.body.firstChild.tagName ); // undefined (в IE8- воскл. знак "!")
// для документа // для документа
alert(document.nodeName); // #document, т.к. корень DOM -- не элемент alert( document.nodeName ); // #document, т.к. корень DOM -- не элемент
alert(document.tagName); // undefined alert( document.tagName ); // undefined
</script> </script>
</body> </body>
``` ```
@ -218,7 +219,7 @@ XML-режим включается, когда браузер получает
<script> <script>
document.body.innerHTML = '<b>тест'; // незакрытый тег document.body.innerHTML = '<b>тест'; // незакрытый тег
alert(document.body.innerHTML); // <b>тест</b> (исправлено) alert( document.body.innerHTML ); // <b>тест</b> (исправлено)
</script> </script>
</body> </body>
@ -270,7 +271,7 @@ chatDiv.innerHTML += "Как дела?";
<script> <script>
var elem = document.getElementById('my'); var elem = document.getElementById('my');
elem.innerHTML = 'ТЕСТ<script>alert(1);</scr'+'ipt>'; elem.innerHTML = 'ТЕСТ<script>alert( 1 );</scr' + 'ipt>';
</script> </script>
``` ```
@ -299,7 +300,7 @@ chatDiv.innerHTML += "Как дела?";
<script> <script>
var div = document.body.children[0]; var div = document.body.children[0];
alert(div.outerHTML); // <div>Привет <b>Мир</b></div> alert( div.outerHTML ); // <div>Привет <b>Мир</b></div>
</script> </script>
``` ```
@ -326,7 +327,7 @@ chatDiv.innerHTML += "Как дела?";
*!* *!*
// ... но содержимое div.outerHTML осталось тем же, несмотря на "перезапись" // ... но содержимое div.outerHTML осталось тем же, несмотря на "перезапись"
*/!* */!*
alert(div.outerHTML); // <div>Привет, Мир!</div> alert( div.outerHTML ); // <div>Привет, Мир!</div>
</script> </script>
``` ```
@ -354,9 +355,9 @@ chatDiv.innerHTML += "Как дела?";
Привет Привет
<!-- Комментарий --> <!-- Комментарий -->
<script> <script>
for (var i=0; i<document.body.childNodes.length; i++) { for (var i = 0; i < document.body.childNodes.length; i++) {
*!* *!*
alert(document.body.childNodes[i].data); alert( document.body.childNodes[i].data );
*/!* */!*
} }
</script> </script>
@ -489,9 +490,9 @@ chatDiv.innerHTML += "Как дела?";
<script> <script>
var input = document.body.children[0]; var input = document.body.children[0];
alert(input.type); // "text" alert( input.type ); // "text"
alert(input.id); // "input" alert( input.id ); // "input"
alert(input.value); // значение alert( input.value ); // значение
</script> </script>
``` ```

View file

@ -9,9 +9,9 @@
if (!Element.prototype.matches) { if (!Element.prototype.matches) {
// определяем свойство // определяем свойство
Element.prototype.matches = Element.prototype.matchesSelector || Element.prototype.matches = Element.prototype.matchesSelector ||
Element.prototype.webkitMatchesSelector || Element.prototype.webkitMatchesSelector ||
Element.prototype.mozMatchesSelector || Element.prototype.mozMatchesSelector ||
Element.prototype.msMatchesSelector, Element.prototype.msMatchesSelector,
} }

View file

@ -7,15 +7,14 @@
if (document.documentElement.textContent === undefined) { if (document.documentElement.textContent === undefined) {
// определяем свойство // определяем свойство
Object.defineProperty(HtmlElement.prototype, "textContent", { Object.defineProperty(HtmlElement.prototype, "textContent", {
get: function() { get: function() {
return this.innerText; return this.innerText;
}, },
set: function(value) { set: function(value) {
this.innerText = value; this.innerText = value;
}
} }
); });
} }
})(); })();

View file

@ -25,20 +25,20 @@
```js ```js
*!* *!*
if( document.documentElement.firstElementChild === undefined ) { // (1) if (document.documentElement.firstElementChild === undefined) { // (1)
*/!* */!*
*!* *!*
Object.defineProperty(Element.prototype, 'firstElementChild', { // (2) Object.defineProperty(Element.prototype, 'firstElementChild', { // (2)
*/!* */!*
get: function () { get: function() {
var el = this.firstChild; var el = this.firstChild;
do { do {
if( el.nodeType === 1 ) { if (el.nodeType === 1) {
return el; return el;
} }
el = el.nextSibling; el = el.nextSibling;
} while(el); } while (el);
return null; return null;
} }
@ -80,7 +80,7 @@ var div = document.createElement('div');
var input = document.createElement('input'); var input = document.createElement('input');
alert( input.value ); // пустая строка, поддержка есть alert( input.value ); // пустая строка, поддержка есть
alert( div.value ); // undefined, поддержки нет alert( div.value ); // undefined, поддержки нет
``` ```
[smart header="Поддержка значений свойств"] [smart header="Поддержка значений свойств"]
@ -98,8 +98,8 @@ alert( div.value ); // undefined, поддержки нет
<input type="no-such-type"> <input type="no-such-type">
<script> <script>
alert(document.body.children[0].type); // radio, поддерживается alert( document.body.children[0].type ); // radio, поддерживается
alert(document.body.children[1].type); // text, не поддерживается alert( document.body.children[1].type ); // text, не поддерживается
</script> </script>
``` ```
@ -136,7 +136,7 @@ alert( div.value ); // undefined, поддержки нет
```js ```js
//+ run //+ run
Element.prototype.sayHi = function() { Element.prototype.sayHi = function() {
alert("Привет от " + this); alert( "Привет от " + this );
} }
document.body.sayHi(); // Привет от [object HTMLBodyElement] document.body.sayHi(); // Привет от [object HTMLBodyElement]
@ -146,7 +146,7 @@ document.body.sayHi(); // Привет от [object HTMLBodyElement]
```js ```js
//+ run //+ run
Object.defineProperty(Element.prototype, 'lowerTag', { Object.defineProperty(Element.prototype, 'lowerTag', {
get: function() { get: function() {
return this.tagName.toLowerCase(); return this.tagName.toLowerCase();
} }

View file

@ -8,12 +8,12 @@
<script> <script>
var div = document.getElementById('widget'); var div = document.getElementById('widget');
var widgetName = div.getAttribute('data-widget-name'); var widgetName = div.getAttribute('data-widget-name');
// или так, кроме IE10- // или так, кроме IE10-
var widgetName = div.dataset.widgetName; var widgetName = div.dataset.widgetName;
alert( widgetName ); // "menu" alert( widgetName ); // "menu"
</script> </script>
</body> </body>
``` ```

View file

@ -13,9 +13,11 @@
```html ```html
<body> <body>
<div id="widget" data-widget-name="menu">Выберите жанр</div> <div id="widget" data-widget-name="menu">Выберите жанр</div>
<script>/* ... */</script> <script>
/* ... */
</script>
</body> </body>
``` ```

View file

@ -23,19 +23,19 @@
```js ```js
var links = document.querySelectorAll('a'); var links = document.querySelectorAll('a');
for(var i=0; i<links.length; i++) { for (var i = 0; i < links.length; i++) {
var a = links[i]; var a = links[i];
var href = a.getAttribute('href'); var href = a.getAttribute('href');
if (!href) continue; // нет атрибута if (!href) continue; // нет атрибута
if (href.indexOf('://') == -1) continue; // без протокола if (href.indexOf('://') == -1) continue; // без протокола
if (href.indexOf('http://internal.com') === 0) continue; // внутренняя if (href.indexOf('http://internal.com') === 0) continue; // внутренняя
a.classList.add('external'); a.classList.add('external');
} }
``` ```
@ -47,7 +47,7 @@ for(var i=0; i<links.length; i++) {
var css = 'a[href*="://"]:not([href^="http://internal.com"])'; var css = 'a[href*="://"]:not([href^="http://internal.com"])';
var links = document.querySelectorAll(css); var links = document.querySelectorAll(css);
for(var i=0; i<links.length; i++) { for (var i = 0; i < links.length; i++) {
links[i].classList.add('external'); links[i].classList.add('external');
} }
``` ```

View file

@ -9,17 +9,19 @@
```html ```html
<!--+ run --> <!--+ run -->
<style> <style>
.external { background-color: yellow } .external {
background-color: yellow
}
</style> </style>
<a name="list">список</a> <a name="list">список</a>
<ul> <ul>
<li><a href="http://google.com">http://google.com</a></li> <li><a href="http://google.com">http://google.com</a></li>
<li><a href="/tutorial">/tutorial.html</a></li> <li><a href="/tutorial">/tutorial.html</a></li>
<li><a href="local/path">local/path</a></li> <li><a href="local/path">local/path</a></li>
<li><a href="ftp://ftp.com/my.zip">ftp://ftp.com/my.zip</a></li> <li><a href="ftp://ftp.com/my.zip">ftp://ftp.com/my.zip</a></li>
<li><a href="http://nodejs.org">http://nodejs.org</a></li> <li><a href="http://nodejs.org">http://nodejs.org</a></li>
<li><a href="http://internal.com/test">http://internal.com/test</a></li> <li><a href="http://internal.com/test">http://internal.com/test</a></li>
</ul> </ul>
``` ```

View file

@ -19,22 +19,22 @@
```js ```js
//+ run //+ run
document.body.myData = { document.body.myData = {
name: 'Петр', name: 'Петр',
familyName: 'Петрович' familyName: 'Петрович'
}; };
alert(document.body.myData.name); // Петр alert( document.body.myData.name ); // Петр
``` ```
Можно добавить и новую функцию: Можно добавить и новую функцию:
```js ```js
//+ run //+ run
document.body.sayHi = function() { document.body.sayHi = function() {
alert(this.nodeName); alert( this.nodeName );
} }
document.body.sayHi(); // BODY, выполнилась с правильным this document.body.sayHi(); // BODY, выполнилась с правильным this
``` ```
@ -91,13 +91,13 @@ document.body.sayHi(); // BODY, выполнилась с правильным t
<script> <script>
alert( elem.getAttribute('About') ); // (1) 'Elephant', атрибут получен alert( elem.getAttribute('About') ); // (1) 'Elephant', атрибут получен
elem.setAttribute('Test', 123); // (2) атрибут Test установлен
alert( document.body.innerHTML ); // (3) в HTML видны все атрибуты!
var attrs = elem.attributes; // (4) можно получить коллекцию атрибутов elem.setAttribute('Test', 123); // (2) атрибут Test установлен
for (var i=0; i<attrs.length; i++) { alert( document.body.innerHTML ); // (3) в HTML видны все атрибуты!
alert(attrs[i].name + " = " + attrs[i].value);
var attrs = elem.attributes; // (4) можно получить коллекцию атрибутов
for (var i = 0; i < attrs.length; i++) {
alert( attrs[i].name + " = " + attrs[i].value );
} }
</script> </script>
</body> </body>
@ -162,7 +162,7 @@ document.body.sayHi(); // BODY, выполнилась с правильным t
// работа с checked через атрибут // работа с checked через атрибут
*/!* */!*
alert( input.getAttribute('checked') ); // пустая строка alert( input.getAttribute('checked') ); // пустая строка
input.removeAttribute('checked'); // снять галочку input.removeAttribute('checked'); // снять галочку
*!* *!*
// работа с checked через свойство // работа с checked через свойство
@ -189,7 +189,7 @@ document.body.sayHi(); // BODY, выполнилась с правильным t
*!* *!*
input.value = 'new'; // поменяли свойство input.value = 'new'; // поменяли свойство
alert(input.getAttribute('value')); // 'markup', не изменилось! alert( input.getAttribute('value') ); // 'markup', не изменилось!
*/!* */!*
</script> </script>
</body> </body>
@ -232,10 +232,10 @@ document.body.sayHi(); // BODY, выполнилась с правильным t
<body class="main page"> <body class="main page">
<script> <script>
// прочитать класс элемента // прочитать класс элемента
alert( document.body.className ); // main page alert( document.body.className ); // main page
// поменять класс элемента // поменять класс элемента
document.body.className="class1 class2"; document.body.className = "class1 class2";
</script> </script>
</body> </body>
``` ```
@ -269,16 +269,16 @@ document.body.sayHi(); // BODY, выполнилась с правильным t
<script> <script>
var classList = document.body.classList; var classList = document.body.classList;
classList.remove('page'); // удалить класс classList.remove('page'); // удалить класс
classList.add('post'); // добавить класс classList.add('post'); // добавить класс
for(var i=0; i<classList.length; i++) { // перечислить классы for (var i = 0; i < classList.length; i++) { // перечислить классы
alert(classList[i]); // main, затем post alert( classList[i] ); // main, затем post
} }
alert( classList.contains('post') ); // проверить наличие класса alert( classList.contains('post') ); // проверить наличие класса
alert( document.body.className ); // main post, тоже работает alert( document.body.className ); // main post, тоже работает
</script> </script>
</body> </body>
``` ```
@ -331,9 +331,11 @@ document.body.sayHi(); // BODY, выполнилась с правильным t
.order[order-state="new"] { .order[order-state="new"] {
color: green; color: green;
} }
.order[order-state="pending"] { .order[order-state="pending"] {
color: blue; color: blue;
} }
.order[order-state="canceled"] { .order[order-state="canceled"] {
color: red; color: red;
} }
@ -364,7 +366,7 @@ div.setAttribute('order-state', 'canceled');
Для классов -- нужно знать, какой класс у заказа сейчас. И тогда мы можем снять старый класс, и поставить новый: Для классов -- нужно знать, какой класс у заказа сейчас. И тогда мы можем снять старый класс, и поставить новый:
```js ```js
div.classList.remove('order-state-new'); div.classList.remove('order-state-new');
div.classList.add('order-state-canceled'); div.classList.add('order-state-canceled');
``` ```
@ -417,7 +419,7 @@ div.classList.add('order-state-canceled');
Этот атрибут должен прятать элемент, действие весьма простое, для его поддержки в HTML достаточно такого CSS: Этот атрибут должен прятать элемент, действие весьма простое, для его поддержки в HTML достаточно такого CSS:
```html ```html
<!--+ run height="80" --> <!--+ run height="80" no-beautify -->
<style> <style>
*!* *!*
[hidden] { display: none } [hidden] { display: none }
@ -441,7 +443,7 @@ div.classList.add('order-state-canceled');
```html ```html
<!--+ run height="80" --> <!--+ run height="80" no-beautify -->
<style> <style>
*!* *!*
[hidden] { display: none } [hidden] { display: none }
@ -485,7 +487,7 @@ div.classList.add('order-state-canceled');
//+ run //+ run
document.body.setAttribute('my', 123); document.body.setAttribute('my', 123);
alert( document.body.my ); // 123 в IE8- alert( document.body.my ); // 123 в IE8-
``` ```
При этом даже тип данных не меняется. Атрибут не становится строкой, как ему положено. При этом даже тип данных не меняется. Атрибут не становится строкой, как ему положено.

View file

@ -2,6 +2,6 @@
```html ```html
<!--+ run height=50 --> <!--+ run height=50 -->
<input type="button" onclick="this.style.display='none'" value="Нажми, чтобы меня спрятать"/> <input type="button" onclick="this.style.display='none'" value="Нажми, чтобы меня спрятать" />
``` ```

View file

@ -5,8 +5,8 @@
Для того, чтобы удалить функцию-обработчик, нужно где-то сохранить ссылку на неё, например так: Для того, чтобы удалить функцию-обработчик, нужно где-то сохранить ссылку на неё, например так:
```js ```js
function handler() { function handler() {
alert("1"); alert( "1" );
} }
button.addEventListener("click", handler); button.addEventListener("click", handler);

View file

@ -9,6 +9,7 @@
Что будет выведено при клике после выполнения кода? Что будет выведено при клике после выполнения кода?
```js ```js
//+ no-beautify
button.addEventListener("click", function() { alert("1"); }); button.addEventListener("click", function() { alert("1"); });
button.removeEventListener("click", function() { alert("1"); }); button.removeEventListener("click", function() { alert("1"); });

View file

@ -1,4 +1,3 @@
# Структура HTML/CSS
Для начала, зададим структуру HTML/CSS. Для начала, зададим структуру HTML/CSS.
@ -33,41 +32,36 @@
<span style="border: solid red 1px">[Сладости (нажми меня)!]</span> <span style="border: solid red 1px">[Сладости (нажми меня)!]</span>
``` ```
Раскрытие/закрытие делайте путём добавления/удаления класса `.menu-open` к меню, которые отвечает за стрелочку и отображение `UL`. Раскрытие/закрытие сделаем путём добавления/удаления класса `.menu-open` к меню, которые отвечает за стрелочку и отображение `UL`.
# CSS Обычно меню будет закрыто:
CSS для меню:
```css ```css
.menu ul { .menu ul {
margin: 0; margin: 0;
list-style: none; list-style: none;
padding-left: 20px; padding-left: 20px;
display: none; display: none;
} }
.menu .title { .menu .title::before {
padding-left: 16px; content: '▶ ';
font-size: 18px; font-size: 80%;
cursor: pointer; color: green;
background: url(...arrow-right.png) left center no-repeat;
} }
``` ```
Если же меню раскрыто, то есть имеет класс `.menu-open`, то стрелочка слева заголовка меняется и список детей показывается: Если же меню раскрыто, то есть имеет класс `.menu-open`, то стрелочка слева заголовка меняется и список детей показывается:
```css ```css
.menu-open .title { .menu.open .title::before {
background: url(...arrow-down.png) left center no-repeat; content: '▼ ';
} }
.menu-open ul { .menu.open ul {
display: block; display: block;
} }
``` ```
Теперь сделайте JavaScript. Для JavaScript остался минимум работы -- только добавить/удалить класс при клике.

View file

@ -26,7 +26,7 @@ p {
position: absolute; position: absolute;
font-size: 110%; font-size: 110%;
top: 0; top: 0;
color: red; color: darkred;
right: 10px; right: 10px;
display: block; display: block;
width: 24px; width: 24px;

View file

@ -22,7 +22,7 @@ p {
.remove-button { .remove-button {
font-size: 110%; font-size: 110%;
color: red; color: darkred;
right: 10px; right: 10px;
width: 24px; width: 24px;
height: 24px; height: 24px;

View file

@ -106,12 +106,12 @@
Пример установки обработчика `click`: Пример установки обработчика `click`:
```html ```html
<input id="elem" type="button" value="Нажми меня"/> <input id="elem" type="button" value="Нажми меня" />
<script> <script>
*!* *!*
elem.onclick = function() { elem.onclick = function() {
alert('Спасибо'); alert( 'Спасибо' );
}; };
*/!* */!*
</script> </script>
``` ```
@ -137,12 +137,12 @@ elem.onclick = function() {
```html ```html
<!--+ run height=50 --> <!--+ run height=50 -->
<input type="button" id="button" value="Кнопка"/> <input type="button" id="button" value="Кнопка" />
<script> <script>
*!* *!*
button.onclick = function() { button.onclick = function() {
alert('Клик!'); alert( 'Клик!' );
}; };
*/!* */!*
</script> </script>
``` ```
@ -156,12 +156,12 @@ button.onclick = function() {
```html ```html
<!--+ run height=50 autorun --> <!--+ run height=50 autorun -->
<input type="button" id="elem" onclick="alert('До')" value="Нажми меня"/> <input type="button" id="elem" onclick="alert('До')" value="Нажми меня" />
<script> <script>
*!* *!*
elem.onclick = function() { // перезапишет существующий обработчик elem.onclick = function() { // перезапишет существующий обработчик
alert('После'); // выведется только это alert( 'После' ); // выведется только это
}; };
*/!* */!*
</script> </script>
``` ```
@ -170,7 +170,7 @@ elem.onclick = function() { // перезапишет существующий
```js ```js
function sayThanks() { function sayThanks() {
alert('Спасибо!'); alert( 'Спасибо!' );
} }
elem.onclick = sayThanks; elem.onclick = sayThanks;
@ -211,7 +211,7 @@ button.onclick = sayThanks;
...А вот в разметке как раз скобки нужны: ...А вот в разметке как раз скобки нужны:
```html ```html
<input type="button" id="button" onclick="sayThanks()"/> <input type="button" id="button" onclick="sayThanks()" />
``` ```
Это различие просто объяснить. При создании обработчика браузером из атрибута, он автоматически создает функцию из его содержимого. Поэтому последний пример -- фактически то же самое, что: Это различие просто объяснить. При создании обработчика браузером из атрибута, он автоматически создает функцию из его содержимого. Поэтому последний пример -- фактически то же самое, что:
@ -219,7 +219,7 @@ button.onclick = sayThanks;
```js ```js
button.onclick = function() { button.onclick = function() {
*!* *!*
sayThanks(); // содержимое атрибута sayThanks(); // содержимое атрибута
*/!* */!*
}; };
``` ```
@ -234,7 +234,7 @@ button.onclick = function() {
Такой вызов работать не будет: Такой вызов работать не будет:
```js ```js
//+ run //+ run no-beautify
// при нажатии на body будут ошибки // при нажатии на body будут ошибки
// потому что при назначении в атрибут функция будет преобразована в строку // потому что при назначении в атрибут функция будет преобразована в строку
document.body.setAttribute('onclick', function() { alert(1) }); document.body.setAttribute('onclick', function() { alert(1) });
@ -255,6 +255,7 @@ document.body.setAttribute('onclick', function() { alert(1) });
При этом новый обработчик будет затирать предыдущий. Например, следующий код на самом деле назначает один обработчик -- последний: При этом новый обработчик будет затирать предыдущий. Например, следующий код на самом деле назначает один обработчик -- последний:
```js ```js
//+ no-beautify
input.onclick = function() { alert(1); } input.onclick = function() { alert(1); }
// ... // ...
input.onclick = function() { alert(2); } // заменит предыдущий обработчик input.onclick = function() { alert(2); } // заменит предыдущий обработчик
@ -269,7 +270,7 @@ input.onclick = function() { alert(2); } // заменит предыдущий
Назначение обработчика осуществляется вызовом `addEventListener` с тремя аргументами: Назначение обработчика осуществляется вызовом `addEventListener` с тремя аргументами:
```js ```js
element.addEventListener( event, handler[, phase]); element.addEventListener(event, handler[, phase]);
``` ```
<dl> <dl>
@ -285,7 +286,7 @@ element.addEventListener( event, handler[, phase]);
```js ```js
// передать те же аргументы, что были у addEventListener // передать те же аргументы, что были у addEventListener
element.removeEventListener( event, handler[, phase]); element.removeEventListener(event, handler[, phase]);
``` ```
[warn header="Удаление требует именно ту же функцию"] [warn header="Удаление требует именно ту же функцию"]
@ -294,6 +295,7 @@ element.removeEventListener( event, handler[, phase]);
Вот так `removeEventListener` не сработает: Вот так `removeEventListener` не сработает:
```js ```js
//+ no-beautify
elem.addEventListener( "click" , function() {alert('Спасибо!')}); elem.addEventListener( "click" , function() {alert('Спасибо!')});
// .... // ....
elem.removeEventListener( "click", function() {alert('Спасибо!')}); elem.removeEventListener( "click", function() {alert('Спасибо!')});
@ -305,12 +307,12 @@ elem.removeEventListener( "click", function() {alert('Спасибо!')});
```js ```js
function handler() { function handler() {
alert('Спасибо!'); alert( 'Спасибо!' );
} }
input.addEventListener( "click", handler); input.addEventListener("click", handler);
// .... // ....
input.removeEventListener( "click", handler); input.removeEventListener("click", handler);
``` ```
Обратим внимание -- если функцию не сохранить где-либо, а просто передать в `addEventListener`, как в предыдущем коде, то потом получить её обратно, чтобы снять обработчик, будет невозможно. Нет метода, который позволяет считать обработчики событий, назанченные через `addEventListener`. Обратим внимание -- если функцию не сохранить где-либо, а просто передать в `addEventListener`, как в предыдущем коде, то потом получить её обратно, чтобы снять обработчик, будет невозможно. Нет метода, который позволяет считать обработчики событий, назанченные через `addEventListener`.
@ -319,7 +321,7 @@ input.removeEventListener( "click", handler);
Метод `addEventListener` позволяет добавлять несколько обработчиков на одно событие одного элемента, например: Метод `addEventListener` позволяет добавлять несколько обработчиков на одно событие одного элемента, например:
```html ```html
<!--+ run --> <!--+ run no-beautify -->
<input id="elem" type="button" value="Нажми меня"/> <input id="elem" type="button" value="Нажми меня"/>
<script> <script>
@ -357,6 +359,7 @@ input.removeEventListener( "click", handler);
transition: width 1s; transition: width 1s;
width: 100px; width: 100px;
} }
.wide { .wide {
width: 300px; width: 300px;
} }
@ -367,14 +370,14 @@ input.removeEventListener( "click", handler);
</button> </button>
<script> <script>
elem.ontransitionend = function() { elem.ontransitionend = function() {
alert("ontransitionend"); // не сработает alert( "ontransitionend" ); // не сработает
}; };
*!* *!*
elem.addEventListener("transitionend", function() { elem.addEventListener("transitionend", function() {
alert("addEventListener"); // сработает по окончании анимации alert( "addEventListener" ); // сработает по окончании анимации
}, false); });
*/!* */!*
</script> </script>
``` ```
@ -390,24 +393,24 @@ input.removeEventListener( "click", handler);
Назначение обработчика осуществляется вызовом `attachEvent`: Назначение обработчика осуществляется вызовом `attachEvent`:
```js ```js
element.attachEvent( "on"+event, handler); element.attachEvent("on" + event, handler);
``` ```
Удаление обработчика -- вызовом `detachEvent`: Удаление обработчика -- вызовом `detachEvent`:
```js ```js
element.detachEvent( "on"+event, handler); element.detachEvent("on" + event, handler);
``` ```
Например: Например:
```js ```js
function handler() { function handler() {
alert('Спасибо!'); alert( 'Спасибо!' );
} }
button.attachEvent( "onclick" , handler) // Назначение обработчика button.attachEvent("onclick", handler) // Назначение обработчика
// .... // ....
button.detachEvent( "onclick", handler) // Удаление обработчика button.detachEvent("onclick", handler) // Удаление обработчика
``` ```
Как видите, почти то же самое, только событие должно включать префикс `on`. Как видите, почти то же самое, только событие должно включать префикс `on`.

View file

@ -50,7 +50,7 @@
В действии: В действии:
```html ```html
<!--+ autorun --> <!--+ autorun no-beautify -->
<textarea rows="6" cols="40" id="area">Кликни меня <textarea rows="6" cols="40" id="area">Кликни меня
</textarea> </textarea>
@ -103,7 +103,7 @@
При этом обработчик `onclick` вызовет метод `focus()` на текстовом поле `text`. Код обработчика `onfocus`, который при этом запустится, сработает синхронно, прямо сейчас, до завершения `onclick`. При этом обработчик `onclick` вызовет метод `focus()` на текстовом поле `text`. Код обработчика `onfocus`, который при этом запустится, сработает синхронно, прямо сейчас, до завершения `onclick`.
```html ```html
<!--+ autorun --> <!--+ autorun no-beautify -->
<input type="button" id="button" value="Нажми меня"> <input type="button" id="button" value="Нажми меня">
<input type="text" id="text" size="60"> <input type="text" id="text" size="60">
@ -147,7 +147,6 @@
<input type="text" id="text" size="60"> <input type="text" id="text" size="60">
<script> <script>
button.onclick = function() { button.onclick = function() {
text.value += ' ->в onclick '; text.value += ' ->в onclick ';
@ -156,10 +155,10 @@
text.focus(); // сработает после onclick text.focus(); // сработает после onclick
}, 0); }, 0);
*/!* */!*
text.value += ' из onclick-> '; text.value += ' из onclick-> ';
}; };
text.onfocus = function() { text.onfocus = function() {
text.value += ' !focus! '; text.value += ' !focus! ';
}; };

View file

@ -76,7 +76,7 @@ element.onclick = function(event) {
```js ```js
element.onclick = function(e) { element.onclick = function(e) {
e = e || event; e = e || event;
// Теперь e - объект события во всех браузерах. // Теперь e - объект события во всех браузерах.
}; };
@ -93,9 +93,9 @@ element.onclick = function(e) {
```js ```js
element.onclick = function(event) { element.onclick = function(event) {
event = event || window.event; event = event || window.event;
// Теперь event - объект события во всех браузерах. // Теперь event - объект события во всех браузерах.
}; };
``` ```
@ -103,8 +103,8 @@ element.onclick = function(event) {
```js ```js
element.onclick = function(e) { element.onclick = function(e) {
e = e || event; // если нет другой внешней переменной event e = e || event; // если нет другой внешней переменной event
... ...
}; };
``` ```

View file

@ -24,13 +24,16 @@
```html ```html
<!--+ run autorun --> <!--+ run autorun -->
<style> <style>
body * { margin: 10px; border: 1px solid blue; } body * {
margin: 10px;
border: 1px solid blue;
}
</style> </style>
<form onclick="alert('form')">FORM <form onclick="alert('form')">FORM
<div onclick="alert('div')">DIV <div onclick="alert('div')">DIV
<p onclick="alert('p')">P</p> <p onclick="alert('p')">P</p>
</div> </div>
</form> </form>
``` ```
@ -166,7 +169,7 @@ JS-код здесь такой:
var elems = document.querySelectorAll('form,div,p'); var elems = document.querySelectorAll('form,div,p');
// на каждый элемент повесить обработчик на стадии перехвата // на каждый элемент повесить обработчик на стадии перехвата
for(var i=0; i<elems.length; i++) { for (var i = 0; i < elems.length; i++) {
elems[i].addEventListener("click", highlightThis, true); elems[i].addEventListener("click", highlightThis, true);
} }
``` ```
@ -176,7 +179,7 @@ for(var i=0; i<elems.length; i++) {
```js ```js
var elems = document.querySelectorAll('form,div,p'); var elems = document.querySelectorAll('form,div,p');
for(var i=0; i<elems.length; i++) { for (var i = 0; i < elems.length; i++) {
elems[i].addEventListener("click", highlightThis, true); elems[i].addEventListener("click", highlightThis, true);
elems[i].addEventListener("click", highlightThis, false); elems[i].addEventListener("click", highlightThis, false);
} }
@ -218,6 +221,7 @@ elem.onclick = function(event) {
<dd>Кросс-браузерно остановить всплытие можно так: <dd>Кросс-браузерно остановить всплытие можно так:
```js ```js
//+ no-beautify
event.stopPropagation ? event.stopPropagation() : (event.cancelBubble=true); event.stopPropagation ? event.stopPropagation() : (event.cancelBubble=true);
``` ```

View file

@ -26,7 +26,7 @@ p {
position: absolute; position: absolute;
font-size: 110%; font-size: 110%;
top: 0; top: 0;
color: red; color: darkred;
right: 10px; right: 10px;
display: block; display: block;
width: 24px; width: 24px;

View file

@ -22,7 +22,7 @@ p {
.remove-button { .remove-button {
font-size: 110%; font-size: 110%;
color: red; color: darkred;
right: 10px; right: 10px;
width: 24px; width: 24px;
height: 24px; height: 24px;

View file

@ -11,18 +11,20 @@
```html ```html
<!--+ autorun height=190 untrusted --> <!--+ autorun height=190 untrusted -->
<style> <style>
li { border: 1px solid green; } li {
border: 1px solid green;
}
</style> </style>
<ul onclick="alert(event.target)"> <ul onclick="alert(event.target)">
<li>Млекопетающие <li>Млекопетающие
<ul> <ul>
<li>Коровы</li> <li>Коровы</li>
<li>Ослы</li> <li>Ослы</li>
<li>Собаки</li> <li>Собаки</li>
<li>Тигры</li> <li>Тигры</li>
</ul> </ul>
</li> </li>
</ul> </ul>
``` ```
@ -41,9 +43,9 @@ var treeUl = document.getElementsByTagName('ul')[0];
var treeLis = treeUl.getElementsByTagName('li'); var treeLis = treeUl.getElementsByTagName('li');
for(var i=0; i<treeLis.length; i++) { for (var i = 0; i < treeLis.length; i++) {
var li = treeLis[i]; var li = treeLis[i];
var span = document.createElement('span'); var span = document.createElement('span');
li.insertBefore(span, li.firstChild); // добавить пустой SPAN li.insertBefore(span, li.firstChild); // добавить пустой SPAN
span.appendChild(span.nextSibling); // переместить в него заголовок span.appendChild(span.nextSibling); // переместить в него заголовок
@ -57,18 +59,20 @@ for(var i=0; i<treeLis.length; i++) {
```html ```html
<!--+ autorun height=190 untrusted --> <!--+ autorun height=190 untrusted -->
<style> <style>
span { border: 1px solid red; } span {
border: 1px solid red;
}
</style> </style>
<ul onclick="alert(event.target.tagName)"> <ul onclick="alert(event.target.tagName)">
<li><span>Млекопетающие</span> <li><span>Млекопетающие</span>
<ul> <ul>
<li><span>Коровы</span></li> <li><span>Коровы</span></li>
<li><span>Ослы</span></li> <li><span>Ослы</span></li>
<li><span>Собаки</span></li> <li><span>Собаки</span></li>
<li><span>Тигры</span></li> <li><span>Тигры</span></li>
</ul> </ul>
</li> </li>
</ul> </ul>
``` ```
@ -88,10 +92,10 @@ var tree = document.getElementsByTagName('ul')[0];
tree.onclick = function(event) { tree.onclick = function(event) {
var target = event.target; var target = event.target;
if (target.tagName != 'SPAN') { if (target.tagName != 'SPAN') {
return; // клик был не на заголовке return; // клик был не на заголовке
} }
var li = target.parentNode; // получить родительский LI var li = target.parentNode; // получить родительский LI
// получить UL с потомками -- это первый UL внутри LI // получить UL с потомками -- это первый UL внутри LI

View file

@ -19,9 +19,9 @@
<th colspan="3"><em>Bagua</em> Chart: Direction, Element, Color, Meaning</th> <th colspan="3"><em>Bagua</em> Chart: Direction, Element, Color, Meaning</th>
</tr> </tr>
<tr> <tr>
<td>...<strong>Northwest</strong>...</td> <td>...<strong>Northwest</strong>...</td>
<td>...</td> <td>...</td>
<td>...</td> <td>...</td>
</tr> </tr>
<tr>...еще 2 строки такого же вида...</tr> <tr>...еще 2 строки такого же вида...</tr>
<tr>...еще 2 строки такого же вида...</tr> <tr>...еще 2 строки такого же вида...</tr>
@ -44,7 +44,7 @@ var selectedTd;
*!* *!*
table.onclick = function(event) { table.onclick = function(event) {
var target = event.target; // где был клик? var target = event.target; // где был клик?
if (target.tagName != 'TD') return; // не на TD? тогда не интересует if (target.tagName != 'TD') return; // не на TD? тогда не интересует
highlight(target); // подсветить TD highlight(target); // подсветить TD
@ -94,13 +94,13 @@ function highlight(node) {
```js ```js
table.onclick = function(event) { table.onclick = function(event) {
var target = event.target; var target = event.target;
// цикл двигается вверх от target к родителям до table // цикл двигается вверх от target к родителям до table
while(target != table) { while (target != table) {
if (target.tagName == 'TD') { if (target.tagName == 'TD') {
// нашли элемент, который нас интересует! // нашли элемент, который нас интересует!
highlight(target); highlight(target);
return; return;
} }
target = target.parentNode; target = target.parentNode;
} }
@ -115,7 +115,7 @@ table.onclick = function(event) {
Кстати, в проверке `while` можно бы было использовать `this` вместо `table`: Кстати, в проверке `while` можно бы было использовать `this` вместо `table`:
```js ```js
while(target != this) { while (target != this) {
// ... // ...
} }
``` ```
@ -128,13 +128,13 @@ while(target != this) {
```js ```js
table.onclick = function(event) { table.onclick = function(event) {
var target = event.target; var target = event.target;
var td = event.target.closest('td'); var td = event.target.closest('td');
if (!td) return; // клик вне <td>, не интересует if (!td) return; // клик вне <td>, не интересует
// если клик на td, но вне этой таблицы (возможно при вложенных таблицах) // если клик на td, но вне этой таблицы (возможно при вложенных таблицах)
// то не интересует // то не интересует
if (!table.contains(td)) return; if (!table.contains(td)) return;
// нашли элемент, который нас интересует! // нашли элемент, который нас интересует!
highlight(td); highlight(td);
@ -172,25 +172,31 @@ table.onclick = function(event) {
</div> </div>
<script> <script>
function Menu(elem) { function Menu(elem) {
this.save = function() { alert('сохраняю'); }; this.save = function() {
this.load = function() { alert('загружаю'); }; alert( 'сохраняю' );
this.search = function() { alert('ищу'); }; };
this.load = function() {
alert( 'загружаю' );
};
this.search = function() {
alert( 'ищу' );
};
var self = this; var self = this;
elem.onclick = function(e) { elem.onclick = function(e) {
var target = e.target; var target = e.target;
*!* *!*
var action = target.getAttribute('data-action'); var action = target.getAttribute('data-action');
if (action) { if (action) {
self[action](); self[action]();
} }
*/!* */!*
}; };
} }
new Menu(menu); new Menu(menu);
</script> </script>
``` ```

View file

@ -4,7 +4,7 @@
```js ```js
function(event) { function(event) {
handler() // тело взято из атрибута onclick handler() // тело взято из атрибута onclick
} }
``` ```

View file

@ -8,7 +8,7 @@
<!--+ autorun run --> <!--+ autorun run -->
<script> <script>
function handler() { function handler() {
alert("..."); alert( "..." );
return false; return false;
} }
</script> </script>

View file

@ -8,12 +8,12 @@
contents.onclick = function(evt) { contents.onclick = function(evt) {
var target = evt.target; var target = evt.target;
function handleLink(href) { function handleLink(href) {
var isLeaving = confirm('Уйти на '+href+'?'); var isLeaving = confirm('Уйти на ' + href + '?');
if (!isLeaving) return false; if (!isLeaving) return false;
} }
while(target != this) { while (target != this) {
if (target.nodeName == 'A') { if (target.nodeName == 'A') {
*!* *!*
return handleLink(target.getAttribute('href')); // (*) return handleLink(target.getAttribute('href')); // (*)

View file

@ -10,7 +10,7 @@ var largeImg = document.getElementById('largeImg');
document.getElementById('thumbs').onclick = function(e) { document.getElementById('thumbs').onclick = function(e) {
var target = e.target; var target = e.target;
while(target != this) { while (target != this) {
if (target.nodeName == 'A') { if (target.nodeName == 'A') {
showThumbnail(target.href, target.title); showThumbnail(target.href, target.title);
@ -34,11 +34,11 @@ function showThumbnail(href, title) {
```js ```js
var imgs = thumbs.getElementsByTagName('img'); var imgs = thumbs.getElementsByTagName('img');
for(var i=0; i<imgs.length; i++) { for (var i = 0; i < imgs.length; i++) {
var url = imgs[i].parentNode.href; var url = imgs[i].parentNode.href;
*!* *!*
var img = document.createElement('img'); var img = document.createElement('img');
img.src = url; img.src = url;
*/!* */!*
} }

View file

@ -24,7 +24,7 @@
В следующем примере при клике по ссылке переход не произойдет: В следующем примере при клике по ссылке переход не произойдет:
```html ```html
<!--+ autorun height=60 --> <!--+ autorun height=60 no-beautify -->
<a href="/" onclick="return false">Нажми здесь</a> <a href="/" onclick="return false">Нажми здесь</a>
или или
<a href="/" onclick="event.preventDefault()">здесь</a> <a href="/" onclick="event.preventDefault()">здесь</a>
@ -68,7 +68,7 @@ menu.onclick = function(event) {
if (event.target.nodeName != 'A') return; if (event.target.nodeName != 'A') return;
var href = event.target.getAttribute('href'); var href = event.target.getAttribute('href');
alert(href); // может быть подгрузка с сервера, генерация интерфейса и т.п. alert( href ); // может быть подгрузка с сервера, генерация интерфейса и т.п.
*!* *!*
return false; // отменить переход по url return false; // отменить переход по url
@ -127,7 +127,7 @@ menu.onclick = function(event) {
element.onclick = function(event) { element.onclick = function(event) {
event = event || window.event; event = event || window.event;
if (event.preventDefault) { // если метод существует if (event.preventDefault) { // если метод существует
event.preventDefault(); // то вызвать его event.preventDefault(); // то вызвать его
} else { // иначе вариант IE8-: } else { // иначе вариант IE8-:
event.returnValue = false; event.returnValue = false;
@ -138,6 +138,7 @@ element.onclick = function(event) {
Можно записать в одну строку: Можно записать в одну строку:
```js ```js
//+ no-beautify
... ...
event.preventDefault ? event.preventDefault() : (event.returnValue=false); event.preventDefault ? event.preventDefault() : (event.returnValue=false);
... ...

View file

@ -37,7 +37,7 @@ var event = new Event(тип события[, флаги]);
При просмотре примера ниже кнопка обработчик `onclick` на кнопке сработает сам по себе, событие генерируется скриптом: При просмотре примера ниже кнопка обработчик `onclick` на кнопке сработает сам по себе, событие генерируется скриптом:
```html ```html
<!--+ run --> <!--+ run no-beautify -->
<button id="elem" onclick="alert('Клик');">Автоклик</button> <button id="elem" onclick="alert('Клик');">Автоклик</button>
<script> <script>
@ -74,15 +74,17 @@ var event = new Event(тип события[, флаги]);
setTimeout(hide, 2000); setTimeout(hide, 2000);
function hide() { function hide() {
var event = new Event("hide", {cancelable: true}); var event = new Event("hide", {
cancelable: true
});
if (!rabbit.dispatchEvent(event)) { if (!rabbit.dispatchEvent(event)) {
alert('действие отменено'); alert( 'действие отменено' );
} else { } else {
rabbit.hidden = true; rabbit.hidden = true;
} }
} }
rabbit.addEventListener('hide', function(event) { rabbit.addEventListener('hide', function(event) {
if (confirm("Вызвать preventDefault?")) { if (confirm("Вызвать preventDefault?")) {
event.preventDefault(); event.preventDefault();
} }
@ -112,6 +114,7 @@ var event = new Event(тип события[, флаги]);
Другие свойства события, если они нужны, например координаты для события мыши -- можно присвоить в объект события позже, например: Другие свойства события, если они нужны, например координаты для события мыши -- можно присвоить в объект события позже, например:
```js ```js
//+ no-beautify
var event = new Event("click", {bubbles: true, cancelable: false}); var event = new Event("click", {bubbles: true, cancelable: false});
event.clientX = 100; event.clientX = 100;
event.clientY = 100; event.clientY = 100;
@ -124,7 +127,7 @@ event.clientY = 100;
Всё, что для этого нужно -- это флаг `bubbles`: Всё, что для этого нужно -- это флаг `bubbles`:
```html ```html
<!--+ run --> <!--+ run no-beautify -->
<h1 id="elem">Привет от скрипта!</h1> <h1 id="elem">Привет от скрипта!</h1>
<script> <script>
@ -179,7 +182,7 @@ var e = new MouseEvent("click", {
}); });
*!* *!*
alert(e.clientX); // 100 alert( e.clientX ); // 100
*/!* */!*
``` ```
@ -195,7 +198,7 @@ var e = new Event("click", {
}); });
*!* *!*
alert(e.clientX); // undefined, свойство не присвоено! alert( e.clientX ); // undefined, свойство не присвоено!
*/!* */!*
``` ```
@ -275,7 +278,10 @@ event.initEvent(type, boolean bubbles, boolean cancelable);
```js ```js
// современный стандарт // современный стандарт
var event = new Event("click", { bubbles: true, cancelable: true }); var event = new Event("click", {
bubbles: true,
cancelable: true
});
// старый стандарт // старый стандарт
var event = document.createEvent("Event"); var event = document.createEvent("Event");
@ -291,9 +297,9 @@ event.initEvent("click", true, true);
<h1 id="elem">Привет от скрипта!</h1> <h1 id="elem">Привет от скрипта!</h1>
<script> <script>
document.addEventListener("hello", function(event) { document.addEventListener("hello", function(event) {
alert("Привет"); alert( "Привет" );
event.preventDefault(); event.preventDefault();
}, false); }, false);
*!* *!*
@ -302,9 +308,8 @@ event.initEvent("click", true, true);
*/!* */!*
if (elem.dispatchEvent(event) === false) { if (elem.dispatchEvent(event) === false) {
alert('Событие было отменено preventDefault'); alert( 'Событие было отменено preventDefault' );
} }
</script> </script>
``` ```
@ -318,22 +323,22 @@ event.initEvent("click", true, true);
Выглядят они немного страшновато, например (взято из [спецификации](http://www.w3.org/TR/DOM-Level-3-Events/#idl-interface-MouseEvent-initializers)): Выглядят они немного страшновато, например (взято из [спецификации](http://www.w3.org/TR/DOM-Level-3-Events/#idl-interface-MouseEvent-initializers)):
```js ```js
void initMouseEvent ( void initMouseEvent(
DOMString typeArg, // тип DOMString typeArg, // тип
boolean bubblesArg, // всплывает? boolean bubblesArg, // всплывает?
boolean cancelableArg, // можно отменить? boolean cancelableArg, // можно отменить?
AbstractView? viewArg, // объект window, null означает текущее окно AbstractView ? viewArg, // объект window, null означает текущее окно
long detailArg, // свойство detail и другие... long detailArg, // свойство detail и другие...
long screenXArg, long screenXArg,
long screenYArg, long screenYArg,
long clientXArg, long clientXArg,
long clientYArg, long clientYArg,
boolean ctrlKeyArg, boolean ctrlKeyArg,
boolean altKeyArg, boolean altKeyArg,
boolean shiftKeyArg, boolean shiftKeyArg,
boolean metaKeyArg, boolean metaKeyArg,
unsigned short buttonArg, unsigned short buttonArg,
EventTarget? relatedTargetArg); EventTarget ? relatedTargetArg);
}; };
``` ```
@ -345,7 +350,7 @@ void initMouseEvent (
<script> <script>
elem.onclick = function(e) { elem.onclick = function(e) {
alert('Клик на координатах ' + e.clientX + ':' + e.clientY); alert( 'Клик на координатах ' + e.clientX + ':' + e.clientY );
}; };
var event = document.createEvent("MouseEvent"); var event = document.createEvent("MouseEvent");
@ -371,9 +376,9 @@ try {
window.CustomEvent = function(event, params) { window.CustomEvent = function(event, params) {
var evt; var evt;
params = params || { params = params || {
bubbles: false, bubbles: false,
cancelable: false, cancelable: false,
detail: undefined detail: undefined
}; };
evt = document.createEvent("CustomEvent"); evt = document.createEvent("CustomEvent");
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
@ -399,15 +404,15 @@ try {
<script> <script>
document.body.onclick = function() { document.body.onclick = function() {
alert("Клик, event.type=" + event.type); alert( "Клик, event.type=" + event.type );
return false; return false;
}; };
*!* *!*
var event = document.createEventObject(); var event = document.createEventObject();
if( !elem.fireEvent("onclick", event) ) { if (!elem.fireEvent("onclick", event)) {
alert('Событие было отменено'); alert( 'Событие было отменено' );
} }
*/!* */!*
</script> </script>
``` ```

Some files were not shown because too many files have changed in this diff Show more