HTML5. Часть 2

Новые браузерные API

Работа с историей браузера

Обычно изменение адресной строки браузера может быь связано с переходом на другой URL (по ссылке или с изменением location через JavaScript). History API позволяет менять историю браузера без перезагрузки страницы.

Новую запись можно добавить с помощью вызова:

history.pushState(state,
    title,
    url);

При этом передаются параметры:

Для совместимости с классической навигацией необходимо "слушать" событие popstate объекта window, чтобы корректно обработать нажатие браузерной кнопки "Назад":

window.addEventListener("popstate", function(e) {
    console.log(e);
});

Работа с геолокацией

В HTML5 есть возможность определить географические координаты пользователя с помощью Geolocation API.

Опция доступна только для сайтов, работающих на HTTPS. В целях безопасности у пользователя будет запрошено разрешение на получение его гео-данных.

if ("geolocation" in navigator) {
    navigator.geolocation.getCurrentPosition( function( position, errorCallback, options ) {
        console.log(position);
    });
}

Объект геолокации содержит данные:

Помимо метода getCurrentPosition может быть доступен метод watchPosition, который получает текущие данные и продолжает отслеживать изменение позиции, если пользователь перемещается, возвращая при этом ID точки наблюдения. Удалить точку из списка наблюдения можно с помощью метода clearWatch.

При возникновении ошибки функция обработки ошибки errorCallback получает данные о коде ошибки (error.code) и описании ошибки (error.message).

В третьем необязательном параметре options можно указать дополнительные настройки гео-положения:

var options = {
    enableHighAccuracy: true, // получать более точные данные
    maximumAge : 30000, // время жизни закешированных координат
    timeout: 27000 // время задержки перед принудительным вызовом errorCallback
};

Пример получения гео-данных и отрисовки их на карте.

Локальное хранилище

Для хранения данных о пользователе в браузере, например, токены авторизации и т.д., используются cookie-файлы. Однако хранение информации в cookie не всегда удобно, т.к. они обладают недостатками:

Попытки исправить ситуации предпринимались Adobe Macromedia, контенеры Flash с согласия пользователя могли получить до 100kB памяти для хранения своей информации.

В HTML5 были добавлены объекты localStorage и sessionStorage для сохранения до 5Mb данных. Хранилище использует формат данных ключ-значение, при этом и ключ, и значение должны быть строками. При необходимости хранения объектов их "прогоняют" через JSON.stringify.

var myStr = "string";
var myObj = { prop: "value" };

// сохранение данных
localStorage.setItem("myStr", myStr);
localStorage["myObj"] = JSON.stringify(myObj);

// получение данных
localStorage.getItem("myStr");
localStorage["myObj"];

// удаление данных
localStorage.removeItem("myStr");
localStorage.clear();

Синтаксис работы с sessionStorage такой же, как у localStorage, только данные в нем хранятся до конца сессии, т.е. до закрытия окна браузера.

Содержимое хранилища можно посмотреть в DevTools браузера.

Действия с хранилищем генерируют событие storage объекта window и могут быть перехвачены другим окном браузера. Объект события содержит следующую информацию:

Базы данных в браузере

Хранение в браузере чего-то более сложного чем пары ключ-значение сильно усложняют использование локального хранилища. В коллекциях, хранящихся в виде строк, тяжело производить поиск отдельных элементов. В HTML5 была добавлена поддержка браузерных баз данных, представленных двумя разными API: Web SQL Database и IndexedDB. Рассмотрим пример работы с Web SQL Database.

Основные методы работы с Web SQL Database:

openDatabase("myDataBase", "1.0", "Database Description", 5*1024*1024, function (db) {
    db.transaction(function (tx) {
        tx.executeSql("CREATE TABLE users (id, name, age)");
        tx.executeSql("INSERT INTO users (id, name, age) VALUES (1, 'Ivan', 28), (2, 'Petr', 30)");
        tx.executeSql("SELECT * FROM users", [], function(tx, results) {
            console.log(results);
        });
    });
});

Работа в offline

В HTML5 появилась возможность создавать приложения, работающие оффлайн. С работой оффлайн связаны:

Помимо получения статуса пользователя можно также дать указание браузеру, что текущую страницу нужно кэшировать для обеспечения к ней доступа оффлайн:

<html manifest="/cache.manifest">

Атрибут manifest указывает путь к файлу манифеста, который описывает, что и как нужно кешировать. Необходимо, чтобы для данного файла сервер отправлял заголовок Content-type: text/cache-manifest.

Файл манифеста всегда начинается со строки CACHE MANIFEST и содержит следующие блоки:

Блок CACHE

Содержит список файлов, которые нужно кешировать. Сюда добавляются все дополнительные ресурсы, вроде файлы стилей, скриптов и изображений. Путь к самой странице указывать необязательно, она по наличию атрибута manifest автоматически добавляется в кеширование. Блок CACHE можно не указывать, если все файлы должны кешироваться по уомлчанию.

Блок NETWORK

Содержит список файлов, которые нельзя кешировать. Это могут быть счетчики статистики, скрипты получения динамических данных с сервера и т.д.

Блок FALLBACK

Приложение может состоять из нескольких страниц, но явно кешировать только несколько. Потому есть вероятность того, что находясь оффлайн пользователь попытается запросить (например, перейдя по ссылке) одну из таких незакешированных страниц. Вместо системной страницы "Отсутствует подключение к сети Интернет" в блоке FALLBACK можно указать собственную страницу. При этом в строке сначала указывается, какую маску url надо замещать, а затем - каким файлом замещать.

Примерный итоговый файл манифеста может выглядеть следующим образом:

CACHE MANIFEST
FALLBACK:
/ offline.html
NETWORK:
update.php
CACHE:
/fstk/css/style.css

Drag and Drop

Drag'n'drop — мощный подход пользовательского интерфейса, знакомый любому пользователю Windows. По умолчанию браузер поддерживает перетаскивание для таких элементов, как ссылка, изображение, выделенный текст и т.д. HTML5 позволяет задавать возможность перетаскивания произвольным элементам.

Использование API Drag and Drop начинается с указания атрибута draggable для перетаскиваемых элементов. Процесс перетаскивания генерирует следующие события:

Пример использования Drag and Drop API.

Web Workers

Ввиду однопоточности выполнения JavaScript при запуске "тяжелых" функций страница может "замораживаться". В HTML5 появилась возможность выделять выполнение скриптов в отдельный поток с помощью Web Workers. При этом скрипт выполняется в своей собственной области видимости, а "общаться" с ним можно с помощью сообщений:

// index.html
var worker = new Worker("worker.js");
worker.addEventListener("message", function(e) {
    console.log(e.data);
});
worker.postMessage({data: "some data"});

// worker.js
self.addEventListener("message", function(e) {
    self.postMessage(e.data);
});

Создание экземпляра new Worker запускает скрипт, указанный в качестве параметра, в параллельном потоке. Но если нам необходимо передать скрипту какие-то параметры, то на стороне воркера необходимо так же установить прослушивание событий message от основного скрипта. Данные, переданные в сообщении, доступны в свойстве data объекта события. Для остановки работы воркера используется worker.terminate().

Пример работы Web Worker.