Партнерка на США и Канаду по недвижимости, выплаты в крипто
- 30% recurring commission
- Выплаты в USDT
- Вывод каждую неделю
- Комиссия до 5 лет за каждого referral
WIN 201 ILL
Лабораторная работа
Введение в разработку WinRT-приложений на HTML/JavaScript
Содержание
Введение. 3
Упражнение 1: От шаблона к приложению с данными.. 4
Задание 1: Создание приложения из шаблона. 4
Задание 2: Замена источников данных. 4
Упражнение 2: Стилизация приложения. 4
Задание 1: Извлечение картинок. 4
Задание 2: Смена общего стиля. 4
Упражнение 3: Продолжение работы с данными.. 4
Задание 1: Ограничение вывода данных. 4
Задание 2: Проверка интернет-соединения. 4
Задание 3: Делимся информацией.. 4
Выводы.. 4
Введение
Данная лабораторная работа поможет вам создать ваше первое приложение для WindowsStore, работающее с внешними данными и отображающее их на экране в приемлемом виде.
Файлы для упражнений: \\labs-dc1.labs. msteched. ru\share\Windows 8 Lab
Имена инструкторов: Константин Кичинский, Ахмед Шериев
Упражнение 1: От шаблона к приложению с данными
Первое упражнение посвящено созданию простой версии приложения, читающего внешние данные через RSS-каналы на базе стандартного шаблона.
В результате должен получиться работающий прототип приложения, способный показывать новости из нескольких RSS-потоков и отображать их на трех типах страниц: хаб (первая страница), группа и детали.
Откройте VisualStudio 2012, выберите создание нового проекта (File ->New ->Project…). Далее в шаблонах выберите проект на JavaScript ->WindowsStore. Укажите, что будете использовать шаблон GridApp.

Укажите любое название проекта, например, ReaderApp.
Изучите структуру проекта:
1. package. appxmanifest—манифест приложения, описывающий ключевые настройки, используемые возможности, название приложения, плитки и другие параметры;
2. default. html—формальная стартовая страница приложения;
3. pages\groupedItems—папкасhtml-, js - иcss-файлами для страницы представления групп контента (подгружается в стартовую страницу);
4. pages\groupDetail—папка с html-, js - иcss-файлами для страницы отображения группы новостей (записей в rss-потоке), соответствующих одному потоку;
5. pages\itemDetail—папка с html-, js - иcss-файлами для страницы отображения каждой из новостей отдельно;
6. js\data. js—js-файл, описывающий работу с данными (содержит зашитые внутрь демонстрационные данные);
7. js\default. js—описывает события, необходимые для инициализации приложения;
8. js\navigator. js—описывает логику переходов между страницами и необходимые для этого события и объекты;
9. images\logo. png—изображение, используемое для квадратной плитки;
10. images\smalllogo. png—изображение, используемое при перечислении приложения в операционной системе, например, при поиске или выборе приложений для поиска или общего доступа;
11. images\splashscreen. png—загрузочное изображение, показываемое при открытии приложения;
12. images\storelogo. png—изображение, используемое в интерфейсе магазина приложений (WindowsStore).
Также по умолчанию к проекту подключена библиотека WinJS, содержащая наборы стилей для темной и светлой тем и вспомогательных функций и объектов на JavaScript.
Попробуйте запустить приложение, нажав F5, зеленую стрелочку или выбрав Debug ->StartDebugging.

Изучите работу приложения:
· Попробуйте нажать на отдельную серую плитку или на заголовок группы.
· Попробуйте нажать на кнопку назад во внутренних страницах.
· Попробуйте перевести приложение в Snapped-режим.
Вернитесь в VisualStudioи остановите отладку (Shift+F5, красный квадратикили выберите в меню Debug ->StopDebugging).
Откройте файл js\data. js. В нем объявлено несколько важных функций и объектов, которые мы также будет использовать.
Первым делом необходимо избавиться от строчек кода, генерирующих примеры данных. Дляэтогоудалитеследующиестрочки:
1. Вставка данных в список:
// TODO: Replace the data with your real data.
// You can add data from asynchronous sources whenever it becomes available.
generateSampleData().forEach(function(item){
list. push(item);
});
2. Генерация примеров данных:
// Returns an array of sample data that can be added to the application's
// data list.
functiongenerateSampleData(){
varitemContent="<p>Curabitur class … ";
varitemDescription="Item Description: Pellente…";
vargroupDescription="Group Description: Lorem …";
…
returnsampleItems;
}
Если вы запустите приложение, оно продолжит работать, только в нем будут отсутствовать какие-либо данные. Остановите отладку и вернитесь к файлу data. js. Давайте вкратце пройдемся по его структуре, чтобы были понятны дальнейшие действия:
varlist=newWinJS. Binding. List();
1. Создается список, который будет использоваться для связки данных с отображением. В него мы будем заносить те блоки информации, которые хотим вывести на экран.
vargroupedItems=list. createGrouped(
functiongroupKeySelector(item){returnitem. group. key;},
functiongroupDataSelector(item){returnitem. group;}
);
2. На основании списка создается группированная коллекция, при создании которой с помощью специальных функций указывается, как элементы коллекции разделять на отдельные группы.
WinJS. Namespace. define("Data",{
items:groupedItems,
groups:groupedItems. groups,
getItemReference:getItemReference,
getItemsFromGroup:getItemsFromGroup,
resolveGroupReference:resolveGroupReference,
resolveItemReference:resolveItemReference
});
3. Через функцию defineв библиотеке WinJS (Namespace) прописывается глобальный объект Data, который будет доступен из других частей программы для работы с нашими данными. Внутри объекта прописываются ссылки на группированную коллекцию, список групп внутри нее и ряд функций, описанных в файле data. js и используемых для работы с коллекцией и извлечения данных.
4. Оставшиеся 4 функции (getItemReference, getItemsFromGroup, resolveGroupReferenceиresolveItemReference) используются для сравнения объектов, извлечения подмножеств элементов, принадлежащих одной группе, определения группы по ключу и элемента по набору уникальных идентификаторов.
Теперь самое время приступить к добавлению наших собственных данных. В качестве источников мы будет использовать внешние RSS-потоки.
Важно: в ходе данной лабораторной работы в целях упрощения кода для получения данных мы будет использовать только RSS-потоки, однако, добавление поддержки Atom-потоков не должно составить труда, так как они имеют схожую структуру и ключевая разница будет в адресации искомых полей данных.
Вернитесь к началу файла и после строчки "usestrict" опишите блоги, информацию из которых вы будете выводить:
varblogs=[
{
key:"ABlogging",
url:"http://blogs. /windows/b/bloggingwindows/rss. aspx",
title:'Blogging Windows',rsstitle:'tbd',updated:'tbd',
dataPromise:null
},
{
key:"BExperience",
url:'http://blogs. /windows/b/windowsexperience/rss. aspx',
title:'Windows Experience',rsstitle:'tbd',updated:'tbd',
dataPromise:null
},
{
key:"CExtreme",
url:'http://blogs. /windows/b/extremewindows/rss. aspx',
title:'Extreme Windows',rsstitle:'tbd',updated:'tbd',
dataPromise:null
}];
Для описания каждого блога (группы контента) мы указываем:
3. ключ—key (так как сортировка групп будет по ключу, мы также добавили в начале группы латинские буквы для явного задания сортировки — в реальном проекте это можно сделать более элегантным способом),
4. ссылку на RSS-поток— url,
5. название потока— title,
6. несколько заглушек:
a. реальное название блога—rsstitle,
b. дата обновления (updated),
c. указатель наdataPromise— «обещание» загрузить этот поток и его обработать.
Чтобы превратить ссылки в данные на компьютере, информацию по ним необходимо загрузить. Для этого после строчки varlist = newWinJS. Binding. List();добавьте новую функцию getBlogPosts, которая как раз будет заниматься загрузкой:
functiongetBlogPosts(postsList){
blogs. forEach(function(feed){
// Создание Promise
feed. dataPromise=WinJS. xhr({url:feed. url}).then(
function(response){
if(response){
varsyndicationXML=response. responseXML||(newDOMParser()).parseFromString(response. responseText,"text/xml");
processRSSFeed(syndicationXML, feed, postsList);
}
}
);
});
returnpostsList;
}
В данной функции мы в цикле проходимся по всем блогам, для каждой ссылки через функцию WinJS. xhrсоздаем асинхронную Promise-обертку вокруг XMLHttpRequest-запроса и после получения результата (then) передаем полученный ответ на обработку в функцию processRSSFeed, которую мы опишем ниже.
Замечание: для используемых нами блогов нет необходимости в дополнительной проверке, что мы получили ответ в виде XML (наличие responseXML), однако, в общем случае это неверно: некоторые блоги из-за неверных настроек сервера/движка отдают RSS-поток как текстовое содержимое, которое необходимо дополнительно обрабатывать, если мы хотим работать с ним как с XML-файлом.
Для обработки потока добавьте нижу еще одну функцию —processRSSFeed:
functionprocessRSSFeed(articleSyndication, feed, postsList){
// Названиеблога
feed. rsstitle=articleSyndication. querySelector("rss> channel > title").textContent;
// Используем дату публикации последнего поста как дату обновления
varpublished=articleSyndication. querySelector("rss> channel > item >pubDate").textContent;
// Преобразуемдатувудобрыйформат
vardate=newDate(published);
vardateFmt=newWindows. Globalization. DateTimeFormatting. DateTimeFormatter(
"daymonth. abbreviatedyear. full");
varblogDate=dateFmt. format(date);
feed. updated="Обновление: "+blogDate;
// Обработка постов
getItemsFromRSSFeed(articleSyndication, feed, postsList);
}
В данной функции мы пользуемся тем фактом, что на входе имеем XML-файл с известной структурой (RSS 2.0), по которому можно перемещаться используя DOM-модель, в частности, функцию querySelector, используя которую, можно вытаскивать из полученного документа необходимые данные.
Полученное текстовое значение последней даты обновления мы преобразуем в нужный формат, используя функции глобализации, доступные через APIWinRT.
В конце мы передаем документ на дальнейшую обработку в функцию getItemsFromRSSFeed, которая выделяет отдельные посты и заносит их в коллекцию posts.
Добавьтенижеследующуюфункцию:
functiongetItemsFromRSSFeed(articleSyndication, feed, postsList){
varposts=articleSyndication. querySelectorAll("item");
// Цикл по каждому посту в потоке
varlength=posts. length;
for(varpostIndex=0;postIndex<length;postIndex++){
varpost=posts[postIndex];
// форматированиедаты
varpostPublished=post. querySelector("pubDate").textContent;
varpostDate=newDate(postPublished);
varmonthFmt=newWindows. Globalization. DateTimeFormatting. DateTimeFormatter("month. abbreviated");
vardayFmt=newWindows. Globalization. DateTimeFormatting. DateTimeFormatter("day");
varyearFmt=newWindows. Globalization. DateTimeFormatting. DateTimeFormatter("year. full");
vartimeFmt=newWindows. Globalization. DateTimeFormatting. DateTimeFormatter("shorttime");
varpostContent=toStaticHTML(post. querySelector("description").textContent);
varpostItem={
index:postIndex,
group:feed,
// заголовокпоста
title:post. querySelector("title").textContent,
// дата и отдельные компоненты
postDate:postDate,
month:monthFmt. format(postDate).toUpperCase(),
day:dayFmt. format(postDate),
year:yearFmt. format(postDate),
time:timeFmt. format(postDate),
// содержимоепоста
content:postContent,
// ссылканапост
link:post. querySelector("link").textContent
};
postsList. push(postItem);
}
}
В данной функции мы проходимся в цикле по всем постам в полученном потоке, выбирая из XML-описания нужные поля (заголовок, дату публикации, контент и т. п.), после чего собираем нужную информацию в один объект (postItem), который добавляем в список постов.
Обратите внимание на форматирование дат и привязку каждого поста к соответствующей группе. Также заметьте, что для повышения безопасности полученное содержимое поста мы приводим к статическому виду с помощью функции toStaticHTML.
Замечание: в общем случае работы с RSS-потоками из неконтролируемых источников нужно внимательно контролировать (и исследовать) получаемые данные. На практике часть данных по искомым полям может отсутствовать, поэтому прежде, чем извлекать текстовое содержимое (textContent) необходимо убеждаться, что предыдущая операция вернула не null-значение. В некоторых случаях полное содержимое поста может скрываться за элементами encoded или full-text или и вовсе отсутствовать. Также известны случаи, когда сервер отдает дату в неправильном формате, в результате чего стандартный парсер выдает исключение.
Добавьте ниже следующую строчку, чтобы запустить считывание блогов:
list=getBlogPosts(list);
Запустите приложение на отладку:

Как видите, оно уже использует наши новые данные, однако, есть несколько «проблемных» зон, которые необходимо поправить:
· нет картинок,
· в отдельных строчках выводится странное “undefined”,
· на главной странице выводится сразу весь список из потока, а хочется его ограничить несколькими записями.
Этим мы займемся в следующих упражнениях.
Упражнение 2: Стилизация приложения
Во втором упражнении мы займемся внешним видом нашего приложения: добавим картинки, поменяем заголовки, стили, плитки и т. п. Всю работу можно провести в VisualStudio, хотя некоторые вещи удобнее и нагляднее менять в ExpressionBlend.
Первым делом, давайте попробуем вытащить из постов изображения, если они там, конечно, есть. Для этого откройте файл js\data. js и перейдите к функции getItemsFromRSSFeed, занимающейся разбором отдельных постов.
Добавьте перед строчкой “varpostItem = {“следующий код:
// извлечение ссылки на изображение в посте
vartempElement=document. createElement("div");
tempElement. innerHTML=postContent;
varimage=tempElement. querySelector("img");
varimglink=(image!=null)?"url('"+image. src+"')":"";
Здесь мы создаем временный элемент с контентом поста и извлекаем из него первую же картинку, чтобы использовать ее в качестве фоновой на плитках к постам. В случае, если картинки нет, используем пустую строку, которую передадим в соответствующее правило CSS.
Замечание: в данном случае мы можем попасть в ситуацию, когда явной картинки в посте нет, но есть невидимая, применяемая для подсчета числа просмотров. Применительно к конкретным используемым блогам эта картинка прозрачная, поэтому особой роли это не играет, но в общем случае это может быть не так.
Добавьте в объект-описание поста следующие строчки в конце (не забудьте добавить также запятую строчкой выше):
// ссылка на картинку
backgroundImage:imglink
Должно получиться примерно вот так:
varpostItem={
…
link:post. querySelector("link").textContent,
// ссылка на картинку
backgroundImage:imglink
};
Если вы сейчас запустите проект на отладку, вы увидите, что визуально ничего не поменялось.
Откройтефайлpages\groupedItems\groupedItems. html.
Внутри этого файла для описания структуры страницы и связывания данных используются шаблоны. Найдите шаблон элемента, начинающийся строчкой:
<divclass="itemtemplate"data-win-control="WinJS. Binding. Template">
Двумя строчками ниже вы увидите описание картинки:
<imgclass="item-image"src="#"data-win-bind="src: backgroundImage; alt: title"/>
Если вы знакомы с основами HTML, вы наверняка уже догадались, почему в отображении ничего не поменялось: формат, который мы использовали выше, рассчитан на использование в CSS, а не явную вставки ссылки на изображение.
Замечание: одна из причин, почему в данном случае CSS является предпочтительнее, заключается в более гибких настройках отображения и, в частности, наличие возможности манипуляций с изображением, в том числе с сохранением пропорций.
Удалите эту строчку для вставки изображения.
Поднимитесь на уровень выше и замените строчку
<divclass="item">
наследующую:
<divclass="item"data-win-bind="style. backgroundImage: backgroundImage">
Попробуйте запустить приложение на отладку:

Стало лучше, но по-прежнему не очень. Например, как мы и ожидали, в некоторых постах нет изображений — и вместо них мы получили отсутствие картинок или пустые заглушки.
Давайте для таких постов поставим цветной фон. Для этого откройте в той же папке файлgroupedItems. css.
Найдите следующую строчку, описывающую отображение отдельного элемента:
.groupeditemspage. groupeditemslist. item {
ДобавьтевконцеэтогоCSS-правила описание фона:
background-color: rgb(0,204,255);
Дополнительно можно сделать еще несколько манипуляций над фоновым изображением, например, центрировать его:
background-position: 50%50%;
Попробуйте запустить приложение:

Теперь давайте перейдем к исправлению отображения текстового содержимого.
Вернитесь к файлу groupedItems. html и описанию шаблона элемента (itemTemplate). В конце элемента вы найдете описание подзаголовка (subtitle). В нашем случае никакого подзаголовка нет, зато есть дата, поэтому замените эту строчку:
<h6class="item-subtitle win-type-ellipsis"data-win-bind="textContent: subtitle"></h6>
наследующие:
<h6class="item-date win-type-ellipsis">
<spandata-win-bind="textContent: day"></span>
<spandata-win-bind="textContent: month"></span>
</h6>
Если вы попробуете сейчас запустить, вы увидите, что дата куда-то съехала и залезла на заголовок.
Чтобы это поправить, перейдите назад к CSS-файлу. Найдитеописаниеподзаголовка:
.groupeditemspage. groupeditemslist. item. item-overlay. item-subtitle {
-ms-grid-row: 2;
width: 220px;
}
Замените его на соответствующее описание отображение даты:
.groupeditemspage. groupeditemslist. item. item-overlay. item-date {
-ms-grid-row: 2;
width: 220px;
text-transform: uppercase;
text-align:right;
}
В данном случае мы также добавили выравнивание по правому краю и отображение текста в верхнем регистре.
Замечание: обратите внимание, что для позиционирования элементов использует модуль CSS 3 GridLayout. Мы не будем останавливаться на деталях его использования, но если вы планируете создавать приложения для WindowsStore на HTML/JS, рекомендуем хорошо изучить его возможности.
Теперь давайте попробуем сделать заголовок поста побольше и разместить его на всю плитку.
Для начала его необходимо вынести на уровень выше. Перейдите к файлу groupedItems. htmlи внутри шаблона элемента вынесите описание заголовка на уровень выше, добавив обертку. Должнополучитьсяпримернотак:
<divclass="item"data-win-bind="style. backgroundImage: backgroundImage">
<divclass="item-title-container">
<h4class="item-title"data-win-bind="textContent: title"></h4>
</div>
<divclass="item-overlay">
<h6class="item-date win-type-ellipsis">
<spandata-win-bind="textContent: day"></span>
<spandata-win-bind="textContent: month"></span>
</h6>
</div>
</div>
Теперь вернитесь к CSS-файлу. В нем необходимо отобразить изменение иерархии и прописать обновленные стили.
Послеправила.groupeditemspage .groupeditemslist .item { … } добавьте новое:
.groupeditemspage. groupeditemslist. item. item-title-container {
-ms-grid-row: 1;
margin: 10px;
padding: 8px;
opacity: 0.85;
}
Сразу после него перенесите находящееся ниже описание заголовка (.item-overlayнадо заменить на .item-title-container):
.groupeditemspage. groupeditemslist. item. item-title-container. item-title {
overflow: hidden;
width: 220px;
display: inline;
font-size: 1.6em;
line-height: 1.5em;
font-family: 'Segoe UI Light';
background: rgb(145,0,145);
box-shadow: rgb(145,0,145)0008px;
}
Попробуйте запустить проект:

Чтобы убрать подложку, оставшуюся от изначального макета, перейдите ниже по коду в CSS-файле к строчкам:
.groupeditemspage. groupeditemslist. item. item-overlay {
background: rgba(0,0,0,0.65);
}
Замените указанный цвет на transparent.
В качестве еще одной небольшой детали попробуйте самостоятельно увеличить размер текста у даты и поменять шрифт на “SegoeUISemibold” и название приложения на другое:

На этом мы закончим упражнение по настройке внешнего вида. Однако, проделайте следующие шаги, чтобы понять дополнительные изменения, которые необходимо внести:
1. Перейдите внутрь группы и внутрь отдельного блога. Аналогичные действия по изменению внешнего вида необходимо проделать для внутренних страниц.
2. Переведите приложение в Snapped-режим. Здесь также нужно поправить стили с учетом выбранной стилистики.
Стартовый проект для следующего упражнения уже содержит необходимые изменения.
Замечание: в данном проекте мы не меняли тему оформления (по умолчанию используется темная). Тема задается в подключаемом из библиотеки WinJSCSS-файле. Вы легко найдете его в заголовке каждой страницы:
<linkhref="//Microsoft. WinJS.1.0/css/ui-dark. css"rel="stylesheet"/>
Попробуйте поменять dark на light, чтобы увидеть разницу. Обратите внимание, что поменялся не только цвет фона, но и цвет текста и других элементов. В нашем случае это может привести к нежелательным последствиям, так как часть использованных цветов рассчитана на темный цвет фона и белый цвет основного текста.
Упражнение 3: Продолжение работы с данными
В этом упражнении мы решим две имеющиеся в проекте проблемы:
· Слишком большое количество данных на первой странице
· Некорректная работа при отсутствии интернета
Давайте начнем с первой задачи и попробуем ограничить количество данных, выводимых на первой странице.
Особенность данного проекта в том, что, вообще говоря, у нас всегда под рукой все доступные данные. В реальном проекте, особенно если данных много или используется специальный API, скорее всего, имеет смысл загружать данные порционно по мере необходимости. Например, сначала загружать заголовки, а сами статьи только по запросу.
В нашем случае необходимо просто ограничить вывод данных на главной странице. Для этого откройте файл pages\groupedItems\groupedItems. js.
В начале функции в области переменных создайте еще две:
vargroupedItems;
vartilesLimit=6;
В первой мы будем хранить отфильтрованную коллекцию. Вторая указывает, сколько максимум плиток можно выводить.
Далеенайдитеследующуюстрочку:
_initializeLayout:function(listView, viewState){
Эта функция вызывается при инициализации страницы и прописывает, какие данные необходимо отобразить в зависимости от используемого режима отображения. В качестве источника данных используется глобальный объект Data.
Добавьте вначале функции следующие строчки:
groupedItems=Data. items. createFiltered(function(item){
returnitem. index<tilesLimit;
}).createGrouped(
functiongroupKeySelector(item){returnitem. group. key;},
functiongroupDataSelector(item){returnitem. group;}
);
Замечание: в данном случае мы явно ограничиваем количество элементов шестью (tilesLimit), однако, в общем случае это неправильный подход. На большом мониторе количество плиток может оказаться меньше желаемого, к тому же могут появляться одиноко висящие плитки в конце списка. Самое правильное: динамически рассчитывать лимит в зависимости от доступного пространства.
Далее в этой же функции замените встречающиеся ниже ссылки на Dataи Data.itemsна переменную groupedItems:
if(viewState===appViewState. snapped){
listView. itemDataSource=groupedItems. groups. dataSource;
listView. groupDataSource=null;
listView. layout=newui. ListLayout();
}else{
listView. itemDataSource=groupedItems. dataSource;
listView. groupDataSource=groupedItems. groups. dataSource;
listView. layout=newui. GridLayout({groupHeaderPosition:"top"});
}
Замечание: будьте внимательны с другими вхождениями Data на данной странице. В данном случае мы их не изменяем, так как они используются при переходе ко внутренним страницам, а выше мы всего лишь сделали фильтр по данным. Но в общем случае, если вы меняете источник данных, его, возможно, надо менять везде.
Запустите проект:

Следующий важный пункт: убедиться, что приложение корректно себя ведет при отсутствии интернет-соединения. Если вы попробуете запустить текущую версию приложения с отключенной сетью, например, включив Airplane-режим, оно должно вызвать ошибку из-за невозможности скачать нужные поток. (Возможно, они успели закешироваться, поэтому для надежности эксперимента можно подключить какие-нибудь другие потоки.)
Аналогично, если поток окажется недоступным, будет проблема.
Чтобы проверить наличие интернета, откройте файл js\data. js и добавьте в него следующую функцию:
functionisInternetConnection(){
varconnectionProfile=working. workInformation. getInternetConnectionProfile();
return(connectionProfile!=null);
}
ЗдесьмыобращаемсякWinRT, чтобы узнать текущее состояние сети. Это уже хорошая информация, хотя она и не дает 100% гарантии, что доступ к интернету и нужному потоку действительно есть.
Теперь давайте добавим функцию, которая будет выводить сообщение об ошибке при наличии проблем:
functionshowConnectionError(msg, donotexit){
msg=(msg!=undefined)?msg:"";
varmessageDialog=newWindows. UI. Popups. MessageDialog(msg,"Can not connect");
mands. append(newWindows. UI. Popups. UICommand("Ok",null,1));
messageDialog. showAsync().done(function(command){
if(!donotexit&&command. id==1){
MSApp. terminateApp({
number:0,
stack:"",
description:"No internet connection"
});
}
});
}
Данная функция, используя WinRTAPI, выводит заданное сообщение об ошибке и если не выставлен флагdonotexit (или он равен false), завершает приложение.
Замечание: в реальном приложении логика поведения может отличаться. Например, приложение может намеренно кешировать данные или предлагать пользователю попробовать еще раз скачать потоки с сервера, если была временная потеря соединения.
Следующий шаг: запустить проверку наличия соединения, для этого замените строчку
list=getBlogPosts(list);
наследующие:
functiontryUpdateData(){
if(isInternetConnection()){
list=getBlogPosts(list);
}else{
showConnectionError("Please check your internet connection. ");
}
};
tryUpdateData();
Фактически, мы обернули обращение данных в проверку наличия интернет-соединения. Если его нет, приложение выдает сообщение об ошибке и закрывается:

Теперь давайте вернемся к функции getBlogPosts. Здесь тоже есть вероятность получения ошибки, например, если какой-то RSS-поток перестал работать, в этом случае наша обертка над XHRвызовет исключение, которое нужно перехватить.
Попробуйте заменить одну из ссылок на RSSна неправильную и запустить приложение.
Для этого в описании Promiseнужнодобавить функцию, вызываемую при возникновении ошибки. Сразу после внутренней анонимной функции function (response) {…}добавьте через запятую:
function(error){
showConnectionError("Can't get rss updates for "+feed. title+". Usedsource: "+feed. url, true);
}
В данном случае мы выводим сообщение об ошибке, но не закрываем приложение: возможно, другие потоки обработаются нормально.
Попробуйте сделать одну из ссылок неправильной и запустить приложение:

Последнее задание нашей лабораторной работы будет нацелено на то, чтобы добавить поддержку контракта «Общий доступ» (Share) в наше приложение при просмотре отдельных постов.
Откройтефайлpages\itemDetail\itemDetail. js. Добавьте в него ближе к концу (до последних закрывающих скобок) следующие функции:
1. setupSharing
functionsetupSharing(item){
vardataTransferManager=Windows. ApplicationModel. DataTransfer. DataTransferManager. getForCurrentView();
dataTransferManager. ondatarequested=sharingHandler. bind(item);
}
Здесь мы обращаемся через WinRTк менеджеру передачи данных и вешаем обработчик события запроса данных.
2. sharingHandler
functionsharingHandler(e){
varrequest=e. request;
varitem=this;
vartext=item. title;
if(item. link){
text+="\n\r"+item. link;
request. data. setUri(newWindows. Foundation. Uri(item. link));
}
request. data. properties. title=text;
request. data. properties. description="Some awesome news on Windows!";
request. data. setText(text);
}
Здесь мы описываем, какие данные мы передаем приложению-получателю: ссылку, текст и т. п.
Последний штрих: внутри функции ready в самом конце добавьте вызов регистрации на поддержку контракта:
setupSharing(item);
Запустите приложение, перейдите к посту и через панель чудо-кнопок попробуйте передать новость в другое приложение:

На этом наша краткая лабораторная работа закончена. В выводах мы немножко подумаем о том, что осталось за бортом.
Выводы
Давайте еще раз посмотрим на то, что мы сделали в ходе этой не очень сложной лабораторной работы:
1. Начав со стандартного шаблона, мы добавили новые источники данных, подгружаемых асинхроннос помощью функций WinJS.
2. Используя DOMAPI, мы вытащили из RSS-потоков необходимые нам данные и вывели их на экран.
3. Небольшими изменениями в HTML и CSSмы смогли придать неплохой вид страницам.
4. Используя функции WinRT мы добавили поддержку наличия интернета и корректно обработать исключительные ситуации.
5. В несколько строчек кода мы добавили поддержку контракта «Общий доступ».
Если вы были ранее знакомы с разработкой на HTML/JS, наверняка, вам было легко разобраться и почти все было сходу понятно – вы просто можете повторно использовать свои знания, в том числе подключать удобные для вас JS-библиотеки вроде jQuery (в лабораторной работе мы этого не делали).
На выходе мы получили неплохое стартовое приложение. Однако оно еще не готово для публикации в WindowsStore. Как минимум необходимо обновить изображения (у нас по-прежнему, как в стартовом шаблоне везде картинки с крестиками) и зарезервировать имя. Конечно, это в предположении, что у вас уже есть аккаунт в магазине.
Также не лишним будет проверить работу приложения с помощью WACK. Если в ходе тестирования будут выявлены ошибки, это верный признак, что ваше приложение отклонят при сертификации.
Наконец, надо работать над повышением пользовательских качеств:
· добавить поддержку живых плиток, чтобы пользователь не запуская приложение, мог понять, есть ли обновления;
· добавить кеширование, обновление, поиск, печать;
· подумать над другими источниками данных и из отображением (например, видео или свежие твиты из твиттера).
Ну и самое главное: понять кто пользователи данного приложения, зачем оно им и вам, как вовлечь пользователей в постоянное пользование.
Успешных вам приложений!


