renovations
This commit is contained in:
parent
9946f93792
commit
13e6f9383f
30 changed files with 126 additions and 144 deletions
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 50 KiB |
|
@ -184,7 +184,7 @@ func();
|
|||
//+ run
|
||||
function func() {
|
||||
"use strict";
|
||||
alert(this); // выведет undefined (кроме IE<10)
|
||||
alert(this); // выведет undefined (кроме IE9-)
|
||||
}
|
||||
|
||||
func();
|
||||
|
|
|
@ -222,7 +222,7 @@ CSS не требует, чтобы вокруг `table-cell` была стру
|
|||
|
||||
При этом он ведёт себя как ячейка `TD`, то есть подстраивается под размер содержимого и умеет вертикально центрировать его при помощи `vertical-align`.
|
||||
|
||||
Значение `display: table-cell` поддерживается во всех браузерах, кроме IE<8. В IE6,7 можно использовать для центрирования CSS-выражения или реальную таблицу.
|
||||
Значение `display: table-cell` поддерживается во всех браузерах, кроме IE7-. В IE6,7 можно использовать для центрирования CSS-выражения или реальную таблицу.
|
||||
|
||||
## Значения list-item и run-in
|
||||
|
||||
|
|
|
@ -327,7 +327,7 @@ h2 {
|
|||
|
||||
Добавив этот класс к родителю, получим тот же результат, что и выше. [edit src="winnie-clearfill-clearfix"]Открыть код[/edit].
|
||||
|
||||
Псевдоселектор `:after` не поддерживается в IE<8, но для старых IE сработает другое свойство:
|
||||
Псевдоселектор `:after` не поддерживается в IE7-, но для старых IE сработает другое свойство:
|
||||
|
||||
```css
|
||||
.clearfix {
|
||||
|
@ -351,7 +351,7 @@ h2 {
|
|||
|
||||
Несмотря на внешнюю странность, этот способ не является "хаком". Такое поведение прописано в спецификации CSS.
|
||||
|
||||
Однако, установка `overflow` может привести к появлению полосы прокрутки, способ с дополнительным элементом (или `.clearfix:after`, если без IE<8) более безопасен.
|
||||
Однако, установка `overflow` может привести к появлению полосы прокрутки, способ с дополнительным элементом (или `.clearfix:after`, если без IE7-) более безопасен.
|
||||
|
||||
|
||||
## Еще применения float
|
||||
|
|
|
@ -355,7 +355,7 @@ position: fixed;
|
|||
|
||||
<ul>
|
||||
<li>Ширина элемента по умолчанию устанавливается по содержимому.</li>
|
||||
<li>Можно указать противположные границы `left/right` (`top/bottom`). Элемент растянется. Возможность не поддерживается в IE<8.</li>
|
||||
<li>Можно указать противположные границы `left/right` (`top/bottom`). Элемент растянется. Возможность не поддерживается в IE7-.</li>
|
||||
<li>Окружающие элементы заполняют освободившееся место.</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
<!--+ autorun height=50 -->
|
||||
<style>
|
||||
.outer {
|
||||
*!*text-align: center;*/!* /* Для IE<8 */
|
||||
*!*text-align: center;*/!* /* Для IE7- */
|
||||
border: 1px solid blue;
|
||||
}
|
||||
.inner {
|
||||
|
@ -390,7 +390,7 @@
|
|||
|
||||
Для горизонтального центрирования:
|
||||
<ul>
|
||||
<li>`text-align: center` -- центрирует инлайн-элементы в блоке. В IE<8 центрирует всё, но это нестандартное поведение.</li>
|
||||
<li>`text-align: center` -- центрирует инлайн-элементы в блоке. В IE7- центрирует всё, но это нестандартное поведение.</li>
|
||||
<li>`margin: 0 auto` -- центрирует блок внутри родителя. У блока должна быть указана ширина.</li>
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -31,12 +31,12 @@
|
|||
|
||||
В примере выше верхняя рамка нижнего элемента находится на территории верхнего и наоборот.
|
||||
|
||||
Все браузеры, кроме IE<10, также поддерживают свойство `outline-offset`, задающее отступ `outline` от внешней границы элемента:
|
||||
Все браузеры, кроме IE9-, также поддерживают свойство `outline-offset`, задающее отступ `outline` от внешней границы элемента:
|
||||
|
||||
```html
|
||||
<!--+ autorun height=60 -->
|
||||
<div style="border:3px solid blue; outline: 3px solid red; outline-offset:5px">
|
||||
Везде, кроме IE<10, между рамками будет расстояние 5px
|
||||
Везде, кроме IE9-, между рамками будет расстояние 5px
|
||||
</div>
|
||||
```
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# IFRAME для длинных соединений
|
||||
|
||||
Реализация COMET, рассматриваемая здесь, подходит для IE<10 и других старых браузеров, не поддерживающих специализированный стандарт WebSocket.
|
||||
Реализация COMET, рассматриваемая здесь, подходит для IE9- и других старых браузеров, не поддерживающих специализированный стандарт WebSocket.
|
||||
|
||||
Бесконечный IFRAME -- самый старый способ организации COMET. Когда-то он был основой AJAX-приложений, а сейчас -- используется лишь в случаях, когда браузер не поддерживает современный стандарт WebSocket.
|
||||
[cut]
|
||||
|
|
|
@ -36,8 +36,8 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<th>Кросс-доменность</th>
|
||||
<td>да, кроме IE<10<a class="link-ref" href="#x1">x1</a></td>
|
||||
<td>да, сложности в IE<8<a class="link-ref" href="#i1">i1</a></td>
|
||||
<td>да, кроме IE9-<a class="link-ref" href="#x1">x1</a></td>
|
||||
<td>да, сложности в IE7-<a class="link-ref" href="#i1">i1</a></td>
|
||||
<td>да</td>
|
||||
<td>да</td>
|
||||
<td>да</td>
|
||||
|
@ -89,7 +89,7 @@
|
|||
<dt>`WebSocket`</dt>
|
||||
<dd>
|
||||
<ol>
|
||||
<li id="w1">Имеется в виду поддержка окончательной редакции протокола [RFC 6455](http://tools.ietf.org/html/rfc6455). Более старые браузеры могут поддерживать черновики протокола. IE<10 не поддерживает `WebSocket`.</li>
|
||||
<li id="w1">Имеется в виду поддержка окончательной редакции протокола [RFC 6455](http://tools.ietf.org/html/rfc6455). Более старые браузеры могут поддерживать черновики протокола. IE9- не поддерживает `WebSocket`.</li>
|
||||
</ol>
|
||||
</dd>
|
||||
</dl>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# XMLHttpRequest и POST, отсылка форм
|
||||
# XMLHttpRequest POST, формы и кодировка
|
||||
|
||||
Во время обычной отправки формы `<form>` браузер собирает значения её полей, делает из них строку и составляет тело GET/POST-запроса для посылки на сервер.
|
||||
|
||||
|
@ -90,7 +90,7 @@ xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
|||
```
|
||||
[/smart]
|
||||
|
||||
## POST-запрос
|
||||
## POST с urlencoded
|
||||
|
||||
В методе POST параметры передаются не в URL, а в теле, посылаемом через `send(body)`. Поэтому `params` нужно указывать не в `open`, а в `send`.
|
||||
|
||||
|
@ -123,12 +123,7 @@ xhr.send(body);
|
|||
|
||||
В этой кодировке поля пересылаются одно за другим, через строку-разделитель.
|
||||
|
||||
|
||||
|
||||
|
||||
Этот способ используется в методе `POST` и указывается атрибутом `enctype="multipart/form-data"`.
|
||||
|
||||
Пример формы
|
||||
Чтобы использовать этот способ, нужно указат его в атрибуте `enctype` и метод должен быть POST:
|
||||
|
||||
```html
|
||||
<form action="/submit" method="POST" enctype="multipart/form-data">
|
||||
|
@ -137,7 +132,7 @@ xhr.send(body);
|
|||
</form>
|
||||
```
|
||||
|
||||
Форма при такой кодировке пересылается в теле запроса, поля разделены случайно сгенерированной строкой `boundary`, вот так:
|
||||
Форма при такой кодировке будет выглядеть примерно так:
|
||||
|
||||
```
|
||||
...Заголовки...
|
||||
|
@ -154,16 +149,21 @@ Content-Disposition: form-data; name="*!*surname*/!*"
|
|||
--RaNdOmDeLiMiTeR--
|
||||
```
|
||||
|
||||
Сервер видит заголовок `Content-Type: multipart/form-data` и раскодирует поля формы.
|
||||
...То есть, поля передаются одно за другим, значения не кодируются, а чтобы было чётко понятно, какое значение где -- поля разделены случайно сгенерированной строкой, которую называют "boundary" (англ. граница), в примере выше это `RaNdOmDeLiMiTeR`:
|
||||
|
||||
**Как видно, само содержимое полей при этом оставляется "как есть". Поэтому такой способ используется в первую очередь при пересылке файла.**
|
||||
Сервер видит заголовок `Content-Type: multipart/form-data`, читает из него границу и раскодирует поля формы.
|
||||
|
||||
Такой способ используется в первую очередь при пересылке файлов, так перекодировка мегабайтов через urlencoded существенно загрузила бы браузер. Да и объём данных после неё сильно вырос бы.
|
||||
|
||||
### POST-запрос
|
||||
Однако, никто не мешает использовать эту кодировку всегда для POST запросов. Для GET доступна только urlencoded.
|
||||
|
||||
В `XMLHttpRequest` можно указать кодировку `multipart/form-data` и вручную сформировать тело запроса, удовлетворяющее требованиям кодировки.
|
||||
## POST с multipart/form-data
|
||||
|
||||
Пример кода для формирования запроса в кодировке `multipart/form-data`:
|
||||
Сделать POST-запрос в кодировке `multipart/form-data` можно и через XMLHttpRequest.
|
||||
|
||||
Достаточно указать в заголовке `Content-Type` кодировку и границу, и далее сформировать тело запроса, удовлетворяющее требованиям кодировки.
|
||||
|
||||
Пример кода для пересылке того же запроса, что и раньше, в кодировке `multipart/form-data`:
|
||||
|
||||
```js
|
||||
var data = {
|
||||
|
@ -202,11 +202,9 @@ xhr.send(body);
|
|||
Тело запроса будет иметь вид, описанный выше, то есть поля через разделитель.
|
||||
|
||||
[smart header="Отправка файла"]
|
||||
**Можно создать запрос, который сервер воспримет как загрузку файла.**
|
||||
Можно создать запрос, который сервер воспримет как загрузку файла.
|
||||
|
||||
Для этого текст файла должен быть уже доступен JavaScript, т.е. произвольный файл прочитать и переслать, конечно же, нельзя.
|
||||
|
||||
Для добавления файла нужно использовать тот же код, что выше, но при добавлении поля вместо строки `body.push('Content-Disposition: form-data; name=...')` указать расширенные заголовки:
|
||||
Для добавления файла нужно использовать тот же код, что выше, модифицировав заголовки перед полем, которое является файлом, так:
|
||||
|
||||
```js
|
||||
Content-Disposition: form-data; name="myfile"; filename="pic.jpg"
|
||||
|
@ -214,39 +212,28 @@ Content-Type: image/jpeg
|
|||
(пустая строка)
|
||||
содержимое файла
|
||||
```
|
||||
|
||||
Код будет выглядеть так:
|
||||
|
||||
```js
|
||||
body.push('Content-Disposition: form-data; name="'+key+'"; filename="pic.jpg"\r\nContent-Type: image/jpeg\r\n\r\n'+data[key]+'\r\n');
|
||||
```
|
||||
|
||||
Имя файла `pic.jpg` здесь задано явно, но вам не составит труда его заменить.
|
||||
[/smart]
|
||||
|
||||
## FormData
|
||||
|
||||
Современные браузеры, исключая IE<10, поддерживают объект [FormData](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/FormData/Using_FormData_Objects), который позволяет загружать формы напрямую.
|
||||
Современные браузеры, исключая IE9- (впрочем, есть полифилл), поддерживают встроенный объект [FormData](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/FormData/Using_FormData_Objects), который кодирует формы для отправки на сервер.
|
||||
|
||||
**В форме могут быть любые поля, в том числе файловые.**
|
||||
|
||||
Лучше всего это показывает пример:
|
||||
Это очень удобно. Например:
|
||||
|
||||
```html
|
||||
<form name="user">
|
||||
<input name="firstname" value="Вася">
|
||||
<form name="person">
|
||||
<input name="name" value="Виктор">
|
||||
<input name="surname" value="Цой">
|
||||
</form>
|
||||
|
||||
<script>
|
||||
// создать объект из формы
|
||||
// в форме могут быть любые поля
|
||||
var form = document.forms.user;
|
||||
// создать объект для формы
|
||||
*!*
|
||||
var formData = new FormData(form);
|
||||
var formData = new FormData(document.forms.person);
|
||||
*/!*
|
||||
|
||||
// добавить к пересылке ещё пару ключ - значение
|
||||
formData.append("lastname", "Пупкин");
|
||||
formData.append("patronym", "Робертович");
|
||||
|
||||
// отослать
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
@ -257,7 +244,7 @@ xhr.send(formData);
|
|||
</script>
|
||||
```
|
||||
|
||||
Этот код отправит на сервер форму с полями `firstname` и `lastname`.
|
||||
Этот код отправит на сервер форму с полями `name`, `surname` и `patronym`.
|
||||
|
||||
Интерфейс:
|
||||
<ul>
|
||||
|
@ -265,30 +252,37 @@ xhr.send(formData);
|
|||
<li>Метод `formData.append(name, value)` добавляет данные к форме.</li>
|
||||
</ul>
|
||||
|
||||
Интеграция `FormData` с `XMLHttpRequest` встроена в браузер.
|
||||
[head]
|
||||
<script>
|
||||
function voteSync(outputElem) {
|
||||
var xhr = new XMLHttpRequest(); // (1)
|
||||
Объект `formData` можно сразу отсылать, интеграция `FormData` с `XMLHttpRequest` встроена в браузер. Кодировка при этом будет `multipart/form-data`.
|
||||
|
||||
xhr.open('GET', '/files/tutorial/ajax/xhr/vote.php', false);
|
||||
xhr.send(null); // (2)
|
||||
## Другие кодировки
|
||||
|
||||
outputElem.innerHTML = xhr.responseText; // (3)
|
||||
}
|
||||
XMLHttpRequest сам по себе не ограничивает кодировку и формат пересылаемых данных.
|
||||
|
||||
function vote(outputElem) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
Поэтому просто для обмена данными JS <-> сервер, без всяких форма, часто используется POST с JSON:
|
||||
|
||||
xhr.open('GET', '/files/tutorial/ajax/xhr/vote.php', true);
|
||||
```js
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState != 4) return;
|
||||
debugger
|
||||
outputElem.innerHTML = xhr.responseText;
|
||||
}
|
||||
var json = JSON.stringify({
|
||||
name: "Виктор",
|
||||
surname: "Цой"
|
||||
});
|
||||
|
||||
xhr.send(null);
|
||||
}
|
||||
</script>
|
||||
[/head]
|
||||
xhr.open("POST", '/submit', true)
|
||||
xhr.setRequestHeader('Content-type','application/json; charset=utf-8');
|
||||
|
||||
xhr.onreadystatechange = ...;
|
||||
|
||||
xhr.send(json);
|
||||
```
|
||||
|
||||
## Итого
|
||||
|
||||
<ul>
|
||||
<li>У форм есть две основные кодировки: `application/x-www-form-urlencoded` -- по умолчанию и `multipart/form-data` -- для POST запросов, если явно указана в `enctype`. Вторая кодировка обычно используется для больших данных и только для тела запроса.</li>
|
||||
<li>Для составления запроса в `application/x-www-form-urlencoded` используется функция `encodeURIComponent`.</li>
|
||||
<li>Для отправки запроса в `multipart/form-data` -- объект `FormData`.</li>
|
||||
<li>Для обмена данными JS <-> сервер можно использовать и просто JSON, желательно с указанием кодировки в заголовке `Content-Type`.</li>
|
||||
</ul>
|
||||
|
||||
В XMLHttpRequest можно использовать и другие HTTP-методы, например PUT, DELETE, TRACE. К ним применимы все те же принципы, что описаны выше.
|
||||
|
|
|
@ -3,8 +3,10 @@
|
|||
Обычно запрос `XMLHttpRequest` может делать запрос только в рамках текущего сайта. При попытке использовать другой домен/порт/протокол -- браузер выдаёт ошибку.
|
||||
|
||||
Существует современный стандарт [XMLHttpRequest](http://www.w3.org/TR/XMLHttpRequest/), он ещё в состоянии черновика, но предусматривает кросс-доменные запросы и многое другое.
|
||||
|
||||
[cut]
|
||||
Большинство возможностей этого стандарта уже поддерживаются всеми браузерами, но увы, не в IE<10.
|
||||
|
||||
Большинство возможностей этого стандарта уже поддерживаются всеми браузерами, но увы, не в IE9-.
|
||||
|
||||
Впрочем, частично кросс-доменные запросы поддерживаются, начиная с IE8, только вместо `XMLHttpRequest` нужно использовать объект [XDomainRequest](http://msdn.microsoft.com/en-us/library/ie/cc288060.aspx).
|
||||
|
||||
|
@ -102,9 +104,9 @@ Access-Control-Allow-Origin: http://javascript.ru
|
|||
|
||||
|
||||
|
||||
### Ограничения IE<10
|
||||
### Ограничения IE9-
|
||||
|
||||
В IE<10 используется `XDomainRequest`, который представляет собой урезанный `XMLHttpRequest`.
|
||||
В IE9- используется `XDomainRequest`, который представляет собой урезанный `XMLHttpRequest`.
|
||||
|
||||
На него действуют ограничения:
|
||||
|
||||
|
@ -122,9 +124,9 @@ Access-Control-Allow-Origin: http://javascript.ru
|
|||
|
||||
Современный стандарт [XMLHttpRequest](http://www.w3.org/TR/XMLHttpRequest/) предусматривает средства для преодоления этих ограничений, но на момент выхода IE8 они ещё не были проработаны, поэтому их не реализовали. А IE9 исправил некоторые ошибки, но в общем не добавил ничего нового.
|
||||
|
||||
Так как большинство сайтов хотят поддерживать IE<10, то на практике кросс-доменные запросы редко используют, предпочитая другие способы кросс-доменной коммуникации. Например, динамически создаваемый тег `SCRIPT` или вспомогательный `IFRAME` с другого домена. Мы разберём эти подходы в последующих главах.
|
||||
Так как большинство сайтов хотят поддерживать IE9-, то на практике кросс-доменные запросы редко используют, предпочитая другие способы кросс-доменной коммуникации. Например, динамически создаваемый тег `SCRIPT` или вспомогательный `IFRAME` с другого домена. Мы разберём эти подходы в последующих главах.
|
||||
|
||||
[smart header="Как разрешить кросс-доменные запросы от доверенного сайта в IE<10?"]
|
||||
[smart header="Как разрешить кросс-доменные запросы от доверенного сайта в IE9-?"]
|
||||
|
||||
Разрешить кросс-доменные запросы можно в настройках IE, во вкладке "Безопасность", включив пункт "Доступ к источникам данных за пределами домена".
|
||||
|
||||
|
@ -145,7 +147,7 @@ Access-Control-Allow-Origin: http://javascript.ru
|
|||
Есть и другие способы обойти кросс-доменные ограничения, например использование тега `SCRIPT` или `IFRAME`. Их детали мы рассмотрим в следующих главах, так как здесь мы рассматриваем именно `XMLHttpRequest`.
|
||||
|
||||
|
||||
**Расширенные возможности, описанные далее, поддерживаются всеми современными браузерами, кроме IE<10.**
|
||||
**Расширенные возможности, описанные далее, поддерживаются всеми современными браузерами, кроме IE9-.**
|
||||
|
||||
## Запросы от имени пользователя
|
||||
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -1,22 +1,16 @@
|
|||
# XMLHttpRequest: длинные опросы
|
||||
|
||||
Способ организации COMET, который мы рассмотрим в этой главе, прост и подходит в 90% реальных случаев.
|
||||
В этой главе мы рассмотрим способ организации COMET, то есть непрерывного получения данных с сервера, который очень прост и подходит в 90% реальных случаев.
|
||||
|
||||
[cut]
|
||||
|
||||
## Частые опросы
|
||||
|
||||
Первое решение, которое приходит в голову для получения событий с сервера -- это "частые опросы" (polling), т.е периодические запросы на сервер: "эй, я тут, изменилось ли что-нибудь?". Например, раз в 10 секунд.
|
||||
Первое решение, которое приходит в голову для непрерывного получения событий с сервера -- это "частые опросы" (polling), т.е периодические запросы на сервер: "эй, я тут, изменилось ли что-нибудь?". Например, раз в 10 секунд.
|
||||
|
||||
В ответ сервер во-первых помечает у себя, что клиент онлайн, а во-вторых посылает сообщение, в котором в специальном формате содержится весь пакет событий, накопившихся к данному моменту.
|
||||
|
||||
**У частых опросов есть одна большая проблема, а именно -- большие задержки между созданием и получением данных.**
|
||||
|
||||
Сервер отсылает их не тогда, когда они появились, а когда настанет время очередного запроса.
|
||||
|
||||
[summary]
|
||||
Задержка = время между опросами + установление соединения + передача данных.
|
||||
[/summary]
|
||||
При этом, однако, возможна задержка между появлением и получением данных, как раз в размере этих 10 секунд между запросами.
|
||||
|
||||
Другой минус -- лишний входящий трафик на сервер. При каждом запросе браузер передает множество заголовков и в ответ получает, кроме данных, также заголовки. Для некоторых приложений трафик заголовков может в 10 и более раз превосходить трафик реальных данных.
|
||||
|
||||
|
@ -48,13 +42,14 @@
|
|||
|
||||
<img src="longpoll.png">
|
||||
|
||||
При этом если соединение рвётся само, например, закрыто прокси-сервером, то браузер тут же отсылает новый запрос.
|
||||
При этом если соединение рвётся само, например, из-за ошибки в сети, то браузер тут же отсылает новый запрос.
|
||||
|
||||
Примерный код клиентской части:
|
||||
|
||||
```js
|
||||
function subscribe(url) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.onreadystatechange = function() {
|
||||
if (this.readyState != 4) return;
|
||||
|
||||
|
@ -67,38 +62,27 @@ function subscribe(url) {
|
|||
subscribe(url);
|
||||
}
|
||||
xhr.open("GET", url, true);
|
||||
xhr.send('');
|
||||
xhr.send();
|
||||
}
|
||||
```
|
||||
|
||||
Функция `subscribe` делает запрос, при ответе обрабатывает результат, и тут же запускает процесс по новой.
|
||||
|
||||
[compare]
|
||||
-Сообщение отправляются клиенту тут же.
|
||||
-Сервер должен уметь держать большое количество ожидающих соединений.
|
||||
-Простота реализации.
|
||||
[/compare]
|
||||
Сервер, конечно же, должен уметь работать с большим количеством таких "ожидающих" соединений.
|
||||
|
||||
## Демо: чат
|
||||
|
||||
Для примера вы можете скачать простейший чат, где в качестве сервера -- Node.JS: [longpoll.zip](/zip/tutorial/ajax/xhr/longpoll.zip).
|
||||
|
||||
Демо:
|
||||
|
||||
[iframe src="longpoll" border="1" height="200px" link zip]
|
||||
[codetabs src="longpoll"]
|
||||
|
||||
## Область применения
|
||||
|
||||
Длинные опросы отлично работают в тех случаях, когда сообщения приходят редко.
|
||||
|
||||
При большом количестве частых сообщений график приёма-отправки, приведённый выше, превращается в "пилу". Каждое сообщение -- это новый запрос, дополнительный трафик.
|
||||
При большом количестве частых сообщений график приёма-отправки, приведённый выше, превращается в "пилу". Каждое сообщение -- это новый запрос, дополнительный трафик заголовков.
|
||||
|
||||
В этих случаях используются другие способы получения данных, подразумевающие непрерывное соединение с сервером. Мы рассмотрим их в следующих главах.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
@ -4,7 +4,10 @@ function PublishForm(form, url) {
|
|||
function sendMessage(message) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", url, true);
|
||||
xhr.send('message='+encodeURIComponent(message));
|
||||
// просто отсылаю сообщение "как есть" без кодировки
|
||||
// если бы было много данных, то нужно было бы отослать JSON из объекта с ними
|
||||
// или закодировать их как-то иначе
|
||||
xhr.send(message);
|
||||
}
|
||||
|
||||
form.onsubmit = function() {
|
||||
|
@ -31,6 +34,7 @@ function SubscribePane(elem, url) {
|
|||
xhr.onreadystatechange = function() {
|
||||
if (this.readyState != 4) return;
|
||||
|
||||
console.log(this);
|
||||
if (this.status == 200) {
|
||||
showMessage(this.responseText);
|
||||
subscribe();
|
||||
|
@ -44,7 +48,7 @@ function SubscribePane(elem, url) {
|
|||
setTimeout(subscribe, 1000); // попробовать ещё раз через 1 сек
|
||||
}
|
||||
xhr.open("GET", url, true);
|
||||
xhr.send('');
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
subscribe();
|
|
@ -18,7 +18,8 @@
|
|||
|
||||
<script>
|
||||
new PublishForm(document.forms.publish, 'publish');
|
||||
new SubscribePane(document.getElementById('subscribe'), 'subscribe');
|
||||
// random url to fix https://code.google.com/p/chromium/issues/detail?id=46104
|
||||
new SubscribePane(document.getElementById('subscribe'), 'subscribe?random='+Math.random());
|
||||
</script>
|
||||
|
||||
</body>
|
|
@ -10,31 +10,27 @@ var subscribers = {};
|
|||
function onSubscribe(req, res) {
|
||||
var id = Math.random();
|
||||
|
||||
res.setHeader('Content-Type', 'text/plain;charset=utf-8');
|
||||
res.setHeader("Cache-Control", "no-cache, must-revalidate");
|
||||
|
||||
subscribers[id] = res;
|
||||
console.log("новый клиент " + id + ", клиентов:" + Object.keys(subscribers).length);
|
||||
//console.log("новый клиент " + id + ", клиентов:" + Object.keys(subscribers).length);
|
||||
|
||||
req.on('close', function() {
|
||||
delete subscribers[id];
|
||||
console.log("клиент "+id+" отсоединился, клиентов:" + Object.keys(subscribers).length);
|
||||
//console.log("клиент "+id+" отсоединился, клиентов:" + Object.keys(subscribers).length);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function onPublish(req, res, message) {
|
||||
function publish(message) {
|
||||
|
||||
console.log("есть сообщение, клиентов:" + Object.keys(subscribers).length);
|
||||
//console.log("есть сообщение, клиентов:" + Object.keys(subscribers).length);
|
||||
|
||||
for(var id in subscribers) {
|
||||
console.log("отсылаю сообщение " + id);
|
||||
//console.log("отсылаю сообщение " + id);
|
||||
var res = subscribers[id];
|
||||
|
||||
res.writeHead(200, {
|
||||
'Content-Type': 'text/plain;charset=utf-8',
|
||||
"Cache-Control": "no-cache, must-revalidate"
|
||||
});
|
||||
|
||||
res.write(message, 'utf-8');
|
||||
res.end();
|
||||
res.end(message);
|
||||
}
|
||||
|
||||
subscribers = {};
|
||||
|
@ -52,11 +48,13 @@ function accept(req, res) {
|
|||
// отправка сообщения
|
||||
if (urlParsed.pathname == '/publish' && req.method == 'POST') {
|
||||
// принять POST-запрос
|
||||
var post;
|
||||
req.addListener('data', function (chunk) {
|
||||
post = querystring.parse(chunk.toString());
|
||||
}).addListener('end', function () {
|
||||
onPublish(req, res, post.message.toString()); // собственно, отправка
|
||||
req.setEncoding('utf8');
|
||||
var message = '';
|
||||
req.on('data', function (chunk) {
|
||||
message += chunk;
|
||||
}).on('end', function () {
|
||||
publish(message); // собственно, отправка
|
||||
res.end("ok");
|
||||
});
|
||||
|
||||
return;
|
|
@ -32,7 +32,7 @@ xhr.upload.onload = function() {
|
|||
|
||||
Современный `XMLHttpRequest` позволяет отправить на сервер всё, что угодно. Текст, файл, форму.
|
||||
|
||||
Мы, для примера, рассмотрим загрузку файла с индикацией прогресса. Это требует от браузера поддержки [File API](http://www.w3.org/TR/FileAPI/), то есть исключает IE<10.
|
||||
Мы, для примера, рассмотрим загрузку файла с индикацией прогресса. Это требует от браузера поддержки [File API](http://www.w3.org/TR/FileAPI/), то есть исключает IE9-.
|
||||
|
||||
File API позволяет получить доступ к содержимому файла, который перенесён в браузер при помощи Drag'n'Drop или выбран в поле формы.
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
Здесь мы рассмотрим общий подход к организации загрузки, а его уже можно расширять, адаптировать к своему фреймворку и так далее.
|
||||
|
||||
Поддержка -- все браузеры кроме IE<10.
|
||||
Поддержка -- все браузеры кроме IE9-.
|
||||
|
||||
[cut]
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# CSS-анимация
|
||||
|
||||
Все современные браузеры, кроме IE<10 поддерживают <a href="http://www.w3.org/TR/css3-transitions/">CSS transitions</a>, которые позволяют реализовать анимацию средствами CSS, без привлечения JavaScript.
|
||||
Все современные браузеры, кроме IE9- поддерживают <a href="http://www.w3.org/TR/css3-transitions/">CSS transitions</a>, которые позволяют реализовать анимацию средствами CSS, без привлечения JavaScript.
|
||||
|
||||
Большинство примеров из этой статьи не будут работать в IE<10.
|
||||
Большинство примеров из этой статьи не будут работать в IE9-.
|
||||
[cut]
|
||||
|
||||
## Анимация свойства [#css-animation]
|
||||
|
@ -220,7 +220,7 @@ document.body.style.Transform = "rotate(360deg)";
|
|||
|
||||
Самое замечательное -- все эти эффекты используют графический ускоритель и почти не нагружают процессор.
|
||||
|
||||
Все браузеры, кроме IE<10 поддерживают это, ну а в IE может быть что-то через JavaScript или вообще без анимации.
|
||||
Все браузеры, кроме IE9- поддерживают это, ну а в IE может быть что-то через JavaScript или вообще без анимации.
|
||||
|
||||
## Событие transitionend
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
-moz-transform: scaleX(-1);
|
||||
-o-transform: scaleX(-1);
|
||||
-ms-transform: scaleX(-1);
|
||||
filter: fliph; /* IE<10 */
|
||||
filter: fliph; /* IE9- */
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
В других браузерах `setImmediate` нет, но его можно эмулировать, используя, к примеру, метод [postMessage](https://developer.mozilla.org/en-US/docs/DOM/window.postMessage), предназначенный для пересылки сообщений от одного окна другому. Детали работы с `postMessage` вы найдёте в статье [](/cross-window-messaging-with-postmessage). Желательно читать её после освоения темы "События".
|
||||
|
||||
Эмуляция `setImmediate` с его помощью для всех браузеров, кроме IE<8 (в которых нет `postMessage`, так что будет использован setTimeout):
|
||||
Эмуляция `setImmediate` с его помощью для всех браузеров, кроме IE7- (в которых нет `postMessage`, так что будет использован setTimeout):
|
||||
|
||||
```js
|
||||
//+ hide="Раскрыть код" src="setImmediate.js"
|
||||
|
|
|
@ -21,7 +21,7 @@ if (!window.setImmediate) window.setImmediate = (function() {
|
|||
tail = tail.next = { func: func };
|
||||
window.postMessage(ID, "*");
|
||||
} :
|
||||
function(func) { // IE<8
|
||||
function(func) { // IE7-
|
||||
setTimeout(func, 0);
|
||||
};
|
||||
}());
|
||||
|
|
|
@ -21,7 +21,7 @@ if (!window.setImmediate) window.setImmediate = (function() {
|
|||
tail = tail.next = { func: func };
|
||||
window.postMessage(ID, "*");
|
||||
} :
|
||||
function(func) { // IE<8
|
||||
function(func) { // IE7-
|
||||
setTimeout(func, 0);
|
||||
};
|
||||
}());
|
||||
|
|
|
@ -36,12 +36,12 @@
|
|||
|
||||
**Чтобы ничего не загружать в ифрейм, укажите `src="javascript:false"`.**
|
||||
</dd>
|
||||
<dt>Атрибут `name` и создание ифрейма в IE<8</dt>
|
||||
<dt>Атрибут `name` и создание ифрейма в IE7-</dt>
|
||||
<dd>В старых IE нельзя менять атрибут `name` после создания ифрейма:
|
||||
|
||||
```js
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.name = 'iName'; // в IE<8 не сработает
|
||||
iframe.name = 'iName'; // в IE7- не сработает
|
||||
```
|
||||
|
||||
Поэтому, если нужна совместимость, создавайте ифреймы через `innerHTML`:
|
||||
|
|
|
@ -135,7 +135,7 @@
|
|||
<li>Все современные браузеры, включая IE8+, поддерживают специальный интерфейс `postMessage` для общения между окнами с разных доменов. Мы рассмотрим его в отдельной главе [](/cross-window-messaging-with-postmessage).</li>
|
||||
<li>Одно окно может поменять другому `location.hash` -- часть пути после `#`. При этом не произойдёт смены `URL`, но другое окно, увидев это, может прочитать из хэша информацию и, в свою очередь, ответить.
|
||||
|
||||
Этот способ испольуется там, где требуется поддержка IE<8.
|
||||
Этот способ испольуется там, где требуется поддержка IE7-.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
|
|
|
@ -177,7 +177,7 @@ Firefox и старый IE могут активировать designMode на
|
|||
|
||||
### Приостановка показа документа
|
||||
|
||||
Если нужно поддерживать старые браузеры (IE<8), то можно и просто отменить показ документа:
|
||||
Если нужно поддерживать старые браузеры (IE7-), то можно и просто отменить показ документа:
|
||||
|
||||
```html
|
||||
<head>
|
||||
|
@ -243,7 +243,7 @@ Firefox и старый IE могут активировать designMode на
|
|||
|
||||
<ul>
|
||||
<li>Рекомендуется использовать X-Frame-Options на страницах, заведомо не предназначеных для запуска во фрейме и на важнейших страницах (финансовые транзакции).</li>
|
||||
<li>Используйте защиту через framebusting для защиты IE<8, т.к. там не поддерживается X-Frame-Options.</li>
|
||||
<li>Используйте защиту через framebusting для защиты IE7-, т.к. там не поддерживается X-Frame-Options.</li>
|
||||
<li>Используйте перекрывающий DIV, если это допустимо вашим проектом и вы хотите разрешить безопасный показ документа во фреймах с любых доменов.</li>
|
||||
</ul>
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue