wtorek, 28 sierpnia 2012

WinJS na żywo - odc.2 (m.in przestrzenie nazw, then/done, syndykacja)

W tym odcinku poruszę kilka zagadnień, które były przydatne przy realizacji wyszukiwania filmów na YouTube. 

Przy pisaniu większej ilości kodu, dobrze jest go sobie jakoś zorganizować. WinJS oferuje pomocnicze metody m.in do definiowania przestrzeni nazw i klas. Przy tak prostej funkcjonalności pobrania danych AtomPub i ich sparsowania z klas nie miałem potrzeby na razie korzystać, natomiast w odrębnych plikach w osobnych przestrzeniach nazw zawarłem sobie m.in logikę do komunikacji z YouTube. Definiowanie przestrzeni to w sumie nic innego jak stosowanie wzorca module. Przykładowo może to wyglądać następująco:

function searchVideos(queryText) {

}

WinJS.Namespace.define("YouTube", {
        searchVideos: searchVideos
});

Asynchroniczność jest domeną programowania w Windows 8. Interfejsy WinRT pod C# są widziane w postaci .NET-owego async, a jak jest w Java Scripcie?  Tutaj WinRT przyjmuje postać konstrukcji then/done, co jest znajome dla użytkowników jQuery oraz jest implementacją propozycji Common JS Promises/A. Najbardziej w tym wszystkim podoba mi się możliwość tworzenia łańcuchów z then. Czym się różni then od done? M.in tym, że then zwraca promise, done już undefined. Po done nie można już dalej ciągnąć łańcucha…

Na poniższym screenshocie funkcja searchVideos jest asynchroniczna, wywołuje w sobie asynchroniczną metodę retrieveFeedAsync z klienta syndykacji WinRT. Po jej poprawnym wykonaniu wykonuje się funkcja w then, która przetwarza otrzymany rezultat.

Mała dygresja - klient syndykacji wymaga obiektu Uri, przy przekazaniu samego stringa dostaniemy wyjątek.

jstube_5

Nie będę się rozpisywał na temat przetwarzania elementów syndykacji, odpowiednie przykłady można znaleźć choćby w MSDN. Powstało trochę kodu by wyłuskać odpowiednie potrzebne informacje. W C# stosowałem często znaną z Linq extension metodę FirstOrDefault z podaniem warunku. W gołym JS w standardzie ECMA Script 5 mamy trochę metod pomocniczych do tablic, ale dokładnie czegoś takiego nie odnalazłem. Posiłkowałem się tutaj metodą find z biblioteki Underscore, co zaowocowało przykładowo taką linijką kodu:

var group = _.find(item.elementExtensions, function (node) {
                return node.nodeName === "group" && node.nodeNamespace === mediaNamespace;
            });

Biblioteka jest prosta w użyciu, działają podpowiedzi IntelliSense, można ją zdecydowanie polecić.

Kolejnym zagadnieniem okazała się obsługa pola tekstowego. Chciałem by podobnie jak w C# wyszukiwanie uruchamiało się przy zmianie tekstu z pewnym opóźnieniem czasowym przy wpisywaniu liter. Input tekstowy ma zdarzenie “change”, ale wyzwalane jest ono dopiero po utracie focusa przez kontrolkę. Nowe przeglądarki (a także engine JS natywnej aplikacji wspólny z IE10) obsługują też zdarzenie “input”, które jest wyzwalane przy każdej zmianie tekstu bez potrzeby opuszczania kontrolki. Dodatkowo dodałem tutaj timer. Całościowo przybrało to taką postać:

var searchInput = document.getElementById("search");
            var timer = null;
            searchInput.addEventListener("input", function () {
                if (timer === null) {
                    timer = setTimeout(function () {
                        timer = null;

                        YouTube.searchVideos(searchInput.value).then(function (data) {
                            listView.itemDataSource = null;
                            var list = new WinJS.Binding.List(data);
                            listView.itemDataSource = list.dataSource;
                        });

                    }, 500);
                }                             
            });

Przy okazji mała dygresja - do zmiany elementów w kontrolce ListView potrzebny jest pokazany kod. Samo przypisanie nowej listy nie odświeża. Możemy już cieszyć się ekranem przedstawionym poniżej:

jstube_6

Na koniec obsłużmy przycisk ze “strzałką w dół”. W tym miejscu chcemy przekazać dane z zaznaczonych elementów ListView do metody rozpoczynającej pobieranie i powrócić do strony startowej. Możemy zrealizować to w następujący sposób:

document.getElementById("cmdDownload").addEventListener("click", function () {
                listView.selection.getItems().done(function (items) {
                    var dataArray = _.map(items, function (item) { return item.data; });
                    Download.startDownload(dataArray);
                });               
                WinJS.Navigation.navigate("/pages/start/start.html");
            });

Na dziś koniec. Stay tuned…

niedziela, 26 sierpnia 2012

WinJS na żywo - odc. 1 (Wstęp & Blend)

Po napisaniu prototypu aplikacji pobierającej clipy z YouTube w C# na Windows 8 (a także ostatnio na WP*), postanowiłem przepisać to co już powstało na WinJS w Windows 8. Przeglądałem jakiś czas temu niemal całą dokumentację msdn na ten temat, ale myślę, że jednak najlepiej pobawić się w praktyce. W międzyczasie przyswoiłem pewną ilość wiedzy na temat samego HTML5, JavaScript, CSS3, jQuery, Knockout oraz innych nowych standardów i frameworków dla aplikacji Web, więc teraz to spojrzenie na WinJS będzie myślę bardziej dojrzałe. Jako, że zawsze bardzo lubiłem narzędzie Blend, więc również i tym razem będę go używał.

Trzecią część tryptyku rozpocząłem od stworzenia nowego projektu z dwiema stronami z przykładowymi danymi, z których drugą przedstawiam poniżej:

jstube_1

Zaraz, zaraz czy takiego screenshota już tutaj nie było? Owszem, jak ktoś przepatrzy historię, to może znaleźć nawet taki z tymi samymi zdjęciami (gdy używałem na początku w C# przykładowych danych, były takie same).

mks_01_C 

Aplikacje w C# i w HTML5 na WinRT nie różnią się wizualnie ani zachowaniem, co świadczy o sporym postępie jeśli chodzi o wykorzystanie technologii Web do pisania natywnych aplikacji.

Teraz parę słów o Blendzie. Nie będę pisał kolejnego tutoriala, jak obsługiwać w nim HTML, JS i CSS, można znaleźć to wszystko w sieci. Ze swojej strony mogę powiedzieć, że jeśli ktoś zna Blenda pod XAML, to tutaj trzeba… chwilki czasu, by się oswoić. Twórcy postanowili odzwierciedlić HTML i CSS takimi jakimi są, bez upiększeń, nie mamy w zasadzie żadnej abstrakcji. Na początku może nam brakować pewnych paneli aplikacji jakie znamy z XAML, ale w miarę używania poczujemy bardzo dużą wygodę korzystania mimo odmiennej filozofii działania. Bardzo wiele rzeczy można zrobić z poziomu designera czy wykorzystując inne pomocnicze narzędzia. W pewnej mierze jest to wzorowane na narzędziach z przeglądarek webowych czy narzędziach dla aplikacji Web w Visual Studio 2012, ale część mechanizmów znanych z Blenda dla XAML zostało tutaj osadzonych.

Zwrócę teraz uwagę na kilka wybranych rzeczy. Layout odpowiadający Grid-owi z XAML, możemy robić … tak samo. Jest to zasługą specyfikacji Grid Layout w CSS3 (szkoda że przy “otwartych” aplikacjach webowych to zagadnienie jest bardziej złożone z uwagi, że na razie chyba jedynie IE10 implementuje ten standard). Na razie używałem grid i flex w paru miejscach… Na screenshocie grid w AppBar z niestandardową zawartością… (btw AppBar pod WinJS jest na większym poziomie organizacyjnym, ma też wygodniejszą obsługę z poziomu Blenda).

jstube_2

Warto powiedzieć, że w designerze wykonuje się kod JS na żywo, z reguły do obserwowania zmian automatyczne odświeżanie jest wystarczające. Z dużą łatwością ustalimy, dlaczego np. dany element ma taki kolor a nie inny. Widzimy jakie reguły CSS z jakich plików odnoszą się do danego elementu, która reguła zwyciężyła, jakie wartości są ostatecznie wyliczane.

jstube_3

Przy okazji mała dygresja na temat gwiazdek. W C# użyłem dla celów demonstracyjnych jedynie napisu, w WinJS mamy kontrolkę Rating, której parametr pozwoliłem sobie zbindować. Trochę też ją przestylowałem, pomniejszając nieco gwiazdki i zmieniając im kolor… Miałem tutaj chwilkę na wyczajenie jednego parametru z layoutu flex. Kontrolka mi się niepotrzebnie rozciągała horyzontalnie, nawet wbrew innym ustawieniom. Pomogło ustawienie w stylu dla gwiazdki ms-flex: 0 0 auto …

Koniecznie należy wspomnieć o przycisku ze “strzałką z kreseczkami” nad prawą górną krawędzią designera. Otwiera nam okno trybu interaktywnego, w którym możemy coś zrobić w naszej aplikacji, a potem wrócić z powrotem wrócić do designera. Mi się to bardzo przydało, gdy edytowałem wygląd zaznaczonego elementu.

jstube_4

W przeciwieństwie do kontrolki z C# zamiast docelowego wyglądu, jaki chciałem osiągnąć w WinJS zastałem domyślnie niewidoczne obramowanie oraz check z przezroczystym tłem przy domyślnej zmianie tła całego elementu na niebieski. Taki styl spotkamy w części wbudowanych aplikacji np. Skydrive. Wszędzie tam stawia się na mały obrazek, jakiś napis i przezroczyste tło, które zmieni kolor. Mi jednak bardziej pasowało by to obrazek był tłem, chciałem więc mieć wygląd taki jaki jest domyślny w C# i … trochę mi to zajęło. Ponieważ nie jest to takie oczywiste więc podam sposób, w jaki osiągnąłem pomarańczową ramką i check w pomarańczowym trójkącie.

Pomarańczowa ramka: ramka … już jest, wystarczy zmienić tylko jej kolor definiując regułę nadpisującą (u mnie były takie zagnieżdżenia jak poniżej, w każdym razie należy zwrócić uwagę na zagnieżdżenie klas .win-selected .win-selectionborder w kontrolce ListView):

.addnewvideospage .groupeditemslist .win-selected .win-selectionborder {
                background-color: #D8512B;   
            }

Z pomarańczowym trójkątem było już gorzej, bo po zmianie koloru tła elementu z checkiem w kontrolce okazał się … prostokątem. Posiłkując się stronami w sieci na temat otrzymywania figur z bordera (np. http://css3shapes.com/, http://www.howtocreate.co.uk/tutorials/css/slopes), ustawiłem regułę:

.addnewvideospage .groupeditemslist .win-selected .win-selectioncheckmarkbackground {
                width: 0px;
                border-top: 20px solid #D8512B;
                border-right: 20px solid #D8512B;
            }

Teraz mała dygresja o tym, jak zrobiłem formatowanie daty. W XAML był to konwerter do bindingu (w przeciwieństwie do Silverlight nie ma StringFormat), w WinJS też mamy podobną koncepcję. Definiujemy funkcję w JavaScript:

var formatDate = WinJS.Binding.converter(function (date) {       
        var dateTimeFmt = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter("{day.integer(2)}/{month.integer(2)}/{year.full}‎ {hour.integer(2)}: {minute.integer(2)}");
        return dateTimeFmt.format(date);
    });

Rejestrujemy ją w przestrzeni nazw (w sumie jest to jakaś implementacja w WinJS jednego z polecanych wzorców projektowych dla JS):

WinJS.Namespace.define("Data", {
        formatDate: formatDate, …
});  

W data bindingu po ścieżce dopisujemy zdefiniowaną funkcję konwertującą:

<h6 class="item-subtitle" data-win-bind="textContent:pubDate Data.formatDate"></h6>

Inną małą dygresją jest wyświetlanie automatyczne wyświetlanie … w przypadku, gdy napis okaże się za długi. W XAML czy Silverlight był na to parametr w TextBlock, w HTML na Windows 8 wystarczy użyć predefiniowanej klasy win-type-ellipsis np.

<h4 class="item-title win-type-ellipsis" data-win-bind="textContent: title"></h4>

W sumie to nasunął mi się jeden komentarz odnośnie data bindingu w WinJS po tych dwóch dygresjach. Używa data-* więc jest zgodny z HTML5 i przypomina Knockouta.

Wiadomo, nie opiszę wszystkiego-;)  Myślę że jak na ten post to już wystarczy.

Ciąg dalszy nastąpi.

wtorek, 21 sierpnia 2012

Windows 8 na Slate - krótka relacja

Tematyka uruchamiania i debugowania aplikacji Windows 8 na zdalnym urządzeniu nie jest nowa. Niemniej jednak postanowiłem zrobić małe podsumowanie na ten temat przy okazji ukazania się finalnej wersji Windows 8.

By cieszyć się aplikacją uruchomioną na slacie musimy najpierw zainstalować na nim Windows 8. Proces zasadniczo nie różni się od PC, z tym że tutaj nie mamy napędu DVD i potrzebujemy zrobić sobie bootowalne USB. Ostatnio z powodzeniem wykorzystałem opis potrzebnych czynności ze strony How to Create Windows 8 Bootable USB Device from ISO Image using WinUSB Maker. Mając  bootowalne USB, ustawiamy w BIOS-ie kolejność bootowania, tak by pierwszym urządzeniem był nasz pendrive (przez USB podłączamy wcześniej klawiaturę). Minimalna rozdzielczość dla aplikacji Metro w Windows 8 to 1024 x 768. Jeśli ktoś ma starszy sprzęt, który obsługuje maksymalnie 1024 x 600, to pomóc może edycja rejestru. Ten sposób zadziałał mi także dla finalnej wersji Windows. Oczywiście lepiej jest mieć nowe urządzenie stworzone specjalnie dla Windows 8 (np. Microsoft Surface).

Aby debugować zdalnie na tablecie aplikacje Metro, wystarczy zainstalować na nim Remote Tools for Visual Studio 2012 (w zależności od środowiska na tablecie wybieramy wersję x86, x64 lub ARM, w moim przypadku było to x64). W dalszej kolejności potrzebujemy:

  • wygenerować deweloperską licencję dla tableta - w tym celu wpisujemy w jego konsoli PowerShell polecenie Show-WindowsDeveloperLicenseRegistration (dostajemy wtedy okno generowania licencji  znane zapewne już wszystkim z Visual Studio 2012)
  • uruchomić na tablecie Remote Debugging Monitor (aplikacja z ikoną trójkąta po instalacji Remote Tools)

Nasz tablet jest już w zasadzie gotowy. Teraz jedynie powinien … być widoczny dla maszyny, na której budujemy aplikacje. Komunikacja między nimi może odbywać się za pomocą sieci Ethernet w Intranecie lub poprzez bezpośrednie połączenie ich kablem Ethernet, przy użyciu adapterów dla USB przy braku gniazda Ethernet w urządzeniu mobilnym. W moim przypadku komputer z Visual Studio i slate’a umieściłem w tej samej sieci lokalnej, slate komunikował się bezprzewodowo za pomocą Wi-Fi. Na maszynie deweloperskiej wystarczy teraz w Visual Studio wybrać debugowanie na zdalnej maszynie. Pojawia się okno, w którym możemy ręcznie skonfigurować połączenie lub po prostu wybrać jedno z wykrytych urządzeń. W moim przypadku wyglądało to tak:

win8_rem1

Możemy już teraz zdalnie debugować aplikację na tablecie (wgrywana jest tam automatycznie)

WP_000037 WP_000052

Więcej informacji na powyższe tematy możemy znaleźć na MSDN:

niedziela, 19 sierpnia 2012

Windows 8 RTM & Visual Studio 2012 RTM - pierwsze wrażenia

W ostatnich dniach ukazały się Windows 8 w wersji finalnej dla deweloperów (kompilacja 9200) oraz finalne Visual Studio 2012 (wraz z finalnym .NET 4.5). Dziś parę zdań na ich temat.

Linki do pobrania wszystkiego (systemu i wszystkich narzędzi) zostały umieszczone na stronie Downloads for Metro style app development. Jeśli chodzi o podstawowe narzędzia, czyli Visual Studio 2012 z Blendem, to oprócz domyślnej wersji Visual Studio Express 2012 for Windows 8, można też korzystać z jednej z wersji Visual Studio 2012.

win8_rtm

Jeśli chodzi o sam Windows, to w stosunku do wcześniejszych wersji mamy inną domyślną kolorystykę, znacznie ładniejsze tapety na pulpit i na lock screen (nie widziałem tego rysunku już gdzieś na jakiejś konferencji MS?) oraz możliwość konfigurowania tapet i kolorystyki ekranu startowego. W aplikacjach też można zauważyć różne zmiany w designie i w funkcjonalnościach…

image

Jeśli chodzi o Visual Studio 2012, to można zauważyć, że zgodnie z ostatnią polityką odchodzenia od terminu Metro, projekty aplikacji dla Windows 8 znajdują się obecnie pod kategorią “Windows Store”. Inną ciekawostką jest nie działający jeszcze link do doinstalowania Windows Phone 8 SDK pod kategorią Windows Phone. Blend for Visual Studio 2012 zawiera jedynie projekty dla Windows 8.

Jeśli chodzi o migrację aplikacji z wersji Release Preview na RTM, to są to niewielkie zmiany. Całość opisuje Migration guide. Najwięcej stosunkowo zmian zaszło w API pod C++ i JS. Ja swoją aplikację w .NET już zmigrowałem, działa!

środa, 15 sierpnia 2012

Nowe WP* -;)

Pozwolę sobie na jeden tajemniczy post, taki w stylu Paula Thurrotta, wczesnego Justin Angela i im podobnych ekip, a nawet bardziej mroczniejszy.

Jak pewna, całkiem niemała, część świata rzuciłem okiem na nachodzący WP*. Wiem już - jak myślę - prawie wszystko o WinPRT oraz nowych funkcjonalnościach systemu i API, ale jakoś się… powstrzymam przed rozpowszechnianiem tych informacji. Zresztą wiele z nich można odnaleźć już na różnych stronach w sieci…

Dziś tylko bardzo ogólnie o kilku rzeczach, które mi wyszły podczas zabawy ze swoim prototypem aplikacji do odtwarzania klipów wideo z Youtube na tę platformę. Ogólnie starałem się przenieść to, co możliwe ze szkicu podobnej aplikacji dla Windows 8, ale jest to też kompozycja sama w sobie z uwzględnieniem podejść typowych dla samego Windows Phone i Windows Phone 8.

Miałem dwie zagadki do rozwiązania w tym wczesnym wydaniu. Jedna dotyczyła struktury folderów przy jednoczesnym korzystaniu z IsolatedStorage API oraz WinRT API. Dane tworzone za pomocą pierwszego API - jak się okazywało - trafiały do podfolderu  IsolatedStore. Więcej czasu zeszło nad podaniem Uri do rejestrowania pliku z komendami głosowymi (wyszły tu chyba jakieś przejściowe niezgodności między starym i nowym API). Ale obszedłem to ładując plik StorageFile za pomocą WinRT API i przekazując do metody rejestrującej komendy wartość jego property Path.

Aha, ponieważ “My movies” jakoś lepiej mi się wypowiadało, niż “My tube”, więc takimi słowami zwracam się do mojej aplikacji przed wydaniem jej polecenia. Mogłem wybrać także język polski, ale z uwagi na zdalny serwis wybrałem en-US.