renovations

This commit is contained in:
Ilya Kantor 2015-02-16 10:39:40 +03:00
parent 9bf1b61cab
commit 0eec1aaccb
25 changed files with 68 additions and 64 deletions

View file

@ -2,6 +2,6 @@
[importance 5]
Добавьте к [предыдущей задаче](/task/pow-nan-spec) тесты, которые будет проверять, что любое число, кроме нуля, в нулевой степени равно `1`, а ноль в нулевой степени даёт `NaN` (это математически корректно, результат 0<sup>0</sup> не определён).
Добавьте к [предыдущей задаче](/task/pow-nan-spec) тесты, которые будут проверять, что любое число, кроме нуля, в нулевой степени равно `1`, а ноль в нулевой степени даёт `NaN` (это математически корректно, результат 0<sup>0</sup> не определён).
При необходимости, исправьте реализацию, чтобы тесты проходили без ошибок.

View file

@ -6,5 +6,5 @@ function unique(arr) {
obj[str] = true; // запомнить строку в виде свойства объекта
}
return Object.keys(obj); // или собрать ключи перебором для IE<9
return Object.keys(obj); // или собрать ключи перебором для IE8-
}

View file

@ -367,7 +367,7 @@ alert(newArr); // 1,2,3,4,5
## indexOf/lastIndexOf
Эти методы не поддерживаются в IE<9. Для их поддержки подключите библиотеку [ES5-shim](https://github.com/kriskowal/es5-shim).
Эти методы не поддерживаются в IE8-. Для их поддержки подключите библиотеку [ES5-shim](https://github.com/kriskowal/es5-shim).
Метод ["arr.indexOf(searchElement[, fromIndex])"](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf) возвращает номер элемента `searchElement` в массиве `arr` или `-1`, если его нет.
@ -446,7 +446,7 @@ alert(keys); // name, age
<li>`sort` -- для сортировки массива. Если не передать функцию сравнения -- сортирует элементы как строки.</li>
<li>`reverse` -- меняет порядок элементов на обратный.</li>
<li>`concat` -- объединяет массивы.</li>
<li>`indexOf/lastIndexOf` -- возвращают позицию элемента в массиве (не поддерживается в IE<9).</li>
<li>`indexOf/lastIndexOf` -- возвращают позицию элемента в массиве (не поддерживается в IE8-).</li>
</ul>
Изученных нами методов достаточно в 95% случаях, но существуют и другие. Для знакомства с ними рекомендуется заглянуть в справочник <a href="http://javascript.ru/Array">Array</a> и [Array в Mozilla Developer Network](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array).

View file

@ -190,7 +190,7 @@ var i = 5;
<!--+ run -->
<div id="a">...</div>
<script>
a = 5; // ошибка в IE<9! Правильно будет "var a = 5"
a = 5; // ошибка в IE8-! Правильно будет "var a = 5"
alert(a); // никогда не сработает
</script>
```
@ -200,7 +200,7 @@ var i = 5;
Это была реклама того, что надо везде ставить `var`.
</li>
<li>Ошибка при рекурсии через функцию-свойство `window`. Следующий код "умрет" в IE<9:
<li>Ошибка при рекурсии через функцию-свойство `window`. Следующий код "умрет" в IE8-:
```html
<!--+ run height=0 -->

View file

@ -121,7 +121,7 @@ user.sayHi(); // Василий
## Подробнее про this
Любая функция может иметь в себе `this`. Совершенно неважно, объявлена она в объекте или вне него.
Любая функция может иметь в себе `this`. Совершенно неважно, объявлена ли она в объекте или отдельно от него.
Значение `this` называется *контекстом вызова* и будет определено в момент вызова функции.

View file

@ -484,7 +484,7 @@ div.classList.add('order-state-canceled');
//+ run
document.body.setAttribute('my', 123);
alert( document.body.my ); // 123 в IE<9
alert( document.body.my ); // 123 в IE8-
```
При этом даже тип данных не меняется. Атрибут не становится строкой, как ему положено.

View file

@ -129,7 +129,7 @@ element.onclick = function(event) {
if (event.preventDefault) { // если метод существует
event.preventDefault(); // то вызвать его
} else { // иначе вариант IE<9:
} else { // иначе вариант IE8-:
event.returnValue = false;
}
}
@ -147,7 +147,7 @@ event.preventDefault ? event.preventDefault() : (event.returnValue=false);
<ul>
<li>Браузер имеет встроенные действия при ряде событий -- переход по ссылке, отправка формы и т.п. Как правило, их можно отменить.</li>
<li>Есть два способа отменить действие по умолчанию: первый -- использовать `event.preventDefault()` (IE<9: `event.returnValue=false`), второй -- `return false` из обработчика. Второй способ работает только если обработчик назначен через `onсобытие`.</li>
<li>Есть два способа отменить действие по умолчанию: первый -- использовать `event.preventDefault()` (IE8-: `event.returnValue=false`), второй -- `return false` из обработчика. Второй способ работает только если обработчик назначен через `onсобытие`.</li>
</ul>

View file

@ -17,7 +17,7 @@
for (var i = 0; i < sources.length; i++) {
var img = document.createElement('img');
// сначала onload/onerror, затем src - важно для IE<9
// сначала onload/onerror, затем src - важно для IE8-
img.onload = img.onerror = onLoad;
img.src = sources[i];
}

View file

@ -23,7 +23,7 @@
script.onload = onload; // все браузеры, IE с версии 9
script.onreadystatechange = function () { // IE<9
script.onreadystatechange = function () { // IE8-
if (this.readyState == 'loaded' || this.readyState == 'complete') {
setTimeout(onload, 0);
}

View file

@ -33,7 +33,7 @@
onload(i);
};
script.onreadystatechange = function() { // IE<9
script.onreadystatechange = function() { // IE8-
if (this.readyState == 'loaded' || this.readyState == 'complete') {
setTimeout(this.onload, 0); // возможны повторные вызовы onload
}

View file

@ -21,7 +21,7 @@ function addOnWheel(elem, handler) {
// 3.5 <= Firefox < 17, более старое событие DOMMouseScroll пропустим
elem.addEventListener ("MozMousePixelScroll", handler);
}
} else { // IE<9
} else { // IE8-
text.attachEvent ("onmousewheel", handler);
}
}

View file

@ -47,7 +47,7 @@ if (elem.addEventListener) {
// Firefox < 17
elem.addEventListener ("MozMousePixelScroll", onWheel);
}
} else { // IE<9
} else { // IE8-
elem.attachEvent ("onmousewheel", onWheel);
}

View file

@ -31,14 +31,15 @@ if (elem.addEventListener) {
// устаревший вариант события
elem.addEventListener ("mousewheel", onWheel);
} else {
// 3.5 <= Firefox < 17, более старое событие DOMMouseScroll пропустим
// Firefox < 17
elem.addEventListener ("MozMousePixelScroll", onWheel);
}
} else { // IE<9
} else { // IE8-
elem.attachEvent ("onmousewheel", onWheel);
}
// Это решение предусматривает поддержку IE8-
function onWheel(e) {
e = e || window.event;

View file

@ -37,8 +37,6 @@ function getChar(event) {
if (navigator.platform.substr(0,3) != 'Mac') { // событие для CapsLock глючит под Mac
document.onkeydown = function(e) {
e = e || event;
if (e.keyCode == 20 && capsLockEnabled !== null) {
capsLockEnabled = !capsLockEnabled;
}

View file

@ -5,7 +5,7 @@
Отслеживаем события изменения для перевычисления результатов:
<ul>
<li>На `input`: событие `input` и дополнительно `propertychange/keyup` для совместимости со старыми IE.</li>
<li>На `checkbox`: событие `click` вместо `change` для совместимости с IE<9.</li>
<li>На `checkbox`: событие `click` вместо `change` для совместимости с IE8-.</li>
<li>На `select`: событие `change`.</li>
</ul>

View file

@ -102,7 +102,7 @@ moneyElem.onkeyup = calculate;
// любые действия, кроме IE. В IE9 также работает, кроме удаления
moneyElem.oninput = calculate;
moneyElem.onpropertychange = function() { // для IE<9 изменение значения, кроме удаления
moneyElem.onpropertychange = function() { // для IE8- изменение значения, кроме удаления
event.propertyName == "value" && calculate();
}

View file

@ -1,4 +1,4 @@
# Изменение: change, input, propertychange
# Изменение: change, input, cut, copy, paste
На элементах формы происходят события клавиатуры и мыши, но есть и несколько других, особенных событий.
@ -24,9 +24,33 @@
Для того, чтобы видеть изменения `checkbox/radio` тут же -- в IE8- нужно повесить обработчик на событие `click` (оно произойдет и при изменении значения с клавиатуры) или воспользоваться событием `propertychange`, описанным далее.
[/warn]
## Событие propertychange
## Событие input
Это событие происходит только в старых IE, до версии 11, при любом изменении свойства. Оно позволяет отлавливать изменение тут же и используется, преимущественно, для исправления ошибок в старых IE.
Событие `input` срабатывает *тут же* при изменении значения текстового элемента и поддерживается всеми браузерами, кроме IE8-.
В IE9 оно поддерживается частично, а именно -- *не возникает при удалении символов* (как и `onpropertychange`).
Пример использования (не работает в IE8-):
```html
<!--+ autorun height=40 -->
<input type="text"> oninput: <span id="result"></span>
<script>
var input = document.body.children[0];
input.oninput = function() {
document.getElementById('result').innerHTML = input.value;
};
</script>
```
В современных браузерах `oninput` -- самое главное событие для работы с элементом формы. Именно его, а не `keydown/keypress` следует использовать.
Если бы ещё не проблемы со старыми IE... Впрочем, их можно решить при помощи события `propertychange`.
## IE10-, событие propertychange
Это событие происходит только в IE10-, при любом изменении свойства. Оно позволяет отлавливать изменение тут же. Оно нестандартное, и его основная область использования -- исправление недочётов обработки событий в старых IE.
Если поставить его на `checkbox` в IE8-, то получится "правильное" событие `change`:
@ -55,27 +79,10 @@ if("onpropertychange" in checkbox) {
</script>
```
Это событие также срабатывает при изменении значения текстового элемента, но в IE9 у него ошибка: оно не срабатывает при удалении символов.
Это событие также срабатывает при изменении значения текстового элемента. Поэтому его можно использовать в старых IE вместо `oninput`.
## Событие input
К сожалению, в IE9 у него недочёт: оно не срабатывает при удалении символов. Поэтому сочетания `onpropertychange` + `oninput` недостаточно, чтобы поймать любое изменение поля в старых IE. Далее мы рассмотрим пример, как это можно сделать иначе.
Событие `input` срабатывает *тут же* при изменении значения текстового элемента и поддерживается всеми браузерами, кроме IE8-.
В IE9 оно поддерживается частично, а именно -- *не возникает при удалении символов* (как и `onpropertychange`).
Пример использования (не работает в IE8-):
```html
<!--+ autorun height=40 -->
<input type="text"> oninput: <span id="result"></span>
<script>
var input = document.body.children[0];
input.oninput = function() {
document.getElementById('result').innerHTML = input.value;
};
</script>
```
## События cut, copy, paste

View file

@ -2,7 +2,7 @@
Событие `submit` возникает при отправке формы. Наиболее частое его применение -- это *валидация* (проверка) формы перед отправкой.
Метод `submit` позволяет инициировать отправку формы из JavaScript, без участия пользователя. Далее мы рассмотрим их важные детали использования.
Метод `submit` позволяет инициировать отправку формы из JavaScript, без участия пользователя. Далее мы рассмотрим детали их использования.
[cut]
## Событие submit
@ -15,9 +15,7 @@
Какой бы способ ни выбрал посетитель -- будет сгенерировано событие `submit`. Обработчик в нём может проверить данные и, если они неверны, то вывести ошибку и сделать `event.preventDefault()` -- тогда форма не отправится на сервер.
Посмотрим это на живом примере.
Оба способа выдадут сообщение, форма не будет отправлена:
Например, в таком HTML оба способа выведут `alert`, форма не будет отправлена:
```html
<!--+ autorun height=80 -->
@ -37,7 +35,7 @@
[smart header="Взаимосвязь событий `submit` и `click`"]
**При отправке формы путём нажатия Enter на текстовом поле, на элементе `<input type="submit">` везде, кроме IE<9, генерируется событие `click`.**
При отправке формы путём нажатия Enter на текстовом поле, на элементе `<input type="submit">` везде, кроме IE8-, генерируется событие `click`.
Это довольно забавно, учитывая что клика-то и не было.
@ -51,8 +49,8 @@
[/smart]
[warn header="В IE<9 событие `submit` не всплывает"]
В IE<9 событие `submit` не всплывает. Впрочем, если вешать обработчик `submit` на сам элемент формы, без использования делегирования, то это не создаёт проблем.
[warn header="В IE8- событие `submit` не всплывает"]
В IE8- событие `submit` не всплывает. Впрочем, если вешать обработчик `submit` на сам элемент формы, без использования делегирования, то это не создаёт проблем.
</li>
</ul>
[/warn]

View file

@ -25,7 +25,7 @@ function iframePost(url, data, onSuccess, onError) {
onSuccess( eval('(' + newName +')') );
};
// для IE<9 нужно использовать attachEvent вместо iframe.onload
// для IE8- нужно использовать attachEvent вместо iframe.onload
if (iframe.attachEvent && !iframe.addEventListener) {
iframe.attachEvent("onload", iframe.onload);
iframe.onload = null;

View file

@ -25,7 +25,7 @@ function iframePost(url, data, onSuccess, onError) {
onSuccess( eval('(' + newName +')') );
};
// для IE<9 нужно использовать attachEvent вместо iframe.onload
// для IE8- нужно использовать attachEvent вместо iframe.onload
if (iframe.attachEvent && !iframe.addEventListener) {
iframe.attachEvent("onload", iframe.onload);
iframe.onload = null;

View file

@ -139,7 +139,7 @@ box-shadow:0 0 100px 20px #000;
</ol>
CSS-препроцессоры, такие как [SASS](http://sass-lang.com/), [LESS](http://lesscss.org/), [Stylus](http://learnboost.github.com/stylus/), [Prefix-free](http://leaverou.github.com/prefixfree/) делает написание CSS сильно удобнее..
CSS-препроцессоры, такие как [SASS](http://sass-lang.com/), [LESS](http://lesscss.org/), [Stylus](http://learnboost.github.com/stylus/), [Autoprefixer](https://github.com/postcss/autoprefixer) делают написание CSS сильно удобнее..
Выберите один из них и используйте. Единственно, они добавляют дополнительную предобработку CSS, которую нужно учесть, и желательно, на сервере.

View file

@ -15,7 +15,7 @@
Но такие области можно создавать не только с помощью пользовательского выделения, но и из JavaScript-сценария, выполняя с ними определенные манипуляции. Однако, написать простой иллюстрирующий код сразу не выйдет, т.к. есть одно НО -- Internet Explorer до версии 9. В Microsoft создали собственную реализацию -- [объект TextRange](http://msdn.microsoft.com/en-us/library/ms535872.aspx). Разбёрем каждую реализацию по-отдельности.
### DOM-реализация Range (кроме IE<9)
### DOM-реализация Range (кроме IE8-)
`Range` состоит из двух граничных точек (boundary-points), соответствующих началу и концу области. Позиция любой граничной точки определяется в документе с помощью двух свойств: узел (node) и смещение (offset).
@ -64,7 +64,7 @@ function domRangeCreate() {
// Теперь мы можем вернуть текст, который содержится в полученной области
return rng.toString();
} else {
return 'Вероятно, у вас IE<9, смотрите реализацию TextRange ниже';
return 'Вероятно, у вас IE8-, смотрите реализацию TextRange ниже';
}
}
</script>
@ -147,7 +147,7 @@ function domRangeHighlight(text) {
// Обернем наш Range в спан
rng.surroundContents( highlightDiv );
} else {
alert('Вероятно, у вас IE<9, смотрите реализацию TextRange ниже');
alert('Вероятно, у вас IE8-, смотрите реализацию TextRange ниже');
}
} else {
alert('Совпадений не найдено');
@ -290,7 +290,7 @@ function getSelectionText() {
}
```
Все браузеры, кроме IE<9 поддерживают метод `window.getSelection()`, который возвращает объект, схожий с рассмотренным ранее `Range`. У этого объекта есть точка начала выделения (anchor) и фокусная точка окончания (focus). Точки могут совпадать. Рассмотрим свойства и методы объекта `Selection`:
Все браузеры, кроме IE8- поддерживают метод `window.getSelection()`, который возвращает объект, схожий с рассмотренным ранее `Range`. У этого объекта есть точка начала выделения (anchor) и фокусная точка окончания (focus). Точки могут совпадать. Рассмотрим свойства и методы объекта `Selection`:
<ul>
<li>Свойство `anchorNode` вернет контейнер, в котором начинается выделение. Замечу, что началом выделения считается та граница, от которой вы начали выделение. То есть, если вы выделяете справа налево, то началом будет именно правая граница. Это правило работает везде, кроме браузера Opera, в котором `anchorNode` вернет ссылку на узел левого края выделения.</li>
@ -328,7 +328,7 @@ IE предоставляет собственный интерфейс взаи
Проще всего решить эту задачу следующим образом:
<ol>
<li>Создать объект `Range` (`TextRange` для IE<9).</li>
<li>Создать объект `Range` (`TextRange` для IE8-).</li>
<li>Перевести полученный объект в выделение.</li>
</ol>
@ -371,7 +371,7 @@ function clearSelection() {
// современный объект Selection
window.getSelection().removeAllRanges();
} catch(e) {
// для IE<9
// для IE8-
document.selection.empty();
}
}
@ -382,7 +382,7 @@ function clearSelection() {
<ul>
<li>В современных браузерах поддерживается стандартный объект [Range](http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html)
</li>
<li>В IE<9 поддерживается только собственный объект [TextRange](http://help.dottoro.com/ljgbbkjf.php).</li>
<li>В IE8- поддерживается только собственный объект [TextRange](http://help.dottoro.com/ljgbbkjf.php).</li>
</ul>
Есть библиотеки, которые "исправляют" объект `TextRange`, добавляя ему нужные свойства из `Range`.

View file

@ -28,7 +28,7 @@ function domRangeCreate() {
// Теперь мы можем вернуть текст, который содержится в полученной области
return rng.toString();
} else {
return 'Вероятно, у вас IE<9, смотрите реализацию TextRange ниже';
return 'Вероятно, у вас IE8-, смотрите реализацию TextRange ниже';
}
}
</script>

View file

@ -24,7 +24,7 @@ function domRangehighlight( text ) {
highlightDiv.style.backgroundColor = 'blue';
rng.surroundContents( highlightDiv );
} else
alert('Вероятно, у вас IE<9, смотрите реализацию TextRange ниже');
alert('Вероятно, у вас IE8-, смотрите реализацию TextRange ниже');
} else
alert('Совпадений не найдено');
}

View file

@ -12,9 +12,9 @@
<dl>
<dt>Рамка: `frameborder="0"`</dt>
<dd>Если хочется, чтобы в IE<9 вокруг ифреймов не было рамок, то поставьте атрибут `frameborder="0"`.
<dd>Если хочется, чтобы в IE8- вокруг ифреймов не было рамок, то поставьте атрибут `frameborder="0"`.
В IE<9 все ифреймы в примере ниже, кроме последнего, будут с рамкой:
В IE8- все ифреймы в примере ниже, кроме последнего, будут с рамкой:
```html
<!--+ run -->