minor renovations, beautify round 2 (final)

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

View file

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View file

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

View file

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

View file

@ -4,7 +4,7 @@
У такого выделения есть два эффекта:
<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>
</ol>
@ -25,7 +25,7 @@ alert( 'Gogogo now!'.match( /(go)+/i ); // "Gogogo"
Для удобства заключим его в скобки: <code class="pattern">&lt;(.*?)&gt;</code>. Тогда содержимое скобок можно будет получить отдельно.
Используем метод [:String#match]. В результирующем массиве будет сначала всё совпадение, а далее -- скобочные группы, в данном случае -- только одна:
Используем метод [String#match](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/match). В результирующем массиве будет сначала всё совпадение, а далее -- скобочные группы, в данном случае -- только одна:
```js
//+ run
@ -35,7 +35,7 @@ var reg = /<(.*?)>/
alert(str.match(reg)) // массив: <h1>, h1
```
Для поиска всех совпадений, как мы обсуждали ранее, используется метод [:RegExp#exec].
Для поиска всех совпадений, как мы обсуждали ранее, используется метод [RegExp#exec](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec).
**Скобки могут быть и вложенными. В этом случае нумерация также идёт слева направо.**

View file

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

View file

@ -13,11 +13,11 @@
alert( document.cookie );
```
Эта строка состоит из пар `ключ=значение`, которые перечисляются через точку с запятой с пробелом `; `.
Эта строка состоит из пар `ключ=значение`, которые перечисляются через точку с запятой с пробелом `"; "`.
Значит, чтобы прочитать cookie, достаточно разбить строку по `; `, и затем найти нужный ключ. Это можно делать либо через `split` и работу с массивом, либо через регулярное выражение.
Значит, чтобы прочитать cookie, достаточно разбить строку по `"; "`, и затем найти нужный ключ. Это можно делать либо через `split` и работу с массивом, либо через регулярное выражение.
### Функция getCookie(name)
## Функция getCookie(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. Интерпретируется по-разному, в зависимости от типа:
<ul>
<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 отсутствует или `0`, то cookie будет установлено как сессионное и исчезнет при закрытии браузера.</li>
</ul>
@ -149,13 +149,15 @@ function setCookie(name, value, options) {
</dd>
</dl>
### Функция deleteCookie(name)
## Функция deleteCookie(name)
Здесь всё просто -- удаляем вызовом `setCookie` с датой в прошлом.
```js
function deleteCookie(name) {
setCookie(name, "", { expires: -1 })
setCookie(name, "", {
expires: -1
})
}
```
@ -248,6 +250,6 @@ if (!navigator.cookieEnabled) {
...Конечно, предполагается, что включён JavaScript. Впрочем, посетитель без JS и cookie с большой вероятностью не человек, а бот.</li>
</ul>
## Cookie.js
## Итого
Файл с функциями для работы с cookie: [cookie.js](/files/tutorial/browser/cookie/cookie.js).
Файл с функциями для работы с cookie: [cookie.js](cookie.js).

View file

@ -131,7 +131,9 @@ alert( collator.compare("ёжик", "яблоко") ); // -1 (ёжик мень
var collator = new Intl.Collator();
alert( collator.compare("ЁжиК", "ёжик") ); // 1, разные
var collator = new Intl.Collator(undefined, { sensitivity: "accent" } );
var collator = new Intl.Collator(undefined, {
sensitivity: "accent"
});
alert( collator.compare("ЁжиК", "ёжик") ); // 0, одинаковые
```
@ -454,7 +456,7 @@ alert( str.localeCompare("яблоко", "ru") ); // -1
<dd>Форматирует дату в соответствии с локалью, например:
```js
//+ run
//+ run no-beautify
var date = new Date(2014, 11, 31, 12, 00);
alert( date.toLocaleString("ru", { year: 'numeric', month: 'long' }) ); // Декабрь 2014

View file

@ -2,7 +2,7 @@
Регулярные выражения в javascript немного странные. Вроде - перловые, обычные, но с подводными камнями, на которые натыкаются даже опытные javascript-разработчики.
Эта статья ставит целью перечислить неожиданные фишки и особенности [:RegExp] в краткой и понятной форме.
Эта статья ставит целью перечислить неожиданные фишки и особенности `RegExp` в краткой и понятной форме.
[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>):
@ -152,7 +152,7 @@ alert("2 ++ 1".replace(/\+/g, "*"))
Следующий пример произведет операции вычитания:
```js
//+ run
//+ run no-beautify
var str = "count 36 - 26, 18 - 9"
str = str.replace(/(\d+) - (\d+)/g, function(a,b,c) { return b-c })
alert(str)
@ -161,7 +161,7 @@ alert(str)
### Найти всё
В javascript нет одного универсального метода для поиска всех совпадений.
Для поиска без запоминания скобочных групп - можно использовать [:String#match|]:
Для поиска без запоминания скобочных групп - можно использовать [String#match](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/match):
```js
//+ 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> используется как точка отсчета для следующего поиска:

View file

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

View file

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

View file

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

View file

@ -281,6 +281,7 @@ function ieTextRangeHighlight(text) {
Эту задачу мы уже решали в самом начале статьи <a href="#demo-mix">в примере с миксом</a>. Теперь рассмотрим код:
```js
//+ no-beautify
function getSelectionText() {
var txt = '';
if (txt = window.getSelection) // Не IE, используем метод getSelection

View file

@ -148,8 +148,7 @@ if( body.compareDocumentPosition(li) & 16 ) {
(this != other && other.contains(this) && 8) +
(this.sourceIndex >= 0 && other.sourceIndex >= 0 ?
(this.sourceIndex < other.sourceIndex && 4) +
(this.sourceIndex > other.sourceIndex && 2)
: 1
(this.sourceIndex > other.sourceIndex && 2) : 1
) + 0;
}
}

View file

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

View file

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

View file

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

View file

@ -21,6 +21,7 @@ for(...) ul.appendChild(li); // потом узлы
<li>Полностью создать список "вне DOM", а потом -- вставить в документ:
```js
//+ no-beautify
var ul = document.createElement('ul');
for(...) ul.appendChild(li); // сначала вставить узлы
document.body.appendChild(ul); // затем в документ
@ -122,7 +123,7 @@ li5.insertAdjacentHTML("beforeBegin", "<li>3</li><li>4</li>");
</script>
```
Единственный недостаток этого метода -- он не работает в Firefox до версии 8. Но его можно легко добавить, используя [полифилл insertAdjacentHTML для Firefox](insertAdjacentHTML.js).
Единственный недостаток этого метода -- он не работает в Firefox до версии 8. Но его можно легко добавить, используя [полифилл insertAdjacentHTML для Firefox](insertAdjacentFF.js).
У этого метода есть "близнецы-братья", которые поддерживаются везде, кроме Firefox, но в него они добавляются тем же полифиллом:
@ -211,6 +212,7 @@ ul.appendChild(fragment); // вместо фрагмента вставятс
```html
<!--+ run autorun height=80 -->
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.polyfill.io/v1/polyfill.js?features=Element.prototype.mutation"></script>
@ -233,6 +235,7 @@ ul.appendChild(fragment); // вместо фрагмента вставятс
</script>
</body>
</html>
```

View file

@ -34,9 +34,13 @@ HTML-документ ниже будет содержать `1 2 3`.
</script>
<table>
<tr>
<script> document.write('<td>') </script>
<script>
document.write('<td>')
</script>
Текст внутри TD.
<script> document.write('</td>') </script>
<script>
document.write('</td>')
</script>
</tr>
</table>
```

View file

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

View file

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

View file

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

View file

@ -80,7 +80,10 @@ function getCoords(elem) {
var top = box.top + scrollTop - clientTop;
var left = box.left + scrollLeft - clientLeft;
return { top: top, left: left };
return {
top: top,
left: left
};
}
```
@ -104,7 +107,8 @@ function getCoords(elem) {
```js
//+ autorun
function getOffsetSum(elem) {
var top = 0, left = 0;
var top = 0,
left = 0;
while (elem) {
top = top + parseInt(elem.offsetTop);
@ -112,7 +116,10 @@ function getOffsetSum(elem) {
elem = elem.offsetParent;
}
return {top: top, left: left};
return {
top: top,
left: left
};
}
```

View file

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

View file

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

View file

@ -13,7 +13,7 @@ DOM -- это представление документа в виде дере
Построим, для начала, дерево DOM для следующего документа.
```html
<!--+ run -->
<!--+ run no-beautify -->
<!DOCTYPE HTML>
<html>
<head>
@ -60,6 +60,7 @@ drawHtmlTree(node, 'div.domtree', 690, 350);
В остальных случаях всё честно -- если пробелы есть в документе, то они есть и в DOM, а если их убрать, то и в DOM их не будет, получится так:
```html
<!--+ no-beautify -->
<!DOCTYPE HTML>
<html><head><title>О лосях</title></head><body>Правда о лосях</body></html>
```
@ -86,6 +87,7 @@ drawHtmlTree(node, 'div.domtree', 690, 300);
Такой документ:
```html
<!--+ no-beautify -->
<p>Привет
<li>Мама
<li>и
@ -98,7 +100,7 @@ drawHtmlTree(node, 'div.domtree', 690, 300);
<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"}]}]}]}
drawHtmlTree(node, [].pop.call(document.querySelectorAll('div.domtree')), 690, 400);
drawHtmlTree(node, 'div.domtree', 690, 400);
</script>
[warn header="Таблицы всегда содержат `<tbody>`"]
@ -107,6 +109,7 @@ drawHtmlTree(node, [].pop.call(document.querySelectorAll('div.domtree')), 690,
Например, для такого HTML:
```html
<!--+ no-beautify -->
<table id="table">
<tr><td>1</td></tr>
</table>
@ -123,6 +126,7 @@ drawHtmlTree(node, 'div.domtree', 600, 200);
Вы видите? Появился `<tbody>`, как будто документ был таким:
```html
<!--+ no-beautify -->
<table>
*!*
<tbody>
@ -145,6 +149,7 @@ drawHtmlTree(node, 'div.domtree', 600, 200);
```html
<!DOCTYPE HTML>
<html>
<body>
Правда о лосях
<ol>
@ -155,6 +160,7 @@ drawHtmlTree(node, 'div.domtree', 600, 200);
<li>...и коварное!</li>
</ol>
</body>
</html>
```
@ -216,6 +222,7 @@ IE8- не генерирует текстовые узлы, если они со
То есть, такие два документа дадут идентичный DOM:
```html
<!--+ no-beautify -->
<!DOCTYPE HTML>
<html><head><title>О лосях</title></head><body>Правда о лосях</body></html>
```
@ -225,12 +232,15 @@ IE8- не генерирует текстовые узлы, если они со
```html
<!DOCTYPE HTML>
<html>
<head>
<title>О лосях</title>
</head>
<body>
Правда о лосях
</body>
</html>
```

View file

@ -7,7 +7,11 @@
```html
<!DOCTYPE HTML>
<html>
<head><meta charset="utf-8"></head>
<head>
<meta charset="utf-8">
</head>
<body>
<div>Пользователи:</div>
<ul>
@ -22,6 +26,7 @@
</script>
</body>
</html>
```

View file

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

View file

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

View file

@ -36,6 +36,7 @@ DOM позволяет делать что угодно с HTML-элементо
<!--+ run -->
<!DOCTYPE HTML>
<html>
<head>
<script>
*!*
@ -43,6 +44,7 @@ DOM позволяет делать что угодно с HTML-элементо
*/!*
</script>
</head>
<body>
<script>
@ -50,6 +52,7 @@ DOM позволяет делать что угодно с HTML-элементо
</script>
</body>
</html>
```
[/warn]
@ -76,6 +79,7 @@ DOM позволяет делать что угодно с HTML-элементо
<!--+ run -->
<!DOCTYPE HTML>
<html>
<body>
<div>Начало</div>
@ -94,6 +98,7 @@ DOM позволяет делать что угодно с HTML-элементо
</script>
...
</body>
</html>
```
@ -242,6 +247,7 @@ for(var key in elems) {
<!--+ run -->
<!DOCTYPE HTML>
<html>
<body>
<div>Начало</div>
@ -260,6 +266,7 @@ for(var key in elems) {
</script>
...
</body>
</html>
```

View file

@ -102,7 +102,6 @@ var elements = document.getElementsByTagName('div');
</table>
<script>
*!*
var tableElem = document.getElementById('age-table');
var elements = tableElem.getElementsByTagName('input');
@ -112,7 +111,6 @@ var elements = document.getElementsByTagName('div');
var input = elements[i];
alert( input.value + ': ' + input.checked );
}
</script>
```
@ -306,8 +304,9 @@ alert( articles.length ); // 2, найдёт оба элемента
Найдем заголовки с текстом `XPath` в текущем документе:
```js
//+ run
var result = document.evaluate("//h2[contains(., 'XPath')]", document.documentElement, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
//+ run no-beautify
var result = document.evaluate("//h2[contains(., 'XPath')]", document.documentElement, null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0; i < result.snapshotLength; i++) {
alert( result.snapshotItem(i).outerHTML );

View file

@ -36,7 +36,6 @@
<li>Магазин</li>
</ul>
<script>
var menu = document.getElementById('menu');
var lis = menu.getElementsByTagName('li');

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -331,9 +331,11 @@ document.body.sayHi(); // BODY, выполнилась с правильным t
.order[order-state="new"] {
color: green;
}
.order[order-state="pending"] {
color: blue;
}
.order[order-state="canceled"] {
color: red;
}
@ -417,7 +419,7 @@ div.classList.add('order-state-canceled');
Этот атрибут должен прятать элемент, действие весьма простое, для его поддержки в HTML достаточно такого CSS:
```html
<!--+ run height="80" -->
<!--+ run height="80" no-beautify -->
<style>
*!*
[hidden] { display: none }
@ -441,7 +443,7 @@ div.classList.add('order-state-canceled');
```html
<!--+ run height="80" -->
<!--+ run height="80" no-beautify -->
<style>
*!*
[hidden] { display: none }

View file

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

View file

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

View file

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

View file

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

View file

@ -234,7 +234,7 @@ button.onclick = function() {
Такой вызов работать не будет:
```js
//+ run
//+ run no-beautify
// при нажатии на body будут ошибки
// потому что при назначении в атрибут функция будет преобразована в строку
document.body.setAttribute('onclick', function() { alert(1) });
@ -255,6 +255,7 @@ document.body.setAttribute('onclick', function() { alert(1) });
При этом новый обработчик будет затирать предыдущий. Например, следующий код на самом деле назначает один обработчик -- последний:
```js
//+ no-beautify
input.onclick = function() { alert(1); }
// ...
input.onclick = function() { alert(2); } // заменит предыдущий обработчик
@ -294,6 +295,7 @@ element.removeEventListener( event, handler[, phase]);
Вот так `removeEventListener` не сработает:
```js
//+ no-beautify
elem.addEventListener( "click" , function() {alert('Спасибо!')});
// ....
elem.removeEventListener( "click", function() {alert('Спасибо!')});
@ -319,7 +321,7 @@ input.removeEventListener( "click", handler);
Метод `addEventListener` позволяет добавлять несколько обработчиков на одно событие одного элемента, например:
```html
<!--+ run -->
<!--+ run no-beautify -->
<input id="elem" type="button" value="Нажми меня"/>
<script>
@ -357,6 +359,7 @@ input.removeEventListener( "click", handler);
transition: width 1s;
width: 100px;
}
.wide {
width: 300px;
}
@ -374,7 +377,7 @@ input.removeEventListener( "click", handler);
*!*
elem.addEventListener("transitionend", function() {
alert( "addEventListener" ); // сработает по окончании анимации
}, false);
});
*/!*
</script>
```

View file

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

View file

@ -24,7 +24,10 @@
```html
<!--+ run autorun -->
<style>
body * { margin: 10px; border: 1px solid blue; }
body * {
margin: 10px;
border: 1px solid blue;
}
</style>
<form onclick="alert('form')">FORM
@ -218,6 +221,7 @@ elem.onclick = function(event) {
<dd>Кросс-браузерно остановить всплытие можно так:
```js
//+ no-beautify
event.stopPropagation ? event.stopPropagation() : (event.cancelBubble=true);
```

View file

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

View file

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

View file

@ -11,7 +11,9 @@
```html
<!--+ autorun height=190 untrusted -->
<style>
li { border: 1px solid green; }
li {
border: 1px solid green;
}
</style>
<ul onclick="alert(event.target)">
@ -57,7 +59,9 @@ for(var i=0; i<treeLis.length; i++) {
```html
<!--+ autorun height=190 untrusted -->
<style>
span { border: 1px solid red; }
span {
border: 1px solid red;
}
</style>
<ul onclick="alert(event.target.tagName)">

View file

@ -173,9 +173,15 @@ table.onclick = function(event) {
<script>
function Menu(elem) {
this.save = function() { alert('сохраняю'); };
this.load = function() { alert('загружаю'); };
this.search = function() { alert('ищу'); };
this.save = function() {
alert( 'сохраняю' );
};
this.load = function() {
alert( 'загружаю' );
};
this.search = function() {
alert( 'ищу' );
};
var self = this;

View file

@ -24,7 +24,7 @@
В следующем примере при клике по ссылке переход не произойдет:
```html
<!--+ autorun height=60 -->
<!--+ autorun height=60 no-beautify -->
<a href="/" onclick="return false">Нажми здесь</a>
или
<a href="/" onclick="event.preventDefault()">здесь</a>
@ -138,6 +138,7 @@ element.onclick = function(event) {
Можно записать в одну строку:
```js
//+ no-beautify
...
event.preventDefault ? event.preventDefault() : (event.returnValue=false);
...

View file

@ -37,7 +37,7 @@ var event = new Event(тип события[, флаги]);
При просмотре примера ниже кнопка обработчик `onclick` на кнопке сработает сам по себе, событие генерируется скриптом:
```html
<!--+ run -->
<!--+ run no-beautify -->
<button id="elem" onclick="alert('Клик');">Автоклик</button>
<script>
@ -74,7 +74,9 @@ var event = new Event(тип события[, флаги]);
setTimeout(hide, 2000);
function hide() {
var event = new Event("hide", {cancelable: true});
var event = new Event("hide", {
cancelable: true
});
if (!rabbit.dispatchEvent(event)) {
alert( 'действие отменено' );
} else {
@ -112,6 +114,7 @@ var event = new Event(тип события[, флаги]);
Другие свойства события, если они нужны, например координаты для события мыши -- можно присвоить в объект события позже, например:
```js
//+ no-beautify
var event = new Event("click", {bubbles: true, cancelable: false});
event.clientX = 100;
event.clientY = 100;
@ -124,7 +127,7 @@ event.clientY = 100;
Всё, что для этого нужно -- это флаг `bubbles`:
```html
<!--+ run -->
<!--+ run no-beautify -->
<h1 id="elem">Привет от скрипта!</h1>
<script>
@ -275,7 +278,10 @@ event.initEvent(type, boolean bubbles, boolean cancelable);
```js
// современный стандарт
var event = new Event("click", { bubbles: true, cancelable: true });
var event = new Event("click", {
bubbles: true,
cancelable: true
});
// старый стандарт
var event = document.createEvent("Event");
@ -304,7 +310,6 @@ event.initEvent("click", true, true);
if (elem.dispatchEvent(event) === false) {
alert( 'Событие было отменено preventDefault' );
}
</script>
```

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

Binary file not shown.

View file

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

View file

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

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Before After
Before After

View file

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

View file

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

View file

@ -12,6 +12,7 @@
Например:
```js
//+ no-beautify
// присвоить
$(document).data('prop', { anything: "любой объект" })
@ -34,6 +35,7 @@ elem[ jQuery.expando ] = id = ++jQuery.uuid; // средствами jQuery
<li>...А сами данные сохраняются в специальном объекте `jQuery.cache`:
```js
//+ no-beautify
jQuery.cache[id]['prop'] = { anything: "любой объект" };
```
@ -55,20 +57,37 @@ jQuery.cache[id]['prop'] = { anything: "любой объект" };
## Примеры утечек в 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/>')
.html(new Array(1000).join('text')) // div с текстом, возможна AJAX-загрузка
.html(new Array(1000).join('text'))
.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` данные остались.
@ -79,7 +98,7 @@ document.getElementById('data').innerHTML = ''; // (*)
Этот код также создает утечку:
```js
function go() {
function leak() {
$('<div/>')
.click(function() {})
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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