x-ms-webview — это мощный элемент управления, позволяющий встраивать веб-содержимое прямо в пользовательский интерфейс приложения. Этот элемент был доступен XAML-приложениям Магазина Windows начиная с версии Windows 8. В Windows 8.1 мы представили много всяческих обновлений, о которых можно прочитать в статье Сэма Спенсера «Что нового в WebView в Windows 8.1». Как сказано в статье Сэма, одно из крупнейших обновлений — то, что данный элемент управления теперь доступен для приложений, написанных на HTML и JavaScript!
Если вы разработчик приложений на HTML/JS, то x-ms-webview — прекрасный способ добавить в них веб-содержимое. В данной статье мы рассмотрим причины, почему вам захочется обновить свои приложения для использования x-ms-webview. Кроме того, я дам несколько рекомендаций касательно того, как воспользоваться всеми возможностями x-ms-webview.
Зачем мы создали HTML x-ms-webview?
Когда я разговариваю с HTML-разработчиками о новом элементе управления x-ms-webview, их первая реакция обычно такая: «Зачем мне это нужно?» Приложения на JavaScript имеют возможность размещать веб-контент в элементе iframe, так что это хороший вопрос. Но фреймы iframe имеют несколько ограничений, из-за которых встраивание веб-содержимого становится трудоемким, а в некоторых случаях — невозможным. Например:
- Сайты, «вырывающиеся» из фреймов. Многие основные веб-свойства определяют, что они размещены в iframe, и просто не загружаются. x-ms-webview ведет себя как браузер при взаимодействии с содержимым.
- События загрузки документов. В случае с iframe обнаружение окончания загрузки содержимого напоминает либо тактическую игру, либо отдельный вид искусства. Пытаясь использовать postMessage() для определения того, загружено ли содержимое DOM, x-ms-webview предоставляет широкий набор событий, что является неотъемлемой частью разработки приложений.
x-ms-webview устраняет все эти проблемы и предоставляет новые функции, недоступные в iframe:
- Улучшенный доступ к локальному содержимому. Доступ к содержимому папки localstate для загрузки в x-ms-webview. Благодаря этому приложения для чтения электронных книг могут загружать книги из локальной папки.
- Снимки экрана веб-содержимого. Возможность сделать снимок содержимого облегчает обмен содержимым через контракт общих данных.
Итак, отвечая на исходный вопрос, зачем приложениям на HTML и JavaScript нужен webview... Все эти функции означают, что x-ms-webview — это просто лучший способ отображения веб-содержимого в ваших приложениях.
Как выглядит x-ms-webview?
Обратимся к основам: Webview — это HTML-элемент, являющийся частью DOM для приложений на JavaScript. Мы добавляем x-ms- к названию элемента x-ms-webview, обозначая тем самым, что это специальная функция HTML от поставщика (например, x-vendor-feature). Использование этого элемента должно показаться знакомым, потому что его синтаксис схож с iframe.
HTML-элемент
<x-ms-webview id="webview" src="http://www.bing.com"></x-ms-webview>
JavaScript
var webview = document.createElement("x-ms-webview");
Добавление базового элемента управления x-ms-webview на страницу default.html в приложении Windows Store, написанном на JavaScript, выглядит так:
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>WebView</title>
<!-- WinJS references -->
<link href="//Microsoft.WinJS.2.0/css/ui-dark.css" rel="stylesheet" />
<script src="//Microsoft.WinJS.2.0/js/base.js"></script>
1:
2:
3: <script src="//Microsoft.WinJS.2.0/js/ui.js">
1: </script>
2:
3: <!— app references -->
4:
5: <link href="/css/default.css" rel="stylesheet" />
6:
7: <script src="/js/default.js">
</script>
</head>
<body>
<x-ms-webview id="webview" src="http://www.bing.com" width="500px" height="500px"></x-ms-webview>
</body>
</html>
Если просто добавить элемент управления x-ms-webview, его размер по умолчанию составит 100 х 100 пикселей. Вы можете задать ширину и высоту так же, как в случае с iframe, либо использовать CSS-стили для iframe.
Навигация с x-ms-webview
Теперь, когда вы познакомились с элементом управления x-ms-webview и тем, как он загружает содержимое, вы понимаете процесс навигации и можете контролировать происходящее. Одна из часто встречающихся у разработчиков для Windows 8 проблем при внедрении веб-содержимого в приложения — определение момента полной загрузки DOM, чтобы начать управление DOM-объектами или выполнение JavaScript. x-ms-webview поддерживает события путей навигации, а также историю навигации, предоставляя контроль над веб-содержимым, загружаемым в приложение.
Увеличить
Свойства и методы истории навигации
API для работы с навигацией x-ms-webview
navigate() — при вызове этого API вы можете также подписаться на следующие события, которые инициируются во время запроса Navigation:
Название события DOM | Описание |
MSWebViewNavigationStarting | Обозначает начало навигации WebView |
MSWebViewContentLoading | HTML-содержимое загружено и сейчас вставляется в элемент управления |
MSWebViewDOMContentLoaded | Обозначает, что главные элементы DOM закончили загрузку |
MSWebViewNavigationCompleted | Обозначает, что навигация завершена, и все медиаэлементы отображены |
MSWebViewUnviewableContentIdentified | WebView обнаружил, что содержимое не является HTML |
Если на загружаемом сайте есть iframe, то вы можете использовать еще несколько событий, чтобы обнаружить загрузку дополнительного содержимого через iframe:
Название события DOM | Описание |
MSWebViewFrameNavigationStarting | Обозначает, что iframe внутри WebView начинает навигацию |
MSWebViewFrameContentLoading | HTML-содержимое загружено и вставляется в элемент управления iframe |
MSWebViewFrameDOMContentLoaded | Обозначает, что главные элементы DOM закончили загрузку в iframe |
MSWebViewFrameNavigationCompleted | Обозначает, что навигация завершена, и все медиаэлементы отображены в iframe |
История навигации x-ms-webview.
Обнаружить, совершил ли пользователь навигацию внутри x-ms-webview, очень просто с помощью данных свойств и методов.
Свойства:
- canGoBack— возвращает true/false, если элемент управления может вернуться к предыдущим страницам.
- canGoForward— возвращает true/false, если элемент управления может перейти вперед.
Методы:
- goBack()— осуществляет навигацию элемента управления на предыдущую страницу.
- goForward()— осуществляет навигацию элемента управления на следующую страницу.
История навигации JavaScript
HTML
…
<body>
<p>Content goes here</p>
<x-ms-webview id="webview" src="http://t.msn.com"></x-ms-webview>
<div id="webviewNavigationButtons"><button id="goBack" onclick="goBack()" disabled>Back</button><button id="goForward" onclick="goForward()" disabled>Forward</button></div>
</body>
…
CSS
#webview{
width:500px;
height:500px;
}
button{
margin-right:15px;
}
JavaScript
webview.addEventListener("MSWebViewContentLoading", webViewContentLoading);
function webViewContentLoading(e) {
document.getElementById("goBack").disabled = !webview.canGoBack;
document.getElementById("goForward").disabled = !webview.canGoForward;
}
function goBack() {
webview.goBack();
}
function goForward() {
webview.goForward();
}
Источники контента
Теперь, когда мы знаем, что WebView — это простой HTML-элемент, давайте рассмотрим типы содержимого, которые можно загружать в x-ms-webview, и различные методы, доступные для каждого из них.
Увеличить
Изображение, демонстрирующее методы навигации в Интернете и по локальному содержимому
Интернет-содержимое
Чаще всего элемент x-ms-webview используется для интеграции онлайн-содержимого из Интернета. Например, мы разработали для конференции Build 2013 демонстрационное приложение — локальный каталог продуктов, использующий x-ms-webview для обработки заказа пользователя на существующем веб-сайте. Чтобы получить более подробную информацию о приложении, посмотрите выступление Джона Хэйзена (John Hazen) на Build — WebView: Bringing the Web to Your App.
Один из способов загрузки веб-содержимого в x-ms-webview — задание атрибута src в HTML-элементе. Задание атрибута src автоматически вызывает метод navigate()и передает ему строку URI с атрибутами.
<x-ms-webview id="webview" src="http://www.bing.com"></x-ms-webview>
Еще один способ загрузки веб-содержимого — вызов navigate() напрямую. Элемент управления x-ms-webview переходит на веб-сайты и загружает их — даже те, которые обычно не загружаются в iframe.
Примечание. Если атрибут src HTML-элемента задан и при загрузке приложения совершается вызов метода navigate, происходит двойная навигация.
Навигация поддерживает различные протоколы для получения доступа как к веб-, так и локальному содержимому. Примеры JavaScript предоставлены для каждого протокола.
Данная таблица содержит различные URI-схемы, поддерживаемые x-ms-webview. Для получения более подробной информации об этих схемах URI посетите портал MSDN.
Схема URI | Описание |
http:// | Произвольное веб-содержимое |
https:// | Веб-содержимое через Secure Sockets Layer |
ms-appdata:/// | Содержимое, помещенное в локальную папку приложения |
ms-appx-web:/// | Содержимое, которое разработчик включил в пакет приложения, но которое не нужно рассматривать как веб-содержимое. Этот HTML не имеет доступа к Windows RT API |
ms-local-stream:// | Содержимое, загруженное разработчиком в поток памяти |
Навигация по веб-содержимому в JavaScript
// Навигация webview
webview.navigate(new Windows.Foundation.Uri("http://www.msn.com"));
// Навигация к SSL-содержимому
webview.navigate(new Windows.Foundation.Uri(https://www.facebook.com));
Элемент управления navigateWithHttpRequestMessage() позволяет добавлять информацию о HTTP-запросах до навигации. За счет этого сервер получает возможность выполнить действия с запросом, прежде чем вернуть содержимое.
JavaScript — пример с Get
// Создаем URI, описывающий сайт, на который нужно перейти
var siteUrl = new Windows.Foundation.Uri("http://www.msn.com");
// Задаем тип запроса
var httpRequestMessage = new Windows.Web.Http.HttpRequestMessage(Windows.Web.Http.HttpMethod.get, siteUrl);
// Добавляем заголовки для запроса к веб-серверу для проверки кэша
httpRequestMessage.headers.append("Cache-Control", "no-cache");
httpRequestMessage.headers.append("Pragma", "no-cache");
// Навигация WebView с помощью информации из запроса
webview.navigateWithHttpRequestMessage(httpRequestMessage);
JavaScript — пример с Post
// Создаем URI, описывающий сайт, на который нужно перейти
var siteUrl = new Windows.Foundation.Uri("http://www.msn.com");
// Задаем тип запроса
var httpRequestMessage = new Windows.Web.Http.HttpRequestMessage(Windows.Web.Http.HttpMethod.post, siteUrl);
// Задаем данные post
httpRequestMessage.Content = new Windows.Web.Http.HttpStringContent("cookie=abcxyz123");
// Навигация WebView с помощью информации из запроса
webview.navigateWithHttpRequestMessage(httpRequestMessage); webview.navigateWithHttpRequestMessage(httpRequestMessage);
Локальное содержимое
Кроме того, вы можете направить x-ms-webview на локально хранимое содержимое, которое было включено в ваш пакет или загружено в папку local state. Поддержка автономного режима в приложениях обеспечивает оптимальную работу приложения для любых способов взаимодействия пользователя. Наиболее общий сценарий — когда игра должна работать в режиме офлайн.
В других случаях приложению может понадобиться большая производительность при загрузке и отображении содержимого, которую можно достичь только с помощью локального содержимого. Пример подобного сценария — программа для чтения EPUB-файлов. EPUB 3 форматы поддерживают содержимое HTML 5, CSS и JavaScript, которое с легкостью отображается в элементе управления x-ms-webview. Давайте рассмотрим API, которые можно использовать для загрузки локального содержимого в x-ms-webview.
JavaScript — переход к локальному содержимому
//Переход к содержимому, включенному в пакет appx
webview.navigate("ms-appx-web:///localPage.html");
//Переход к содержимому, хранящемуся в каталоге local state
webview.navigate("ms-appdata:///local/MyAppsLocalFolder/local.html");
JavaScript — переход к локальному содержимому
Простой пример, показанный выше, работает, но вы можете воспользоваться следующим примером для создания простого HTML-файла в каталоге local state.
// Переменные для local storage
var applicationData = Windows.Storage.ApplicationData.current;
var localFolder = applicationData.localFolder;
// Пишем локальный HTML-файл
function writeLocalHTMLThenNavigate() {
localFolder.createFolderAsync("MyAppsLocalFolder", Windows.Storage.CreationCollisionOption.openIfExists).then(function (folder) {
localFolder.createFileAsync("MyAppsLocalFolder\\local.html",
Windows.Storage.CreationCollisionOption.replaceExisting).then(function (htmlFile) {
var html = "<!DOCTYPE html><html><head>";
html += "<title>Local HTML Content</title></head>";
html += "<body><h1>Local HTML Content</h1></body></html>";
Windows.Storage.FileIO.writeTextAsync(htmlFile, html).then(function (e) {
document.getElementById("webview").navigate("ms-appdata:///local/MyAppsLocalFolder/local.html");
});
}).done(function () {
console.log("Local.html file created successfully.");
});
})
}
writeLocalHTMLThenNavigate();
Метод navigateToLocalStreamUri() предоставляет возможность перехвата содержимого до его загрузки в элемент управления. Наиболее общий сценарий использования — декодирование локального содержимого перед отправкой вывода в x-ms-webview. IUriToStreamResolver должен быть написан на C#/VB или C++, так что разработчикам JavaScript нужно включить дополнительный тип проекта для использования этих функций. В SDK уже есть готовый пример.
Пример: вызов navigateToLocalStreamUri из JavaScript полагается на лежащий в основе код C#, чтобы выполнить возврат потока. Для ознакомления с полным текстом примера обратитесь к SDK.
JavaScript — переход к потоку
function navigateToStreamWithCSResolver() {
var contentUri = document.getElementById("webview").buildLocalStreamUri("NavigateToStream", "simple_example.html");
var uriResolver = new SDK.WebViewSampleCS.StreamUriResolver();
document.getElementById("webview").navigateToLocalStreamUri(contentUri, uriResolver);
}
navigateToString() — создание и отображение динамического HTML часто встречается в приложениях, которым нужно использовать макет HTML для небольшого фрагмента контента, чтобы быстро отобразить его поверх содержимого или расширить возможности встроенной рекламы.
JavaScript — переход к строковому HTML-содержимому
var strHTML = "<!DOCTYPE HTML>";
strHTML += "<HTML>";
strHTML += "<HEAD><TITLE>NavigateToString() Example</TITLE></HEAD>";
strHTML += "<BODY><H1>HTML markup from a string</H1></BODY>";
strHTML += "</HTML>";
webview.navigateToString(strHTML);
Коммуникации от приложения к WebView
Очень часто бывает так, что приложению нужно связаться с веб-содержимым внутри x-ms-webview, чтобы улучшить удобство использования. Вы можете наладить связь между приложением и веб-сайтом, интегрировав такие функции Windows, как панель приложений, чудо-кнопка «Поиск» или чудо-кнопка «Поделиться», для обмена сообщениями между ними.
Использование метода invokeScriptAsync схоже с вызовом postMessage() в элемент . Приложение всегда может вызвать метод invokeScriptAsync в элементе управления, чтобы выполнить скрипт внутри встроенного содержимого. Однако для встроенного содержимого есть определенные ограничения при отправке сообщений с помощью события MSWebViewScriptNotify в родительский контейнер приложения. Host app to webcontent communication graphic .Изображение с коммуникацией между приложением-хостом и веб-содержимымВ данной
Название события DOM | Описание |
MSWebViewScriptNotify | Данное событие инициализируется, когда страница внутри webview вызывает метод window.external.notify |
В таблице показано, как элемент управления webview передает сообщения в родительское приложение.
Схема URI | MSWebViewScriptNotify |
http:// | Нет |
https:// | Да* |
ms-appdata:/// | Нет** |
ms-appx-web:/// | Да |
ms-local-stream:// | Да |
*Только если ContentURI заданы в Package.appxmanifest **Может использовать UriResolver для подключения ScriptNotify | |
webview.addEventListener("MSWebViewScriptNotify", scriptNotify);
function scriptNotify(e) {
// Проверка URI, посылающего оповещение
if (e.callingUri == "https://myUri.com") {
doSomething(e.value);
}
}
JavaScript
var operation = webview.invokeScriptAsync("startAnimation", "500");
operation.oncomplete = function (e) {
console.log(e.target.result);
};
operation.start();
Взаимодействие с содержимым x-ms-webview
Увеличить
Изображение демонстрирует вызов метода capturePreviewToBlogAsync для вывода изображения
Теперь вы можете получить снимок содержимого внутри x-ms-webview, встроенного в API. не может отображать произвольный HTML в виде растрового изображения. Однако метод <a href="http://msdn.microsoft.com/en-us/library/windows/apps/dn301835.aspx"> < strong>capturePreviewToBlobAsync()</strong></a> элемента x-ms-webview позволяет получить изображение. <strong>JavaScript</strong>
var operation = webview.capturePreviewToBlobAsync();
operation.oncomplete = function (e) {
var url = window.URL.createObjectURL(e.target.result);
document.getElementById("imagetag").src = url;
};
operation.start();
Увеличить
Изображение демонстрирует, как выделенный HTML (текст + изображение) выводится в главное приложение
Вы можете с легкостью обмениваться содержимым из элемента управления x-ms-webview с помощью контракта«Общий доступ Windows». Встроенный API может извлекать содержимое, выбранное пользователем. Это содержимое затем может быть возвращено в ваше приложение для передачи другим приложениям, поддерживающим контракт получателя данных.
JavaScript — получение выбранного пользователем содержимого
var operation = webview.captureSelectedContentToDataPackageAsync();
operation.oncomplete = function (e) {
// Проверка, допустимо ли выделение
if (e.target.result) {
var data = e.target.result.getView();
if (data.contains(Windows.ApplicationModel.DataTransfer.StandardDataFormats.html){
// Данные содержат HTML, так что берем его!
data.getHtmlFormatAsync().then(function (htmlFormat) {
var htmlFragment = Windows.ApplicationModel.DataTransfer.HtmlFormatHelper.getStaticFragment(htmlFormat);
document.getElementById("output").innerHTML = htmlFragment;
});
}
}
};
operation.start();
Хотите узнать больше?
Как вы видите, элемент x-ms-webview — это мощный инструмент для отображения веб-содержимого в приложениях на HTML и JS. Если у вас уже есть приложение для Windows 8, использующее iframe для встраивания веб-содержимого, я очень советую обновить его и перейти на x-ms-webview в Windows 8.1. А если вы только начинаете создавать приложение, обязательно воспользуйтесь элементом x-ms-webview с самого начала.
Если вы хотите узнать больше об элементе x-ms-webview, посетите следующие замечательные ресурсы:
- Документация:
- Образцы кода:
- Выступление на Build:
- Другие блоги: