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

@ -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>
@ -25,7 +25,7 @@ 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
@ -35,7 +35,7 @@ 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).
**Скобки могут быть и вложенными. В этом случае нумерация также идёт слева направо.** **Скобки могут быть и вложенными. В этом случае нумерация также идёт слева направо.**

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`:
@ -92,7 +92,7 @@ document.cookie="name=; path=/; expires="+date.toUTCString();
При удалении значение не важно. Можно его не указывать, как сделано в коде выше. При удалении значение не важно. Можно его не указывать, как сделано в коде выше.
### Функция setCookie(name, value, options) ## Функция setCookie(name, value, options)
Если собрать все настройки воедино, вот такая функция ставит куки: Если собрать все настройки воедино, вот такая функция ставит куки:
@ -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
})
} }
``` ```
@ -248,6 +250,6 @@ if (!navigator.cookieEnabled) {
...Конечно, предполагается, что включён 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

@ -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, одинаковые
``` ```
@ -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]
@ -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,7 +161,7 @@ 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
@ -175,7 +175,7 @@ for(var i=0; i<result.length; i++) alert(result[i])
### Найти всё с учётом скобочных групп ### Найти всё с учётом скобочных групп
В сколько-нибудь сложных задачах важны не только совпадения, но и скобочные группы. Чтобы их найти, предлагается использовать многократный вызов [: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> используется как точка отсчета для следующего поиска:

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>
@ -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

@ -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

View file

@ -148,8 +148,7 @@ if( body.compareDocumentPosition(li) & 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

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

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

@ -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>
@ -216,7 +216,6 @@ parentElem.appendChild(elem)
// вставим её после текущего сообщения // вставим её после текущего сообщения
div.parentNode.insertBefore(div2, div.nextSibling); div.parentNode.insertBefore(div2, div.nextSibling);
*/!* */!*
</script> </script>
``` ```
@ -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>

View file

@ -21,6 +21,7 @@ for(...) ul.appendChild(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); // затем в документ
@ -122,7 +123,7 @@ 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, но в него они добавляются тем же полифиллом:
@ -211,6 +212,7 @@ 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>
@ -233,6 +235,7 @@ ul.appendChild(fragment); // вместо фрагмента вставятс
</script> </script>
</body> </body>
</html> </html>
``` ```

View file

@ -34,9 +34,13 @@ HTML-документ ниже будет содержать `1 2 3`.
</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>
``` ```

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
@ -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,8 +191,11 @@ 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>
@ -264,8 +268,11 @@ 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;

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

@ -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;
} }
``` ```

View file

@ -80,7 +80,10 @@ function getCoords(elem) {
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,7 +107,8 @@ 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);
@ -112,7 +116,10 @@ function getOffsetSum(elem) {
elem = elem.offsetParent; elem = elem.offsetParent;
} }
return {top: top, left: left}; return {
top: top,
left: left
};
} }
``` ```

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,6 +6,7 @@
```html ```html
<html> <html>
<head> <head>
*!* *!*
<script> <script>
@ -13,9 +14,11 @@
</script> </script>
*/!* */!*
</head> </head>
<body> <body>
Привет, мир! Привет, мир!
</body> </body>
</html> </html>
``` ```

View file

@ -13,7 +13,7 @@ DOM -- это представление документа в виде дере
Построим, для начала, дерево DOM для следующего документа. Построим, для начала, дерево DOM для следующего документа.
```html ```html
<!--+ run --> <!--+ run no-beautify -->
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<head> <head>
@ -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,6 +149,7 @@ drawHtmlTree(node, 'div.domtree', 600, 200);
```html ```html
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<body> <body>
Правда о лосях Правда о лосях
<ol> <ol>
@ -155,6 +160,7 @@ drawHtmlTree(node, 'div.domtree', 600, 200);
<li>...и коварное!</li> <li>...и коварное!</li>
</ol> </ol>
</body> </body>
</html> </html>
``` ```
@ -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> <head>
<title>О лосях</title> <title>О лосях</title>
</head> </head>
<body> <body>
Правда о лосях Правда о лосях
</body> </body>
</html> </html>
``` ```

View file

@ -7,7 +7,11 @@
```html ```html
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<head><meta charset="utf-8"></head>
<head>
<meta charset="utf-8">
</head>
<body> <body>
<div>Пользователи:</div> <div>Пользователи:</div>
<ul> <ul>
@ -22,6 +26,7 @@
</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,6 +36,7 @@ DOM позволяет делать что угодно с HTML-элементо
<!--+ run --> <!--+ run -->
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<head> <head>
<script> <script>
*!* *!*
@ -43,6 +44,7 @@ DOM позволяет делать что угодно с HTML-элементо
*/!* */!*
</script> </script>
</head> </head>
<body> <body>
<script> <script>
@ -50,6 +52,7 @@ DOM позволяет делать что угодно с HTML-элементо
</script> </script>
</body> </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>
@ -94,6 +98,7 @@ DOM позволяет делать что угодно с HTML-элементо
</script> </script>
... ...
</body> </body>
</html> </html>
``` ```
@ -242,6 +247,7 @@ for(var key in elems) {
<!--+ run --> <!--+ run -->
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<body> <body>
<div>Начало</div> <div>Начало</div>
@ -260,6 +266,7 @@ for(var key in elems) {
</script> </script>
... ...
</body> </body>
</html> </html>
``` ```

View file

@ -102,7 +102,6 @@ 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');
@ -112,7 +111,6 @@ var elements = document.getElementsByTagName('div');
var input = elements[i]; var input = elements[i];
alert( input.value + ': ' + input.checked ); alert( input.value + ': ' + input.checked );
} }
</script> </script>
``` ```
@ -306,8 +304,9 @@ 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

@ -36,7 +36,6 @@
<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');

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

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

View file

@ -7,11 +7,13 @@
```html ```html
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<body> <body>
<script> <script>
alert( document.body.lastChild.nodeType ); alert( document.body.lastChild.nodeType );
</script> </script>
</body> </body>
</html> </html>
``` ```

View file

@ -172,7 +172,8 @@ XML-режим включается, когда браузер получает
```html ```html
<!--+ run --> <!--+ run -->
<body><!-- комментарий --> <body>
<!-- комментарий -->
<script> <script>
// для комментария // для комментария

View file

@ -14,8 +14,7 @@
set: function(value) { set: function(value) {
this.innerText = value; this.innerText = value;
} }
} });
);
} }
})(); })();

View file

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

View file

@ -9,7 +9,9 @@
```html ```html
<!--+ run --> <!--+ run -->
<style> <style>
.external { background-color: yellow } .external {
background-color: yellow
}
</style> </style>
<a name="list">список</a> <a name="list">список</a>

View file

@ -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;
} }
@ -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 }

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

@ -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); } // заменит предыдущий обработчик
@ -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('Спасибо!')});
@ -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;
} }
@ -374,7 +377,7 @@ input.removeEventListener( "click", handler);
*!* *!*
elem.addEventListener("transitionend", function() { elem.addEventListener("transitionend", function() {
alert( "addEventListener" ); // сработает по окончании анимации alert( "addEventListener" ); // сработает по окончании анимации
}, false); });
*/!* */!*
</script> </script>
``` ```

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 ';

View file

@ -24,7 +24,10 @@
```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
@ -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,7 +11,9 @@
```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)">
@ -57,7 +59,9 @@ 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)">

View file

@ -173,9 +173,15 @@ table.onclick = function(event) {
<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;

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>
@ -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,7 +74,9 @@ 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 {
@ -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>
@ -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");
@ -304,7 +310,6 @@ event.initEvent("click", true, true);
if (elem.dispatchEvent(event) === false) { if (elem.dispatchEvent(event) === false) {
alert( 'Событие было отменено preventDefault' ); alert( 'Событие было отменено preventDefault' );
} }
</script> </script>
``` ```

View file

@ -77,7 +77,7 @@
Это событие срабатывает при клике правой кнопкой мыши: Это событие срабатывает при клике правой кнопкой мыши:
```html ```html
<!--+ autorun height=80 --> <!--+ autorun height=80 no-beautify -->
<div>Правый клик на этой кнопке выведет "Клик".</div> <div>Правый клик на этой кнопке выведет "Клик".</div>
<button oncontextmenu="alert('Клик!');">Правый клик сюда</button> <button oncontextmenu="alert('Клик!');">Правый клик сюда</button>
``` ```
@ -89,7 +89,7 @@
В примере ниже встроенное меню показано не будет: В примере ниже встроенное меню показано не будет:
```html ```html
<!--+ autorun height=60 --> <!--+ autorun height=60 no-beautify -->
<button oncontextmenu="alert('Клик!');return false">Правый клик сюда</button> <button oncontextmenu="alert('Клик!');return false">Правый клик сюда</button>
``` ```

View file

@ -9,6 +9,7 @@
Пример использования: Пример использования:
```js ```js
//+ no-beautify
addScripts(["a.js", "b.js", "c.js"], function() { a() }); addScripts(["a.js", "b.js", "c.js"], function() { a() });
/* функция a() описана в a.js и использует b.js,c.js */ /* функция a() описана в a.js и использует b.js,c.js */
``` ```

View file

@ -89,7 +89,7 @@ script.onerror = function() {
Например, рабочий скрипт: Например, рабочий скрипт:
```js ```js
//+ run //+ run no-beautify
var script = document.createElement('script'); var script = document.createElement('script');
script.src = "https://code.jquery.com/jquery.js"; script.src = "https://code.jquery.com/jquery.js";
document.documentElement.appendChild(script); document.documentElement.appendChild(script);
@ -104,7 +104,7 @@ script.onreadystatechange = function() {
Скрипт с ошибкой: Скрипт с ошибкой:
```js ```js
//+ run //+ run no-beautify
var script = document.createElement('script'); var script = document.createElement('script');
script.src = "http://ajax.googleapis.com/404.js"; script.src = "http://ajax.googleapis.com/404.js";
document.documentElement.appendChild(script); document.documentElement.appendChild(script);
@ -132,7 +132,7 @@ script.onreadystatechange = function() {
Пример ниже вызывает `afterLoad` после загрузки скрипта и работает только в IE: Пример ниже вызывает `afterLoad` после загрузки скрипта и работает только в IE:
```js ```js
//+ run //+ run no-beautify
var script = document.createElement('script'); var script = document.createElement('script');
script.src = "https://code.jquery.com/jquery.js"; script.src = "https://code.jquery.com/jquery.js";
document.documentElement.appendChild(script); document.documentElement.appendChild(script);
@ -189,7 +189,9 @@ script.onload = script.onerror = function() {
script.onreadystatechange = function() { script.onreadystatechange = function() {
var self = this; var self = this;
if (this.readyState == "complete" || this.readyState == "loaded") { if (this.readyState == "complete" || this.readyState == "loaded") {
setTimeout(function() { self.onload() }, 0);// сохранить "this" для onload setTimeout(function() {
self.onload()
}, 0); // сохранить "this" для onload
} }
}; };
``` ```
@ -221,6 +223,7 @@ script.onreadystatechange = function() {
<dd>Ставим обработчики на `onload` + `onerror` <dd>Ставим обработчики на `onload` + `onerror`
```js ```js
//+ no-beautify
var img = document.createElement('img'); var img = document.createElement('img');
img.onload = function() { alert("Успех "+this.src }; img.onload = function() { alert("Успех "+this.src };
img.onerror = function() { alert("Ошибка "+this.src }; img.onerror = function() { alert("Ошибка "+this.src };

View file

@ -99,8 +99,12 @@
<!--+ autorun height=auto --> <!--+ autorun height=auto -->
<style> <style>
b { b {
-webkit-user-select: none; /* user-select -- это нестандартное свойство */ -webkit-user-select: none;
-moz-user-select: none; /* поэтому нужны префиксы */ /* user-select -- это нестандартное свойство */
-moz-user-select: none;
/* поэтому нужны префиксы */
-ms-user-select: none; -ms-user-select: none;
} }
</style> </style>
@ -171,7 +175,7 @@ elem.onmousedown = elem.onselectstart = function() {
Если уж хочется запретить копирование -- можно использовать событие `oncopy`: Если уж хочется запретить копирование -- можно использовать событие `oncopy`:
```html ```html
<!--+ autorun height=80 --> <!--+ autorun height=80 no-beautify -->
<div oncopy="alert('Копирование запрещено');return false"> <div oncopy="alert('Копирование запрещено');return false">
Уважаемый копирователь, Уважаемый копирователь,
почему-то автор хочет заставить вас покопаться в исходном коде этой страницы. почему-то автор хочет заставить вас покопаться в исходном коде этой страницы.

View file

@ -356,6 +356,7 @@ function findDroppable(event) {
Для его создания используем не обычный синтаксис `{...}`, а вызов `new function`. Это позволит прямо при создании объявить дополнительные переменные и функции в замыкании, которыми могут пользоваться методы объекта, а также назначить обработчики: Для его создания используем не обычный синтаксис `{...}`, а вызов `new function`. Это позволит прямо при создании объявить дополнительные переменные и функции в замыкании, которыми могут пользоваться методы объекта, а также назначить обработчики:
```js ```js
//+ no-beautify
var DragManager = new function() { var DragManager = new function() {
var dragObject = {}; var dragObject = {};
@ -400,6 +401,7 @@ var DragManager = new function() {
С использованием `DragManager` пример, с которого начиналась эта глава -- перенос иконок браузеров в компьютер, реализуется совсем просто: С использованием `DragManager` пример, с которого начиналась эта глава -- перенос иконок браузеров в компьютер, реализуется совсем просто:
```js ```js
//+ no-beautify
DragManager.onDragEnd = function(dragObject, dropElem) { DragManager.onDragEnd = function(dragObject, dropElem) {
// скрыть/удалить переносимый объект // скрыть/удалить переносимый объект

View file

@ -9,7 +9,7 @@
Несмотря на то, что колёсико мыши обычно ассоциируется с прокруткой, это совсем разные вещи. Несмотря на то, что колёсико мыши обычно ассоциируется с прокруткой, это совсем разные вещи.
<ul> <ul>
<li>При прокрутке срабатывает событие [onscroll](/event-onscroll) -- рассмотрим его в дальнейшем. Оно произойдёт *при любой прокрутке*, в том числе через клавиатурy, но *только на прокручиваемых элементах*. Например, элемент с `overflow:hidden` в принципе не может сгенерировать `onscroll`.</li> <li>При прокрутке срабатывает событие [onscroll](/onscroll) -- рассмотрим его в дальнейшем. Оно произойдёт *при любой прокрутке*, в том числе через клавиатурy, но *только на прокручиваемых элементах*. Например, элемент с `overflow:hidden` в принципе не может сгенерировать `onscroll`.</li>
<li>А событие `wheel` является чисто "мышиным". Оно генерируется *над любым элементом* при передвижении колеса мыши. При этом не важно, прокручиваемый он или нет. В частности, `overflow:hidden` никак не препятствует обработке колеса мыши.</li> <li>А событие `wheel` является чисто "мышиным". Оно генерируется *над любым элементом* при передвижении колеса мыши. При этом не важно, прокручиваемый он или нет. В частности, `overflow:hidden` никак не препятствует обработке колеса мыши.</li>
</ul> </ul>

View file

@ -7,6 +7,7 @@
Например, код ниже выведет `alert` при одновременном нажатии клавиш `"Q"` и `"W"` (в любом регистре, в любой раскладке) Например, код ниже выведет `alert` при одновременном нажатии клавиш `"Q"` и `"W"` (в любом регистре, в любой раскладке)
```js ```js
//+ no-beautify
runOnKeys( runOnKeys(
function() { alert("Привет!") }, function() { alert("Привет!") },
"Q".charCodeAt(0), "Q".charCodeAt(0),

View file

@ -11,6 +11,7 @@
Например: Например:
```js ```js
//+ no-beautify
document.forms.my -- форма с именем 'my' document.forms.my -- форма с именем 'my'
document.forms[0] -- первая форма в документе document.forms[0] -- первая форма в документе
``` ```
@ -68,7 +69,8 @@ alert(elems[0].value); // 10, первый input
<!--+ run height=80 --> <!--+ run height=80 -->
<body> <body>
<form> <form>
<fieldset name="set"><legend>fieldset</legend> <fieldset name="set">
<legend>fieldset</legend>
<input name="text" type="text"> <input name="text" type="text">
</fieldset> </fieldset>
</form> </form>
@ -84,7 +86,7 @@ alert( form.elements.set.elements.text ); // INPUT
</body> </body>
``` ```
Спецификация: [HTML5 Forms](http://www.w3.org/TR/html5/forms.html). Спецификация: [HTML5 Forms](https://html.spec.whatwg.org/multipage/forms.html).
[warn header="Доступ `form.name` тоже работает, но с особенностями"] [warn header="Доступ `form.name` тоже работает, но с особенностями"]
Получить доступ к элементам формы можно не только через `form.elements[name/index]`, но и проще: `form[index/name]`. Получить доступ к элементам формы можно не только через `form.elements[name/index]`, но и проще: `form[index/name]`.
@ -95,7 +97,9 @@ alert( form.elements.set.elements.text ); // INPUT
```html ```html
<!--+ run height=40 --> <!--+ run height=40 -->
<form name="myform"> <input name="text"> </form> <form name="myform">
<input name="text">
</form>
<script> <script>
var form = document.forms.myform; var form = document.forms.myform;
@ -138,7 +142,7 @@ alert(elem.form == form); // true
</body> </body>
``` ```
Познакомиться с другими свойствами элементов можно в спецификации [HTML5 Forms](http://www.w3.org/TR/html5/forms.html). Познакомиться с другими свойствами элементов можно в спецификации [HTML5 Forms](https://html.spec.whatwg.org/multipage/forms.html).
## Элемент label ## Элемент label
@ -157,12 +161,20 @@ alert(elem.form == form); // true
<!--+ autorun --> <!--+ autorun -->
<table> <table>
<tr> <tr>
<td><label for="agree">Согласен с правилами</label></td> <td>
<td><input id="agree" type="checkbox"></td> <label for="agree">Согласен с правилами</label>
</td>
<td>
<input id="agree" type="checkbox">
</td>
</tr> </tr>
<tr> <tr>
<td><label for="not-a-robot">Я не робот</label></td> <td>
<td><input id="not-a-robot" type="checkbox"></td> <label for="not-a-robot">Я не робот</label>
</td>
<td>
<input id="not-a-robot" type="checkbox">
</td>
</tr> </tr>
</table> </table>
``` ```
@ -171,7 +183,7 @@ alert(elem.form == form); // true
<li>Завернуть элемент в `label`. В этом случае можно обойтись без дополнительных атрибутов: <li>Завернуть элемент в `label`. В этом случае можно обойтись без дополнительных атрибутов:
```html ```html
<!--+ autorun --> <!--+ autorun no-beautify -->
<label>Кликни меня <input type="checkbox"></label> <label>Кликни меня <input type="checkbox"></label>
``` ```
@ -242,10 +254,10 @@ for (var i=0; i<select.options.length; i++) {
</script> </script>
``` ```
Спецификация: <a href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-94282980">HTMLSelectElement</a>. Спецификация: [the select element](https://html.spec.whatwg.org/multipage/forms.html#the-select-element).
[smart header="`new Option`"] [smart header="`new Option`"]
В стандарте [the Option Element](http://dev.w3.org/html5/spec/the-option-element.html#the-option-element) есть любопытный короткий синтаксис для создания элемента с тегом `option`: В стандарте [the option element](https://html.spec.whatwg.org/multipage/forms.html#the-option-element) есть любопытный короткий синтаксис для создания элемента с тегом `option`:
```js ```js
option = new Option(text, value, defaultSelected, selected); option = new Option(text, value, defaultSelected, selected);
@ -275,7 +287,7 @@ var option = new Option("Текст", "value", true, true);
[smart header="Дополнительные свойства `option`"] [smart header="Дополнительные свойства `option`"]
У элементов `option` также есть особые свойства, которые могут оказаться полезными (см. [The Option Element](http://dev.w3.org/html5/spec/the-option-element.html#the-option-element)): У элементов `option` также есть особые свойства, которые могут оказаться полезными (см. [the option element](https://html.spec.whatwg.org/multipage/forms.html#the-option-element)):
<dl> <dl>
<dt>`selected`</dt> <dt>`selected`</dt>

View file

@ -5,7 +5,8 @@
Так как мы преобразуем `<div>` в `<textarea>` и обратно, нам нужно сделать их практически одинаковыми с виду: Так как мы преобразуем `<div>` в `<textarea>` и обратно, нам нужно сделать их практически одинаковыми с виду:
```css ```css
#view, #area { #view,
#area {
height: 150px; height: 150px;
width: 400px; width: 400px;
font-family: arial; font-family: arial;
@ -20,6 +21,7 @@
```css ```css
#view { #view {
/* padding + border = 3px */ /* padding + border = 3px */
padding: 2px; padding: 2px;
border: 1px solid black; border: 1px solid black;
} }
@ -31,7 +33,6 @@ CSS для `#area` заменяет поля границами:
#area { #area {
border: 3px groove blue; border: 3px groove blue;
padding: 0px; padding: 0px;
display: none; display: none;
} }
``` ```
@ -39,6 +40,7 @@ CSS для `#area` заменяет поля границами:
По умолчанию, текстовое поле скрыто. Кстати, этот код убирает дополнительную рамку в ряде браузеров, которая появляется вокруг поля, когда на него попадает фокус: По умолчанию, текстовое поле скрыто. Кстати, этот код убирает дополнительную рамку в ряде браузеров, которая появляется вокруг поля, когда на него попадает фокус:
```css ```css
/*+ no-beautify */
#area:focus { #area:focus {
outline: none; /* убирает рамку при фокусе */ outline: none; /* убирает рамку при фокусе */
} }

View file

@ -57,23 +57,32 @@
```html ```html
<!--+ run autorun height=80 --> <!--+ run autorun height=80 -->
<style> .error { background: red; } </style> <style>
.error {
background: red;
}
</style>
<div>Возраст: <input type="text" id="age"></div> <div>Возраст:
<input type="text" id="age">
</div>
<div>Имя: <input type="text"></div> <div>Имя:
<input type="text">
</div>
<script> <script>
age.onblur = function() { age.onblur = function() {
if (isNaN(this.value)) { // введено не число if (isNaN(this.value)) { // введено не число
// показать ошибку // показать ошибку
this.classList.add("error"); this.classList.add("error");
age.focus();*!* *!*
age.focus();
*/!*
} else { } else {
this.classList.remove("error"); this.classList.remove("error");
} }
}; };
</script> </script>
``` ```
@ -175,7 +184,7 @@ age.onblur = function() {
В примере ниже есть список элементов. Кликните на любой из них и нажмите "tab". В примере ниже есть список элементов. Кликните на любой из них и нажмите "tab".
```html ```html
<!--+ autorun --> <!--+ autorun no-beautify -->
Кликните на первый элемент списка и нажмите Tab. Внимание! Дальнейшие нажатия Tab могут вывести за границы iframe'а с примером. Кликните на первый элемент списка и нажмите Tab. Внимание! Дальнейшие нажатия Tab могут вывести за границы iframe'а с примером.
<ul> <ul>
<li tabindex="1">Один</li> <li tabindex="1">Один</li>
@ -225,7 +234,11 @@ age.onblur = function() {
<input type="text" name="surname" value="Ваша фамилия"> <input type="text" name="surname" value="Ваша фамилия">
</form> </form>
<style> .focused { outline: 1px solid red; } </style> <style>
.focused {
outline: 1px solid red;
}
</style>
<script> <script>
*!* *!*
@ -262,12 +275,19 @@ age.onblur = function() {
<input type="text" name="surname" value="Ваша фамилия"> <input type="text" name="surname" value="Ваша фамилия">
</form> </form>
<style> <style>
.focused { outline: 1px solid red; } .focused {
outline: 1px solid red;
}
</style> </style>
<script> <script>
function onFormFocus() { this.className = 'focused'; } function onFormFocus() {
function onFormBlur() { this.className = ''; } this.className = 'focused';
}
function onFormBlur() {
this.className = '';
}
var form = document.forms.form; var form = document.forms.form;

View file

@ -127,7 +127,6 @@ if("onpropertychange" in checkbox) {
<!--+ autorun run height=60 --> <!--+ autorun run height=60 -->
<input type="text" id="sms"> символов: <span id="result"></span> <input type="text" id="sms"> символов: <span id="result"></span>
<script> <script>
function showCount() { function showCount() {
result.innerHTML = sms.value.length; result.innerHTML = sms.value.length;
} }

View file

@ -18,7 +18,7 @@
Например, в таком HTML оба способа выведут `alert`, форма не будет отправлена: Например, в таком HTML оба способа выведут `alert`, форма не будет отправлена:
```html ```html
<!--+ autorun height=80 --> <!--+ autorun height=80 no-beautify -->
<form onsubmit="alert('submit!');return false"> <form onsubmit="alert('submit!');return false">
Первый: Enter в текстовом поле <input type="text" value="Текст"><br> Первый: Enter в текстовом поле <input type="text" value="Текст"><br>
Второй: Нажать на "Отправить": <input type="submit" value="Отправить"> Второй: Нажать на "Отправить": <input type="submit" value="Отправить">

View file

@ -47,7 +47,9 @@
function Menu(options) { function Menu(options) {
var elem = options.elem; var elem = options.elem;
elem.onmousedown = function() { return false; } elem.onmousedown = function() {
return false;
}
elem.onclick = function(event) { elem.onclick = function(event) {
if (event.target.closest('.title')) { if (event.target.closest('.title')) {
@ -127,7 +129,9 @@ if (event.target.closest('.title')) {
function Menu(options) { function Menu(options) {
var elem = options.elem; var elem = options.elem;
elem.onmousedown = function() { return false; } elem.onmousedown = function() {
return false;
}
elem.onclick = function(event) { elem.onclick = function(event) {
if (event.target.closest('.title')) { if (event.target.closest('.title')) {

View file

@ -22,10 +22,8 @@
float: left; float: left;
padding: 6px; padding: 6px;
margin: 0 2px; margin: 0 2px;
border: 1px solid gray; border: 1px solid gray;
border-radius: 10px; border-radius: 10px;
cursor: pointer; cursor: pointer;
font-size: 90%; font-size: 90%;
background: #FFF5EE; background: #FFF5EE;

View file

@ -102,7 +102,7 @@ HTML-разметка и названия CSS-классов должны отр
Рассмотрим пример вёрстки "диалогового окна": Рассмотрим пример вёрстки "диалогового окна":
```html ```html
<!--+ autorun height=100 --> <!--+ autorun height=100 no-beautify -->
<div class="dialog"> <div class="dialog">
<h2 class="title">Заголовок</h2> <h2 class="title">Заголовок</h2>
<div class="content"> <div class="content">

View file

@ -5,6 +5,7 @@
Есть данные: Есть данные:
```js ```js
//+ no-beautify
var users = [ var users = [
{name: "Вася", age: 10}, {name: "Вася", age: 10},
{name: "Петя", age: 15}, {name: "Петя", age: 15},

View file

@ -13,6 +13,7 @@
Ранее мы уже видели код `Menu`, который сам создаёт свой элемент: Ранее мы уже видели код `Menu`, который сам создаёт свой элемент:
```js ```js
//+ no-beautify
function Menu(options) { function Menu(options) {
// ... приведены только методы для генерации DOM ... // ... приведены только методы для генерации DOM ...
@ -66,6 +67,7 @@ function Menu(options) {
Пример шаблона для меню: Пример шаблона для меню:
```html ```html
<!--+ no-beautify -->
<div class="menu"> <div class="menu">
<span class="title"><%-title%></span> <span class="title"><%-title%></span>
<ul> <ul>
@ -180,7 +182,7 @@ alert( tmpl(data) ); // <span class="title">Заголовок</span>
Например, вот шаблон для генерации списка от `1` до `count`: Например, вот шаблон для генерации списка от `1` до `count`:
```js ```js
//+ run //+ run no-beautify
// используется \, чтобы объявить многострочную переменную-текст шаблона // используется \, чтобы объявить многострочную переменную-текст шаблона
var tmpl = '<ul>\ var tmpl = '<ul>\
<% for (var i=1; i<=count; i++) { %> \ <% for (var i=1; i<=count; i++) { %> \
@ -263,6 +265,7 @@ alert( compiled );
Функция `compiled`, которую вернул вызов `_template` из этого примера, выглядит примерно так: Функция `compiled`, которую вернул вызов `_template` из этого примера, выглядит примерно так:
```js ```js
//+ no-beautify
function(obj) { function(obj) {
obj || (obj = {}); obj || (obj = {});
var __t, __p = '', __e = _.escape; var __t, __p = '', __e = _.escape;
@ -297,7 +300,7 @@ function(obj) {
Например: Например:
```js ```js
//+ run //+ run no-beautify
alert( _.template("<h1><%=menu.title%></h1>", {variable: "menu"}) ); alert( _.template("<h1><%=menu.title%></h1>", {variable: "menu"}) );
``` ```
@ -331,6 +334,7 @@ function(*!*menu*/!*) {
HTML (шаблоны): HTML (шаблоны):
```html ```html
<!--+ no-beautify -->
<script type="text/template" id="menu-template"> <script type="text/template" id="menu-template">
<div class="menu"> <div class="menu">
<span class="title"><%-title%></span> <span class="title"><%-title%></span>
@ -380,7 +384,9 @@ function Menu(options) {
} }
function render() { function render() {
var html = options.template({title: options.title}); var html = options.template({
title: options.title
});
elem = document.createElement('div'); elem = document.createElement('div');
elem.innerHTML = html; elem.innerHTML = html;
@ -400,7 +406,9 @@ function Menu(options) {
function renderItems() { function renderItems() {
if (elem.querySelector('ul')) return; if (elem.querySelector('ul')) return;
var listHtml = options.listTemplate({items: options.items}); var listHtml = options.listTemplate({
items: options.items
});
elem.insertAdjacentHTML("beforeEnd", listHtml); elem.insertAdjacentHTML("beforeEnd", listHtml);
} }
@ -432,6 +440,7 @@ function Menu(options) {
Здесь два шаблона. Первый мы уже разобрали, посмотрим теперь на список `ul/li`: Здесь два шаблона. Первый мы уже разобрали, посмотрим теперь на список `ul/li`:
```html ```html
<!--+ no-beautify -->
<ul> <ul>
<% items.forEach(function(item) { %> <% items.forEach(function(item) { %>
<li><%-item%></li> <li><%-item%></li>
@ -453,6 +462,7 @@ function Menu(options) {
Вот функция, которую возвратит `_.template(tmpl)` для этого шаблона: Вот функция, которую возвратит `_.template(tmpl)` для этого шаблона:
```js ```js
//+ no-beautify
function(obj) { function(obj) {
obj || (obj = {}); obj || (obj = {});
var __t, __p = '', __e = _.escape; var __t, __p = '', __e = _.escape;
@ -485,7 +495,7 @@ function(obj) {
Попробуйте сами запустить пример с открытыми инструментами разработчика и *включённой* опцией "остановка при ошибке": Попробуйте сами запустить пример с открытыми инструментами разработчика и *включённой* опцией "остановка при ошибке":
```html ```html
<!--+ run --> <!--+ run no-beautify -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.2.0/lodash.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.2.0/lodash.js"></script>
<script type="text/template" id="menu-template"> <script type="text/template" id="menu-template">
@ -523,6 +533,7 @@ function(obj) {
Это, конечно, лучше чем ничего, но, как правило, его имеет смысл заменить `sourceURL` на свой, указав при компиляции дополнительный параметр `sourceURL`: Это, конечно, лучше чем ничего, но, как правило, его имеет смысл заменить `sourceURL` на свой, указав при компиляции дополнительный параметр `sourceURL`:
```js ```js
//+ no-beautify
... ...
var compiled = _.template(tmpl, {sourceURL: '/template/menu-template'}); var compiled = _.template(tmpl, {sourceURL: '/template/menu-template'});
... ...

View file

@ -13,6 +13,7 @@
Например, мы можем добавить в `options` для `Menu` новый параметр -- функцию `onselect`, которая будет вызываться при выборе пункта меню: Например, мы можем добавить в `options` для `Menu` новый параметр -- функцию `onselect`, которая будет вызываться при выборе пункта меню:
```js ```js
//+ no-beautify
var menu = new Menu({ var menu = new Menu({
title: "Сладости", title: "Сладости",
template: _.template(document.getElementById('menu-template').innerHTML), template: _.template(document.getElementById('menu-template').innerHTML),
@ -37,6 +38,7 @@ function showSelected(href) {
В коде меню нужно будет вызывать её, например так: В коде меню нужно будет вызывать её, например так:
```js ```js
//+ no-beautify
... ...
function select(link) { function select(link) {
options.onselect(link.getAttribute('href').slice(1)); options.onselect(link.getAttribute('href').slice(1));
@ -58,6 +60,7 @@ function showSelected(href) {
Для этого модифицируем функцию `select`: Для этого модифицируем функцию `select`:
```js ```js
//+ no-beautify
function Menu(options) { function Menu(options) {
... ...

View file

@ -77,7 +77,7 @@
В примере ниже регистрация элемента происходит через 2 секунды после его появления в разметке: В примере ниже регистрация элемента происходит через 2 секунды после его появления в разметке:
```html ```html
<!--+ run --> <!--+ run no-beautify -->
<style> <style>
*!* *!*
/* стиль для :unresolved элемента (до регистрации) */ /* стиль для :unresolved элемента (до регистрации) */

View file

@ -21,7 +21,7 @@
В Shadow DOM выше можно увидеть полезный атрибут `pseudo`. Он нестандартный, существует по историческим причинам. С его помощью можно стилизовать подэлементы через CSS, например, сделаем поле редактирования даты красным: В Shadow DOM выше можно увидеть полезный атрибут `pseudo`. Он нестандартный, существует по историческим причинам. С его помощью можно стилизовать подэлементы через CSS, например, сделаем поле редактирования даты красным:
```html ```html
<!--+ run --> <!--+ run no-beautify -->
<style> <style>
*!* *!*
input::-webkit-datetime-edit { input::-webkit-datetime-edit {
@ -92,7 +92,7 @@ Shadow DOM примера выше в инструментах разработ
Например: Например:
```html ```html
<!--+ run autorun="no-epub" --> <!--+ run autorun="no-epub" no-beautify -->
<section id="elem"> <section id="elem">
<h1>Новости</h1> <h1>Новости</h1>

View file

@ -19,13 +19,15 @@
```html ```html
<!--+ run autorun="no-epub" --> <!--+ run autorun="no-epub" -->
<p id="elem">
<p id="elem">Доброе утро, страна!</p> Доброе утро, страна!</p>
<template id="tmpl"> <template id="tmpl">
<h3><content></content></h3> <h3><content></content></h3>
<p>Привет из подполья!</p> <p>Привет из подполья!</p>
<script> document.write('...document.write:Новость!'); </script> <script>
document.write('...document.write:Новость!');
</script>
</template> </template>
<script> <script>

View file

@ -17,7 +17,11 @@
<template id="tmpl"> <template id="tmpl">
*!* *!*
<style> p { color: red; } </style> <style>
p {
color: red;
}
</style>
*/!* */!*
<h3><content></content></h3> <h3><content></content></h3>
<p>Привет из подполья!</p> <p>Привет из подполья!</p>
@ -54,11 +58,13 @@
<style> <style>
#elem::shadow span { #elem::shadow span {
/* для span только внутри Shadow DOM #elem */ /* для span только внутри Shadow DOM #elem */
border-bottom: 1px dashed blue; border-bottom: 1px dashed blue;
} }
#elem >>> * { #elem >>> * {
/* для всех элементов внутри Shadow DOM #elem и далее внутри input[type=date] */ /* для всех элементов внутри Shadow DOM #elem и далее внутри input[type=date] */
color: red; color: red;
} }
</style> </style>
@ -132,7 +138,9 @@
```html ```html
<style> <style>
:host > p { color: green; } :host > p {
color: green;
}
</style> </style>
``` ```
Этот селектор сработает для `<p>` первого уровня внутри Shadow DOM. Этот селектор сработает для `<p>` первого уровня внутри Shadow DOM.
@ -142,8 +150,13 @@
Этот селектор используется для темизации хозяина "изнутри", в зависимости от его классов и атрибутов. Он отлично добавляет просто `:host`, например: Этот селектор используется для темизации хозяина "изнутри", в зависимости от его классов и атрибутов. Он отлично добавляет просто `:host`, например:
```css ```css
:host p { color: green; } :host p {
:host(.important) p { color: red; } color: green;
}
:host(.important) p {
color: red;
}
``` ```
Здесь параграфы будут иметь `color:green`, но если у хозяина класс `.important`, то `color:red`. Здесь параграфы будут иметь `color:green`, но если у хозяина класс `.important`, то `color:red`.
@ -163,7 +176,7 @@
Пример использования селектора `:host()` для разной расцветки Shadow DOM-сообщения, в зависимости от того, в каком оно `<p>`: Пример использования селектора `:host()` для разной расцветки Shadow DOM-сообщения, в зависимости от того, в каком оно `<p>`:
```html ```html
<!--+ run autorun="no-epub" --> <!--+ run autorun="no-epub" no-beautify -->
*!* *!*
<p class="message info">Доброе утро, страна!</p> <p class="message info">Доброе утро, страна!</p>
*/!* */!*
@ -215,7 +228,7 @@ elems[1].createShadowRoot().appendChild( tmpl.content.cloneNode(true) );
Например, здесь применится стиль для `<span>`: Например, здесь применится стиль для `<span>`:
```html ```html
<!--+ run autorun="no-epub" --> <!--+ run autorun="no-epub" no-beautify -->
<style> <style>
*!* *!*
span { text-decoration: underline; } span { text-decoration: underline; }
@ -247,7 +260,7 @@ elems[1].createShadowRoot().appendChild( tmpl.content.cloneNode(true) );
В примере ниже селектор `::content span` стилизует все `<span>` внутри всех `<content>`: В примере ниже селектор `::content span` стилизует все `<span>` внутри всех `<content>`:
```html ```html
<!--+ run --> <!--+ run no-beautify -->
<style> <style>
*!* *!*
span { text-decoration: underline; } span { text-decoration: underline; }

View file

@ -102,6 +102,7 @@
<li>Главный файл `index.html` подключает документы: <li>Главный файл `index.html` подключает документы:
```html ```html
<!--+ no-beautify -->
<link rel="import" href="ui-tabs.html"> <link rel="import" href="ui-tabs.html">
<link rel="import" href="ui-dialog.html"> <link rel="import" href="ui-dialog.html">
... ...
@ -111,6 +112,7 @@
<li>`ui-tabs.html` подключает `libs.html`: <li>`ui-tabs.html` подключает `libs.html`:
```html ```html
<!--+ no-beautify -->
<link rel="import" href="libs.html"> <link rel="import" href="libs.html">
...template и код для табов... ...template и код для табов...
``` ```
@ -120,6 +122,7 @@
<li>`ui-dialog.html` также использует `libs.html`: <li>`ui-dialog.html` также использует `libs.html`:
```html ```html
<!--+ no-beautify -->
<link rel="import" href="libs.html"> <link rel="import" href="libs.html">
...template и код для диалогов... ...template и код для диалогов...
``` ```

View file

@ -60,7 +60,9 @@
color: red; color: red;
} }
</style> </style>
<div class="content"><content></content></div> <div class="content">
<content></content>
</div>
</template> </template>
``` ```
@ -171,7 +173,6 @@ document.registerElement('ui-message', {
<template id="tmpl"> <template id="tmpl">
<style> <style>
@import url(http://code.jquery.com/ui/1.11.3/themes/ui-lightness/jquery-ui.css); @import url(http://code.jquery.com/ui/1.11.3/themes/ui-lightness/jquery-ui.css);
:host { :host {
display: block; display: block;
} }
@ -209,7 +210,9 @@ SliderProto.createdCallback = function() {
slide: function() { slide: function() {
// (3) пробросить событие // (3) пробросить событие
var event = new CustomEvent("slide", { var event = new CustomEvent("slide", {
detail: { value: self.$slider.slider("option", "value") }, detail: {
value: self.$slider.slider("option", "value")
},
bubbles: true bubbles: true
}); });
self.dispatchEvent(event); self.dispatchEvent(event);
@ -258,7 +261,10 @@ Object.defineProperty(SliderProto, 'value', {
Он был в методе [offset](http://api.jquery.com/offset/), который предназначен для того, чтобы определять координаты элемента. Этот метод не срабатывал, поскольку в нём есть проверка, которая выглядит примерно так: Он был в методе [offset](http://api.jquery.com/offset/), который предназначен для того, чтобы определять координаты элемента. Этот метод не срабатывал, поскольку в нём есть проверка, которая выглядит примерно так:
```js ```js
var box = { top: 0, left: 0 }; var box = {
top: 0,
left: 0
};
... ...
// Make sure it's not a disconnected DOM node // Make sure it's not a disconnected DOM node
if(!jQuery.contains(elem.ownerDocument, elem)) { if(!jQuery.contains(elem.ownerDocument, elem)) {

View file

@ -1,5 +1,3 @@
# Веб-компоненты: взгляд в будущее # Веб-компоненты: взгляд в будущее
Веб-компоненты -- "платформа будущего": совокупность стандартов, которые позволяют описывать "свои теги" -- новые типы DOM-элементов, со своими свойствами и методами, инкапсулировать их DOM и стили. Веб-компоненты -- "платформа будущего": совокупность стандартов, которые позволяют описывать новые типы DOM-элементов, со своими свойствами и методами, инкапсулировать их DOM и стили.
Современные браузеры поддерживают их частично.

View file

@ -24,7 +24,7 @@ addScript('user?id=123');
Такой вызов добавит в `HEAD` документа тег: Такой вызов добавит в `HEAD` документа тег:
```js ```html
<script src="/user?id=123"></script> <script src="/user?id=123"></script>
``` ```
@ -38,6 +38,7 @@ addScript('user?id=123');
```js ```js
//+ no-beautify
// ответ сервера // ответ сервера
var user = {name: "Вася", age: 25 }; var user = {name: "Вася", age: 25 };
``` ```

View file

@ -118,6 +118,7 @@ id: 3
У объекта `EventSource` есть свойство `readyState`, которое содержит одно из значений (выдержка из стандарта): У объекта `EventSource` есть свойство `readyState`, которое содержит одно из значений (выдержка из стандарта):
```js ```js
//+ no-beautify
const unsigned short CONNECTING = 0; // в процессе (пере-)соединения const unsigned short CONNECTING = 0; // в процессе (пере-)соединения
const unsigned short OPEN = 1; // соединение установлено const unsigned short OPEN = 1; // соединение установлено
const unsigned short CLOSED = 2; // соединение закрыто const unsigned short CLOSED = 2; // соединение закрыто
@ -203,7 +204,9 @@ eventSource.addEventListener('leave', function(e) {
`EventSource` поддерживает кросс-доменные запросы, аналогично `XMLHttpRequest`. Для этого у конструктора есть второй аргумент -- объект, который нужно передать так: `EventSource` поддерживает кросс-доменные запросы, аналогично `XMLHttpRequest`. Для этого у конструктора есть второй аргумент -- объект, который нужно передать так:
```js ```js
var source = new EventSource("http://pupkin.ru/stream", { withCredentials: true }); var source = new EventSource("http://pupkin.ru/stream", {
withCredentials: true
});
``` ```
Второй аргумент сделан объектом с расчётом на будущее. Пока что никаких других свойств там не поддерживается, только `withCredentials`. Второй аргумент сделан объектом с расчётом на будущее. Пока что никаких других свойств там не поддерживается, только `withCredentials`.

View file

@ -68,7 +68,6 @@ var iframeDoc = iframe.contentWindow.document;
<li>Когда ифрейм уже создан, то единственный способ поменять его `src` без попадания запроса в историю посещений: <li>Когда ифрейм уже создан, то единственный способ поменять его `src` без попадания запроса в историю посещений:
```js ```js
// newSrc - новый адрес // newSrc - новый адрес
iframeDoc.location.replace(newSrc); iframeDoc.location.replace(newSrc);
``` ```
@ -181,6 +180,7 @@ function postToIframe(url, data, target){
<li>Сервер отвечает как-то так: <li>Сервер отвечает как-то так:
```html ```html
<!--+ no-beautify -->
<script> <script>
parent.CallbackRegistry[window.name]({данные}); parent.CallbackRegistry[window.name]({данные});
</script> </script>
@ -257,6 +257,7 @@ function postToIframe(url, data, target){
Поэтому в таком `IFRAME` первые несколько сообщений задержатся: Поэтому в таком `IFRAME` первые несколько сообщений задержатся:
```html ```html
<!--+ no-beautify -->
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<body> <body>
@ -270,10 +271,15 @@ function postToIframe(url, data, target){
```html ```html
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<body> <body>
******* 1 килобайт пробелов, а потом уже сообщения ****** ******* 1 килобайт пробелов, а потом уже сообщения ******
<script>parent.onMessage("привет");</script> <script>
<script>parent.onMessage("от сервера");</script> parent.onMessage("привет");
</script>
<script>
parent.onMessage("от сервера");
</script>
... ...
``` ```

View file

@ -18,6 +18,7 @@
<li>На злой странице находится форма такого вида: <li>На злой странице находится форма такого вида:
```html ```html
<!--+ no-beautify -->
<form action="http://mail.com/send" method="POST"> <form action="http://mail.com/send" method="POST">
<input type="hidden" name="message" value="Сообщение"> <input type="hidden" name="message" value="Сообщение">
... ...

View file

@ -216,6 +216,7 @@ xhr.send(body);
Для добавления файла нужно использовать тот же код, что выше, модифицировав заголовки перед полем, которое является файлом, так: Для добавления файла нужно использовать тот же код, что выше, модифицировав заголовки перед полем, которое является файлом, так:
```js ```js
//+ no-beautify
Content-Disposition: form-data; name="myfile"; filename="pic.jpg" Content-Disposition: form-data; name="myfile"; filename="pic.jpg"
Content-Type: image/jpeg Content-Type: image/jpeg
(пустая строка) (пустая строка)

View file

@ -236,6 +236,7 @@ xhr.open('POST', 'http://anywhere.com/request', true)
Пример заголовков: Пример заголовков:
```js ```js
//+ no-beautify
HTTP/1.1 200 OK HTTP/1.1 200 OK
Content-Type:text/html; charset=UTF-8 Content-Type:text/html; charset=UTF-8
*!* *!*

View file

@ -452,7 +452,9 @@ var WebSocketServer = new require('ws');
var clients = {}; var clients = {};
// WebSocket-сервер на порту 8081 // WebSocket-сервер на порту 8081
var webSocketServer = new WebSocketServer.Server({port: 8081}); var webSocketServer = new WebSocketServer.Server({
port: 8081
});
webSocketServer.on('connection', function(ws) { webSocketServer.on('connection', function(ws) {
var id = Math.random(); var id = Math.random();
@ -475,7 +477,7 @@ webSocketServer.on('connection', function(ws) {
}); });
``` ```
Рабочий пример можно скачать: [websocket.zip](/zip/tutorial/ajax/websocket.zip). Понадобится поставить два модуля: `npm install node-static && npm install ws`. Рабочий пример можно скачать: [websocket.zip](websocket.zip). Понадобится поставить два модуля: `npm install node-static && npm install ws`.
## Итого ## Итого
WebSocket -- современное средство коммуникации. Кросс-доменное, универсальное, безопасное. WebSocket -- современное средство коммуникации. Кросс-доменное, универсальное, безопасное.
@ -489,6 +491,3 @@ WebSocket -- современное средство коммуникации.
Например, для Node.JS одной из самых известных библиотек является [Socket.IO](http://socket.io). Например, для Node.JS одной из самых известных библиотек является [Socket.IO](http://socket.io).
К недостаткам библиотек следует отнести то, что некоторые продвинутые возможности WebSocket, такие как двухсторонний обмен бинарными данными, в них недоступны. С другой -- в большинстве случаев стандартного текстового обмена вполне достаточно. К недостаткам библиотек следует отнести то, что некоторые продвинутые возможности WebSocket, такие как двухсторонний обмен бинарными данными, в них недоступны. С другой -- в большинстве случаев стандартного текстового обмена вполне достаточно.
[head]
<script src="/files/tutorial/ajax/script/scriptRequest.js"></script>
[/head]

Binary file not shown.

View file

@ -1,5 +1,3 @@
# AJAX и COMET # AJAX и COMET
Современный `XMLHttpRequest`, включая поддержку докачки, индикации прогресса, кросс-доменных запросов. Современные средства для обмена данными с сервером и смежные аспекты.
WebSocket. Альтернативные методы общения с сервером при помощи JSONP и IFRAME'ов.

View file

@ -119,11 +119,15 @@
<li>Эти точки соединяются. На рисунке ниже соединяющий их отрезок изображён <span style="color:blue">синим</span>. <li>Эти точки соединяются. На рисунке ниже соединяющий их отрезок изображён <span style="color:blue">синим</span>.
<table> <table>
<thead>
<tr><td>При `t=0.25`</td><td>При `t=0.5`</td></tr> <tr><td>При `t=0.25`</td><td>При `t=0.5`</td></tr>
</thead>
<tbody>
<tr> <tr>
<td><img src="bezier3-draw1.svg"></td> <td><img src="bezier3-draw1.svg"></td>
<td><img src="bezier3-draw2.svg"></td> <td><img src="bezier3-draw2.svg"></td>
</tr> </tr>
</tbody>
</table> </table>
</li> </li>

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Before After
Before After

View file

@ -2,10 +2,10 @@
CSS-код для анимации одновременно `width` и `height`: CSS-код для анимации одновременно `width` и `height`:
```css ```css
/* исходный класс */ /* исходный класс */
#flyjet { #flyjet {
transition: all 3s; transition: all 3s;
} }
/* JS добавляет .growing *. /* JS добавляет .growing *.
#flyjet.growing { #flyjet.growing {
width: 400px; width: 400px;

View file

@ -53,7 +53,7 @@ color.onclick = function() {
Например, при клике на эту кнопку анимируются одновременно цвет и размер шрифта: Например, при клике на эту кнопку анимируются одновременно цвет и размер шрифта:
```html ```html
<!--+ run height=80 autorun --> <!--+ run height=80 autorun no-beautify -->
<button id="growing">Кликни меня</button> <button id="growing">Кликни меня</button>
<style> <style>
@ -380,20 +380,29 @@ boat.onclick = function() {
```html ```html
<!--+ run height=60 --> <!--+ run height=60 -->
<div class="progress">
<div class="progress"></div> </div>
<style> <style>
/* Chrome, Opera, Safari */ /* Chrome, Opera, Safari */
@-webkit-keyframes MY-ANIMATION-NAME {
from { left:0px; }
to { left:300px; }
}
@-webkit-keyframes MY-ANIMATION-NAME {
from {
left: 0px;
}
to {
left: 300px;
}
}
/* Other browsers, except IE9- */ /* Other browsers, except IE9- */
@keyframes MY-ANIMATION-NAME { @keyframes MY-ANIMATION-NAME {
from { left:0px; } from {
to { left:300px; } left: 0px;
}
to {
left: 300px;
}
} }
.progress { .progress {

View file

@ -12,6 +12,7 @@
Например: Например:
```js ```js
//+ no-beautify
// присвоить // присвоить
$(document).data('prop', { anything: "любой объект" }) $(document).data('prop', { anything: "любой объект" })
@ -34,6 +35,7 @@ elem[ jQuery.expando ] = id = ++jQuery.uuid; // средствами jQuery
<li>...А сами данные сохраняются в специальном объекте `jQuery.cache`: <li>...А сами данные сохраняются в специальном объекте `jQuery.cache`:
```js ```js
//+ no-beautify
jQuery.cache[id]['prop'] = { anything: "любой объект" }; jQuery.cache[id]['prop'] = { anything: "любой объект" };
``` ```
@ -55,20 +57,37 @@ jQuery.cache[id]['prop'] = { anything: "любой объект" };
## Примеры утечек в jQuery ## Примеры утечек в jQuery
Следующий код создает jQuery-утечку во всех браузерах: Следующая функция `leak` создает jQuery-утечку во всех браузерах:
```js
```html
<!--+ run -->
<script src="http://code.jquery.com/jquery.min.js"></script>
<div id="data"></div>
<script>
function leak() {
*!*
$('<div/>') $('<div/>')
.html(new Array(1000).join('text')) // div с текстом, возможна AJAX-загрузка .html(new Array(1000).join('text'))
.click(function() {}) .click(function() {})
.appendTo('#data') .appendTo('#data');
document.getElementById('data').innerHTML = ''; // (*) document.getElementById('data').innerHTML = '';
*/!*
}
var interval = setInterval(leak, 10)
</script>
Утечка идёт...
<input type="button" onclick="clearInterval(interval)" value="stop" />
``` ```
Полный пример:
[codetabs src="jquery-leak"]
Утечка происходит потому, что обработчик события в jQuery хранится в данных элемента. В строке `(*)` элемент удален очисткой родительского `innerHTML`, но в `jQuery.cache` данные остались. Утечка происходит потому, что обработчик события в jQuery хранится в данных элемента. В строке `(*)` элемент удален очисткой родительского `innerHTML`, но в `jQuery.cache` данные остались.
@ -79,7 +98,7 @@ document.getElementById('data').innerHTML = ''; // (*)
Этот код также создает утечку: Этот код также создает утечку:
```js ```js
function go() { function leak() {
$('<div/>') $('<div/>')
.click(function() {}) .click(function() {})
} }

View file

@ -1,34 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script src="http://code.jquery.com/jquery.min.js"></script>
</head>
<body>
<div id="data"></div>
<script>
function go() {
$('<div/>')
.html(new Array(1000).join('text'))
.click(function() {})
.appendTo('#data');
document.getElementById('data').innerHTML = '';
}
var interval = setInterval(go, 10)
</script>
Утечка идёт...
<input type="button" onclick="clearInterval(interval)" value="stop" />
</body>
</html>

View file

@ -146,6 +146,7 @@ function test(a, b) {
После: После:
```js ```js
//+ no-beautify
function test(a,b){run(a,"mystring",18E5,0,b&&0)}; function test(a,b){run(a,"mystring",18E5,0,b&&0)};
``` ```
@ -169,6 +170,7 @@ function sayHi(*!*name*/!*, *!*message*/!*) {
После оптимизации: После оптимизации:
```js ```js
//+ no-beautify
function sayHi(a,b){alert(a+" сказал: "+b)}; function sayHi(a,b){alert(a+" сказал: "+b)};
``` ```
@ -193,6 +195,7 @@ function test(nodeId) {
После оптимизации GCC: После оптимизации GCC:
```js ```js
//+ no-beautify
function test(a){a=document.getElementsById(a).parentNode;alert(a)}; function test(a){a=document.getElementsById(a).parentNode;alert(a)};
``` ```
@ -226,6 +229,7 @@ function test(node) {
После оптимизации: После оптимизации:
```js ```js
//+ no-beautify
function test(){alert("Останется только один")} function test(){alert("Останется только один")}
``` ```
@ -263,6 +267,7 @@ if (i=='1') {
После оптимизации: После оптимизации:
```js ```js
//+ no-beautify
for(var i=0;10>i++;)alert(i);i&&alert(i);"1"==i?alert(1):"2"==i?alert(2):alert(i); for(var i=0;10>i++;)alert(i);i&&alert(i);"1"==i?alert(1):"2"==i?alert(2):alert(i);
``` ```
@ -359,7 +364,8 @@ function sayHi(b){
alert( "Привет вам из JavaScript" ); alert( "Привет вам из JavaScript" );
alert( "Привет вам из JavaScript" ); alert( "Привет вам из JavaScript" );
}; };
}})(); }
})();
``` ```
<ul> <ul>
@ -385,6 +391,7 @@ function sayHi(b){
<li>Убираются лишние кавычки у ключей <li>Убираются лишние кавычки у ключей
```js ```js
//+ no-beautify
{"prop" : "val" } => {prop:"val"} {"prop" : "val" } => {prop:"val"}
``` ```
@ -392,6 +399,7 @@ function sayHi(b){
<li>Упрощаются простые вызовы `Array/Object` <li>Упрощаются простые вызовы `Array/Object`
```js ```js
//+ no-beautify
a = new Array() => a = [] a = new Array() => a = []
o = new Object() => o = {} o = new Object() => o = {}
``` ```
@ -414,6 +422,7 @@ o = new Object() => o = {}
Рассмотрим код: Рассмотрим код:
```js ```js
//+ no-beautify
function changePosition(style) { function changePosition(style) {
var position, test; var position, test;
@ -432,6 +441,7 @@ function changePosition(style) {
Можно ли в такой ситуации заменить локальную переменную на более короткую? Очевидно, нет: Можно ли в такой ситуации заменить локальную переменную на более короткую? Очевидно, нет:
```js ```js
//+ no-beautify
function changePosition(style) { function changePosition(style) {
var a, b; var a, b;
@ -446,6 +456,7 @@ function changePosition(style) {
Такая же опасность для сжатия кроется в использованном `eval`. Ведь `eval` может обращаться к локальным переменным: Такая же опасность для сжатия кроется в использованном `eval`. Ведь `eval` может обращаться к локальным переменным:
```js ```js
//+ no-beautify
function f(code) { function f(code) {
var myVar; var myVar;
@ -483,18 +494,10 @@ function f(code) {
//+ run //+ run
var isIE /*@cc_on =true@*/ ; var isIE /*@cc_on =true@*/ ;
alert(isIE); // true в IE. alert( isIE ); // true в IE10-
``` ```
Там же доступны и дополнительные директивы: `@_jscript_version`, `@if` и т.п., но речь здесь не о том. Можно хитро сделать, чтобы комментарий остался, например так:
Для минификаторов этот "условный" комментарий -- всего лишь обычный комментарий. Они его удалят. Получится, что код не поймёт, где же IE.
Что делать?
<ol>
<li>Первое и наиболее корректное решение -- не использовать условную компиляцию.</li>
<li>Второе, если уж очень надо -- применить хак, завернуть его в `eval` или `new Function` (чтобы сжиматель не ругался):
```js ```js
//+ run //+ run
@ -503,10 +506,8 @@ var isIE = new Function('', '/*@cc_on return true@*/')();
alert( isIE ); // true в IE. alert( isIE ); // true в IE.
``` ```
</li>
</ol>
Ещё раз заметим, что в современных IE11+ эта компиляция не работает в любом случае. ...Однако, с учётом того, что в современных IE11+ эта компиляция не работает в любом случае, лучше избавиться от неё вообще.
В следующих главах мы посмотрим, какие продвинутые возможности есть в минификаторах, как сделать сжатие более эффективным. В следующих главах мы посмотрим, какие продвинутые возможности есть в минификаторах, как сделать сжатие более эффективным.

View file

@ -121,13 +121,17 @@ first:2 --module second:1:first
Например: Например:
```js ```js
document.onkeyup = function(event) { alert(event.type) } document.onkeyup = function(event) {
alert(event.type)
}
``` ```
После продвинутого сжатия: После продвинутого сжатия:
```js ```js
document.onkeyup = function(a) { alert(a.type) } document.onkeyup = function(a) {
alert(a.type)
}
``` ```
Как видите, переименованной оказалась только переменная `event`. Такое переименование заведомо безопасно, т.к. `event` -- локальная переменная. Как видите, переименованной оказалась только переменная `event`. Такое переименование заведомо безопасно, т.к. `event` -- локальная переменная.
@ -135,13 +139,17 @@ document.onkeyup = function(a) { alert(a.type) }
Почему компилятор не тронул остального? Попробуем другой вариант: Почему компилятор не тронул остального? Попробуем другой вариант:
```js ```js
document.blabla = function(event) { alert(event.megaProperty) } document.blabla = function(event) {
alert(event.megaProperty)
}
``` ```
После компиляции: После компиляции:
```js ```js
document.a = function(a) { alert(a.b) } document.a = function(a) {
alert(a.b)
}
``` ```
Теперь компилятор переименовал и <code>blabla</code> и <code>megaProperty</code>. Теперь компилятор переименовал и <code>blabla</code> и <code>megaProperty</code>.
@ -268,6 +276,7 @@ SayWidget.prototype['setSayHandler'] = SayWidget.prototype.setSayHandler;
После сжатия: После сжатия:
```js ```js
//+ no-beautify
function a(b) { function a(b) {
this.a = b; this.a = b;
this.b() this.b()
@ -428,6 +437,7 @@ MyFramework.publicOne();
Результат компиляции в обычном режиме: Результат компиляции в обычном режиме:
```js ```js
//+ no-beautify
// java -jar compiler.jar --js myframework.js --formatting PRETTY_PRINT // java -jar compiler.jar --js myframework.js --formatting PRETTY_PRINT
(function(a) { (function(a) {
a = a.MyFramework = {}; a = a.MyFramework = {};

View file

@ -128,7 +128,7 @@ function removeNode(node) {
Восклицательный знак означает, что параметр обязатален. Восклицательный знак означает, что параметр обязатален.
Найти описания встроенных типов и объектов javascript вы можете в файле экстернов: <code>externs.zip</code> находится в корне архива <code>compiler.jar</code>, или в соответствующей директории SVN: <a href="http://closure-compiler.googlecode.com/svn/trunk/externs/">http://closure-compiler.googlecode.com/svn/trunk/externs/</a>. Найти описания встроенных типов и объектов javascript вы можете в файле экстернов: <code>externs.zip</code> находится в корне архива <code>compiler.jar</code>.
## Интеграция с проверками типов из Google Closure Library ## Интеграция с проверками типов из Google Closure Library
@ -138,7 +138,9 @@ Google Closure Compiler знает о них и понимает, что вну
```js ```js
var goog = { var goog = {
isFunction: function(f) { return typeof f == 'function' } isFunction: function(f) {
return typeof f == 'function'
}
} }
if (goog.isFunction(func)) { if (goog.isFunction(func)) {
@ -168,7 +170,7 @@ required: (Object|null|undefined)
Также можно указывать количество и тип параметров функции, ключевого слова <code>this</code>, объявлять классы, приватные методы и интерфейсы. Также можно указывать количество и тип параметров функции, ключевого слова <code>this</code>, объявлять классы, приватные методы и интерфейсы.
Проверка типов javascript, предоставляемая Google Closure Compiler - пожалуй, самая продвинутая из существующих на сегодняшний день. Проверка типов javascript, предоставляемая Google Closure Compiler -- пожалуй, самая продвинутая из существующих на сегодняшний день.
C ней аннотации, документирующие типы и параметры, становятся не просто украшением, а реальным средством проверки, уменьшающим количество ошибок на production. C ней аннотации, документирующие типы и параметры, становятся не просто украшением, а реальным средством проверки, уменьшающим количество ошибок на production.

View file

@ -102,7 +102,6 @@ Google Closure Library умеет преобразовывать классы CS
Например, следующая функция задает такой список. Например, следующая функция задает такой список.
```js ```js
goog.setCssNameMapping({ goog.setCssNameMapping({
"goog-menu": "a", "goog-menu": "a",
"goog-menu-disabled": "a-b", "goog-menu-disabled": "a-b",
@ -151,8 +150,7 @@ Google Closure Compiler производит соответствующие пр
```js ```js
/** @export */ /** @export */
function Widget() { function Widget() {}
}
/** @export */ /** @export */
Widget.prototype.hide = function() { Widget.prototype.hide = function() {
this.elem.style.display = 'none' this.elem.style.display = 'none'
@ -162,8 +160,7 @@ Widget.prototype.hide = function() {
После компиляции в продвинутом режиме: После компиляции в продвинутом режиме:
```js ```js
function a() { function a() {}
}
goog.d("Widget", a); goog.d("Widget", a);
a.prototype.a = function() { a.prototype.a = function() {
this.b.style.display = "none" this.b.style.display = "none"

View file

@ -9,6 +9,7 @@
```html ```html
<html> <html>
<body> <body>
<div> <div>
<ul> <ul>
@ -17,6 +18,7 @@
Сосед Сосед
</div> </div>
</body> </body>
</html> </html>
``` ```

View file

@ -48,7 +48,6 @@
alert( "Ошибка: " + e.message ); alert( "Ошибка: " + e.message );
} }
} }
</script> </script>
``` ```
@ -82,7 +81,6 @@
iframe.onload = null; iframe.onload = null;
} }
</script> </script>
``` ```

View file

@ -26,6 +26,7 @@
Например: Например:
```html ```html
<!--+ no-beautify -->
<iframe src="http://target.com" name="target"> <iframe src="http://target.com" name="target">
<script> <script>

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