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:
- Другие блоги: