minor renovations, beautify round 2 (final)
This commit is contained in:
parent
fad6615c42
commit
8410ce6421
212 changed files with 1981 additions and 1717 deletions
|
@ -95,7 +95,7 @@ var border_left_width;
|
||||||
|
|
||||||
Есть причина и поважнее. Поскольку именно это имя переменной пришло в голову -- скорее всего, оно больше соответствует хранимым там данным, чем то, которое было мы придумали изначально. Исключения бывают, но в любом случае -- такое несовпадение -- это повод задуматься.
|
Есть причина и поважнее. Поскольку именно это имя переменной пришло в голову -- скорее всего, оно больше соответствует хранимым там данным, чем то, которое было мы придумали изначально. Исключения бывают, но в любом случае -- такое несовпадение -- это повод задуматься.
|
||||||
|
|
||||||
Чтобы удобно переименовывать переменную, нужно использовать [хороший редактор JavaScript](/editors), тогда этот процесс будет очень простым и быстрым.
|
Чтобы удобно переименовывать переменную, нужно использовать [хороший редактор JavaScript](/editor), тогда этот процесс будет очень простым и быстрым.
|
||||||
|
|
||||||
[smart header="Если коротко..."]
|
[smart header="Если коротко..."]
|
||||||
Смысл имени переменной -- это "имя на коробке", по которому мы сможем максимально быстро находить нужные нам данные.
|
Смысл имени переменной -- это "имя на коробке", по которому мы сможем максимально быстро находить нужные нам данные.
|
||||||
|
|
BIN
1-js/4-data-structures/7-array/9-eratosthenes-sieve/sieve.gif
Normal file
BIN
1-js/4-data-structures/7-array/9-eratosthenes-sieve/sieve.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 44 KiB |
|
@ -15,7 +15,7 @@
|
||||||
<li>Все оставшиеся незачеркнутыми числа -- простые.</li>
|
<li>Все оставшиеся незачеркнутыми числа -- простые.</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
Посмотрите также <a href="/files/tutorial/intro/array/sieve.gif">анимацию алгоритма</a>.
|
Посмотрите также [анимацию алгоритма](sieve.gif).
|
||||||
|
|
||||||
Реализуйте "Решето Эратосфена" в JavaScript, используя массив.
|
Реализуйте "Решето Эратосфена" в JavaScript, используя массив.
|
||||||
|
|
||||||
|
|
|
@ -22,4 +22,4 @@ coffeeMachine.setOnReady(function() {
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
Исходный код возьмите из решения [предыдущей задачи](/task/setter-onReady).
|
Исходный код возьмите из решения [предыдущей задачи](/task/setter-onready).
|
|
@ -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"><(.*?)></code>. Тогда содержимое скобок можно будет получить отдельно.
|
Для удобства заключим его в скобки: <code class="pattern"><(.*?)></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).
|
||||||
|
|
||||||
**Скобки могут быть и вложенными. В этом случае нумерация также идёт слева направо.**
|
**Скобки могут быть и вложенными. В этом случае нумерация также идёт слева направо.**
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
# Регулярные выражения [в работе]
|
# Регулярные выражения [в работе]
|
||||||
|
|
||||||
Регулярные выражения -- мощный способ поиска и замены для строк.
|
Регулярные выражения -- мощный способ поиска и замены для строк.
|
||||||
|
|
||||||
В JavaScript они поддерживаются в простом варианте, менее мощном, чем в большинстве других языков. Но зато нам будет проще их изучить.
|
|
||||||
|
|
|
@ -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).
|
|
@ -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
|
||||||
|
|
|
@ -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> используется как точка отсчета для следующего поиска:
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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-связный список
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
|
|
||||||
// вставить elem за последним элементом
|
// вставить elem за последним элементом
|
||||||
insertAfter(elem, body.lastChild); // <--- должно работать
|
insertAfter(elem, body.lastChild); // <--- должно работать
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
```
|
```
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -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
|
||||||
|
};
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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) { ... }
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
"Пустой" -- значит нет дочерних узлов, даже текстовых.
|
"Пустой" -- значит нет дочерних узлов, даже текстовых.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
//+ no-beautify
|
||||||
if (/*...ваш код проверки elem... */) { узел elem пуст }
|
if (/*...ваш код проверки elem... */) { узел elem пуст }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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');
|
||||||
|
|
||||||
|
|
|
@ -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');
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -172,7 +172,8 @@ XML-режим включается, когда браузер получает
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<!--+ run -->
|
<!--+ run -->
|
||||||
<body><!-- комментарий -->
|
<body>
|
||||||
|
<!-- комментарий -->
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// для комментария
|
// для комментария
|
||||||
|
|
|
@ -14,8 +14,7 @@
|
||||||
set: function(value) {
|
set: function(value) {
|
||||||
this.innerText = value;
|
this.innerText = value;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -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>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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 }
|
||||||
|
|
|
@ -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"); });
|
||||||
|
|
|
@ -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 остался минимум работы -- только добавить/удалить класс при клике.
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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>
|
||||||
```
|
```
|
||||||
|
|
|
@ -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 ';
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)">
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
...
|
...
|
||||||
|
|
|
@ -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>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
```
|
```
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
|
@ -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">
|
||||||
Уважаемый копирователь,
|
Уважаемый копирователь,
|
||||||
почему-то автор хочет заставить вас покопаться в исходном коде этой страницы.
|
почему-то автор хочет заставить вас покопаться в исходном коде этой страницы.
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
||||||
// скрыть/удалить переносимый объект
|
// скрыть/удалить переносимый объект
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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; /* убирает рамку при фокусе */
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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="Отправить">
|
||||||
|
|
|
@ -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')) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
Есть данные:
|
Есть данные:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
//+ no-beautify
|
||||||
var users = [
|
var users = [
|
||||||
{name: "Вася", age: 10},
|
{name: "Вася", age: 10},
|
||||||
{name: "Петя", age: 15},
|
{name: "Петя", age: 15},
|
||||||
|
|
|
@ -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'});
|
||||||
...
|
...
|
||||||
|
|
|
@ -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) {
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@
|
||||||
В примере ниже регистрация элемента происходит через 2 секунды после его появления в разметке:
|
В примере ниже регистрация элемента происходит через 2 секунды после его появления в разметке:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<!--+ run -->
|
<!--+ run no-beautify -->
|
||||||
<style>
|
<style>
|
||||||
*!*
|
*!*
|
||||||
/* стиль для :unresolved элемента (до регистрации) */
|
/* стиль для :unresolved элемента (до регистрации) */
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
|
@ -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 и код для диалогов...
|
||||||
```
|
```
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
# Веб-компоненты: взгляд в будущее
|
# Веб-компоненты: взгляд в будущее
|
||||||
|
|
||||||
Веб-компоненты -- "платформа будущего": совокупность стандартов, которые позволяют описывать "свои теги" -- новые типы DOM-элементов, со своими свойствами и методами, инкапсулировать их DOM и стили.
|
Веб-компоненты -- "платформа будущего": совокупность стандартов, которые позволяют описывать новые типы DOM-элементов, со своими свойствами и методами, инкапсулировать их DOM и стили.
|
||||||
|
|
||||||
Современные браузеры поддерживают их частично.
|
|
|
@ -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 };
|
||||||
```
|
```
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -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>
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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="Сообщение">
|
||||||
...
|
...
|
||||||
|
|
|
@ -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
|
||||||
(пустая строка)
|
(пустая строка)
|
||||||
|
|
|
@ -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
|
||||||
*!*
|
*!*
|
||||||
|
|
|
@ -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]
|
|
BIN
4-ajax/9-websockets/websocket.zip
Normal file
BIN
4-ajax/9-websockets/websocket.zip
Normal file
Binary file not shown.
|
@ -1,5 +1,3 @@
|
||||||
# AJAX и COMET
|
# AJAX и COMET
|
||||||
|
|
||||||
Современный `XMLHttpRequest`, включая поддержку докачки, индикации прогресса, кросс-доменных запросов.
|
Современные средства для обмена данными с сервером и смежные аспекты.
|
||||||
|
|
||||||
WebSocket. Альтернативные методы общения с сервером при помощи JSONP и IFRAME'ов.
|
|
||||||
|
|
|
@ -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 |
|
@ -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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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() {})
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
|
|
@ -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+ эта компиляция не работает в любом случае, лучше избавиться от неё вообще.
|
||||||
|
|
||||||
В следующих главах мы посмотрим, какие продвинутые возможности есть в минификаторах, как сделать сжатие более эффективным.
|
В следующих главах мы посмотрим, какие продвинутые возможности есть в минификаторах, как сделать сжатие более эффективным.
|
||||||
|
|
||||||
|
|
|
@ -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 = {};
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div>
|
<div>
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -17,6 +18,7 @@
|
||||||
Сосед
|
Сосед
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,6 @@
|
||||||
alert( "Ошибка: " + e.message );
|
alert( "Ошибка: " + e.message );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -82,7 +81,6 @@
|
||||||
|
|
||||||
iframe.onload = null;
|
iframe.onload = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue