Condividi tramite


Il presente articolo è stato tradotto automaticamente.

HTML5

Sviluppo di applicazioni HTML5 per Windows Phone Apps con Apache Cordova

Colin Eberhardt

Scaricare il codice di esempio

Questo articolo presenta Apache Cordova, un framework per la creazione di applicazioni mobile multi-piattaforma usando HTML5 e JavaScript e mostra come può essere utilizzato per sviluppare applicazioni per Windows Phone.

Windows Phone e la sua piattaforma di sviluppo nativo consentono di creare applicazioni in stile Metro belle con facilità.Con la recente partnership di Nokia, Windows Phone sta iniziando a trovare la sua strada nelle tasche sempre di più.

Recenti dati pubblicati dalla ricerca studio di Gartner Inc.predice un futuro promettente per il sistema operativo Microsoft (bit.ly/h5Ic32), con significativo quota di mercato in un mercato frammentato.Se si sta sviluppando un'applicazione smartphone, questa frammentazione del mercato significa che si che sia necessario scegliere quale OS di destinazione o scrivere la stessa applicazione più volte utilizzando la vasta gamma di lingue questi telefoni richiede (c#, Java e Objective-C).

Tuttavia, c'è un altro modo.Tutti questi smartphone hanno un browser altamente capace, in molti modi più capaci di loro controparti desktop, dove alcune persone usano ancora arcaica browser!Moderni smartphone consentono di creare applicazioni che vengono eseguite all'interno del browser utilizzando una combinazione di HTML5, JavaScript e CSS.Con queste tecnologie è potenzialmente possibile scrivere una singola applicazione basata su browser che attraversa una vasta gamma di dispositivi smartphone.

Introduzione di Apache Cordova

È possibile creare un'applicazione mobile HTML5 creando una pagina Web pubblica con contenuto JavaScript e HTML5 e dirigere le persone all'URL host.Tuttavia, ci sono un paio di problemi con questo approccio.Il primo è il modello di distribuzione attraverso negozi e mercati on-line.Voi non può presentare l'URL che ospita la vostra Web app per un mercato, così come esso si monetizzare?Il secondo problema è come accedere hardware del telefono cellulare.Non ci sono nessun browser ampiamente supportato le API per l'accesso ai contatti del telefono, le notifiche, telecamere, sensori e così via.Apache Cordova (appena Cordova in seguito per brevità) è un framework open source e gratuito che risolve entrambi questi problemi.

Cordova ha iniziato la vita come PhoneGap, che è stato sviluppato da Nitobi.In ottobre 2011 Nitobi è stata acquisita da Adobe Systems Inc., con il quadro PhoneGap sta open-source sotto Apache Software Foundation e rinominato come Cordova.Questa transizione è ancora in corso.

Cordova fornisce un ambiente per l'hosting del tuo contenuto HTML5/JavaScript all'interno di un sottile wrapper nativo.Per ogni smartphone OS, che utilizza un controllo browser nativo per rendere i contenuti dell'applicazione, con le attività di applicazione è fornito in bundle nel distribuibile.Con Windows Phone, i vostri beni HTML5 sono confezionati all'interno del file XAP e caricati archiviazione isolata quando si avvia l'applicazione di Cordova.In fase di esecuzione un controllo WebBrowser esegue il rendering di contenuto ed esegue il codice JavaScript.

Cordova fornisce anche un set di API standard per l'accesso alla funzionalità che è comune attraverso diversi smartphone.Alcune di queste funzionalità includono:

  • Eventi del ciclo di vita dell'applicazione
  • Archiviazione (archiviazione locale HTML5 e basi di dati)
  • Contatti
  • Macchina fotografica
  • Geolocalizzazione
  • Accelerometro

Ognuna delle funzionalità precedente viene esposto come un Java­Script API, che essere utilizzata dal codice JavaScript.Cordova fa tutto il lavoro duro coinvolto nel fornire la necessaria implementazione nativa, garantendo che lavorare contro le stesse API JavaScript, indipendentemente dal telefono OS il codice è in esecuzione su, come illustrato nella Figura 1.

Cordova Allows the Same HTML5 Application to Run Across a Range of Mobile OSesFigura 1 Cordova consente all'applicazione di HTML5 stesso di imbattersi in una gamma di Mobile sistemi operativi

La maggior parte di questo articolo discute Cordova dal punto di vista di uno sviluppatore di Windows Phone, dove lo sviluppo avviene all'interno di Visual Studio e testare l'applicazione su emulatore o un dispositivo fisico.Mentre Cordova è una tecnologia multi-piattaforma, tipicamente sviluppare utilizzando vostro editor o IDE di scelta, quindi uno sviluppatore di iOS sarebbe sviluppare un'applicazione di Cordova in Xcode e sviluppatori di Android molto probabilmente sarebbero utilizzare Eclipse.

Cordova dispone anche di un servizio basato su cloud generazione chiamato Build (build.phonegap.com), dove è possibile inviare il tuo contenuto HTML5/JavaScript.Dopo un breve periodo restituisce distribuzioni per la maggior parte delle piattaforme supportate da Cordova.Questo significa che non dovete avere copie delle varie piattaforme specifiche Idi (o un computer Mac) al fine di costruire la tua applicazione per una vasta gamma di piattaforme.Il servizio di compilazione è di proprietà di Adobe ed è attualmente in versione beta e gratis da usare.Rimarrà gratuito per progetti open source.

Acquisire gli strumenti

Si presume che si dispone già di Visual Studio, il Windows Phone SDK e (facoltativamente) Zune istituito per lo sviluppo di Windows Phone.Se no, si possono ottenere gli strumenti gratuitamente scaricando Visual Studio 2010 Express per Windows Phone (bit.ly/dTsCH2).

È possibile ottenere i più recenti strumenti di sviluppo Cordova dal sito Web di PhoneGap (phonegap.com), anche se le versioni future saranno distribuite tramite Apache (incubator.apache.org/cordova).Il download include i modelli, le biblioteche e gli script necessari per sviluppare applicazioni di Cordova attraverso tutte le piattaforme supportate.Ti consigliamo di utilizzare la versione Windows Phone, naturalmente.

Dopo aver scaricato gli strumenti di Cordova, seguire la guida introduttiva ottenere di Windows Phone (phonegap.com/start#wp) e installare il modello di Visual Studio.Creazione di un "Hello World"-stile applicazione è semplice come la creazione di un nuovo progetto basato sul modello fornito, come mostrato nella Figura 2.

Cordova for Windows Phone Includes a Visual Studio TemplateFigura 2 Cordova per Windows Phone include un modello di Visual Studio

Se costruire e distribuire il progetto creato con il modello a vostro emulatore, si dovrebbe salutati con il messaggio "Ciao Cordova," come mostrato in Figura 3.

The Cordova Template Application Running on an EmulatorNella figura 3 Cordova modello applicazione in esecuzione su un emulatore

L'anatomia di una domanda di Cordova Windows Phone

Anche se è possibile sviluppare un'applicazione di Cordova senza molta conoscenza del funzionamento sotto il cofano, vale la pena di capire quali sono i vari file generati dal modello, come mostrato nella Figura 4.

The Cordova Template Folder StructureFigura 4 la struttura di cartelle del modello di Cordova

Concentrandosi solo sui file Cordova in Figura 4 (dall'alto in basso), notare quanto segue:

  • GapLib/WP7CordovaClassLib.dll è l'Assemblea di Cordova.Questa contiene l'implementazione nativa del Windows Phone delle API di Cordova.
  • www è la cartella dove si posiziona il tuo patrimonio di applicazione, HTML5, JavaScript, CSS e immagini.Il modello genera un file index. html base e il foglio di stile master.css.
  • www/Cordova-1.5.0.js fornisce l'AP Windows Phone­mentation delle API JavaScript Cordova.Questo si interfaccia con il codice nativo contenuto all'interno di WP7CordovaClassLib.
  • BuildManifestProcessor.js è un file JavaScript che viene richiamato da un passaggio post-compilazione.Questo file genera la Cordova­file SourceDictionary.xml, assicurare che tutto ciò che aggiungere alla cartella www saranno caricate nel spazio di memorizzazione isolato.
  • CordovaSourceDictionary.xml è un file XML generato che elenca tutte le risorse dell'applicazione.Quando l'applicazione lancia in primo luogo, questo file XML indica i file da caricare in archiviazione isolata.

Il file MainPage contiene un'istanza del controllo CordovaView, un controllo utente che contiene un controllo WebBrowser:

<Grid x:Name="LayoutRoot">
    <my:CordovaView Name="PGView" />
  </Grid>

Quando l'applicazione viene avviato, il controllo di CordovaView si prende cura di caricare le risorse dell'applicazione in archiviazione locale e la navigazione nel file www/index.html, quindi il lancio dell'applicazione. È ovviamente possibile, inserire altri controlli di Silverlight nella pagina modificando questo codice XAML, anche se io non lo Consiglio. Se si sta scrivendo un'applicazione HTML5, vostra intenzione è probabilmente di rendere questa lavoro multi-piattaforma. Tutti i controlli che si aggiunge a MainPage sarà ovviamente specifici per la compilazione di Windows Phone.

Lo sviluppo di applicazioni di Cordova

È possibile aggiungere i file HTML, JavaScript e CSS nella cartella www e —, purché si contrassegnarli con una Build azione di contenuto — essi saranno inclusi nel progetto e accessibile tramite il controllo browser quando l'applicazione esegue. È possibile utilizzare qualsiasi delle librerie JavaScript/HTML5 standard o quadri nell'applicazione di Cordova, finché sono compatibili con il browser del telefono cellulare.

Le API di Cordova sono documentate sul sito Web di Cordova; Loro non descrivono in dettaglio qui. Una cosa importante da notare è che deve attendere l'evento deviceready prima di fare uso di uno qualsiasi degli altri metodi API. Se si controlla il file index. html generato dal modello, si può vedere che aspetta fino a che il dispositivo sia pronto prima dell'aggiornamento dell'interfaccia utente:

<script type="text/javascript">
  document.addEventListener("deviceready",onDeviceReady,false);
  function onDeviceReady()
  {
    document.getElementById("welcomeMsg").innerHTML
      += "Cordova is ready!
version=" + window.device.cordova;
    console.log(
      "onDeviceReady.
You should see this " +
        "message in Visual Studio's output window.");
  }
</script>

L'oggetto console utilizzata nel codice precedente consente di aggiungere l'output di debug all'applicazione. Questi messaggi vengono inviati alla console Visual Studio da Cordova.

Pagina singola o più pagine architettura applicativa

Durante la creazione di applicazioni di Cordova, si possono impiegare due distinti modelli:

  • Applicazioni più pagine: Nelle applicazioni più pagine, più pagine HTML vengono utilizzate per rappresentare le varie schermate della vostra applicazione. Navigazione tra le pagine utilizza la meccanica del browser standard, con collegamenti definiti dal tag di ancoraggio. Ogni pagina HTML include riferimenti a script per il
  • Codice JavaScript di Cordova e applicazione JavaScript.
  • Pagina singola applicazioni: Nelle applicazioni a pagina singola, un solo file HTML fa riferimento a Cordova e applicazione JavaScript. Navigazione tra le varie pagine dell'applicazione è possibile aggiornare dinamicamente il rendering HTML. Dal punto di vista del browser del telefono cellulare, l'URL rimane lo stesso e non non c'è nessuna navigazione tra le pagine.

La scelta effettuata tra questi due modelli ha un impatto significativo sulla struttura del codice.

In linea generale, il modello più pagine è più adatto alle applicazioni che comprendono principalmente contenuto statico. Con questo approccio si può prendere HTML/CSS/JavaScript attualmente utilizzata sul tuo sito Web e comprimerlo, utilizzando Cordova, per la consegna al telefono come applicazione. Ma l'approccio più pagine presenta alcuni svantaggi. In primo luogo, quando il browser si sposta da una pagina alla successiva, ha ricaricare e analizzare tutti i JavaScript associati con la nuova pagina. C'è una pausa di evidente come il ciclo di vita di Cordova, che crea il collegamento tra l'API JavaScript e c# controparti, viene eseguito. In secondo luogo, perché il codice JavaScript viene ricaricato, si perde tutto lo stato dell'applicazione.

Il modello di pagina singola permette di superare i problemi connessi con l'approccio più pagine. Cordova e applicazione codice JavaScript viene caricato solo una volta, risultante in un'interfaccia utente più reattiva ed eliminando la necessità di passare lo stato dell'applicazione da una pagina alla successiva. L'unico svantaggio di questo approccio è la complessità, con codice JavaScript per aggiornare l'interfaccia utente quando una navigazione essendo necessaria.

L'applicazione demo descritto in questo articolo utilizza il modello di pagina singola. Per un esempio dell'approccio più pagine in azione, mi raccomando guardando il progetto DemoGAP CodePlex (demogap.codeplex.com), che fornisce una semplice dimostrazione delle funzionalità all'interno di un'applicazione Windows Phone API di Cordova.

L'applicazione Demo

Il resto di questo articolo descrive "Cordova Twitter Search," una semplice applicazione di Windows Phone che permette all'utente di ricercare Twitter basato su una o più parole chiave, come illustrato nella Figura 5.

The Cordova Twitter Search Demo Application
Figura 5 l'applicazione Demo di Cordova Twitter ricerca

Oltre a Cordova, questa applicazione fa uso di ambiti seguenti:

  • jQuery e jQuery modelli: jQuery è diventato il framework standard de facto per la manipolazione del browser Document Object Model (DOM). i modelli di jQuery sono plug-in che Microsoft ha sviluppato (bit.ly/8ZO2V1), rendendo più semplice per creare modelli HTML riutilizzabili che possono essere reso a Dom. Twitter che Search utilizza jQuery modelli per definire l'interfaccia utente per le varie pagine all'interno dell'applicazione.
  • Knockout JS: Knockout è un framework di Model-View-ViewModel (MVVM) che lo rende facile da costruire ViewModels e tenerli sincronizzati con viste in modo familiare agli sviluppatori di Silverlight. È questa familiarità che mi ha portato a scegliere Knockout su numerosi altri idonei JavaScript UI Framework.

Non essere coprendo Knockout in dettaglio in questo articolo. Se siete interessati a saperne di più su questo quadro, vi consiglio di leggere il recente articolo di John Papa, "Ottenere iniziato con Knockout" (msdn.microsoft.com/magazine/hh781029). E se non si ha familiarità con il modello MVVM (dove hanno stava nascondendo?), mi raccomando questo ottimo articolo di Josh Smith: "Applicazioni WPF con il modello di progettazione Model-View-ViewModel" (msdn.microsoft.com/magazine/dd419663).

Lo sviluppo di applicazioni JavaScript con Visual Studio

Prima di addentrarsi nei dettagli dell'applicazione, voglio dire alcune cose circa lo sviluppo di applicazioni JavaScript. Una delle sfide per lo sviluppatore di JavaScript è la natura dinamica della lingua. Con JavaScript non sono vincolate da un sistema di tipo rigido; al contrario, gli oggetti possono essere costruiti in modo dinamico. Questo rappresenta una sfida per gli sviluppatori di JavaScript redattori e idi. Lingue fortemente tipizzata come c# e Java, le informazioni sul tipo consente di fornire codice migliorata navigazione, refactoring e IntelliSense. Con JavaScript, d'altra parte, la mancanza di informazioni di tipo significa che l'IDE fornisce in genere assai meno aiuti dello sviluppatore.

Fortunatamente, le cose sono migliorate di recente, con Visual Studio 2010 eseguire pseudo-execution del codice JavaScript al fine di determinare la "forma" di ciascun oggetto, permettendo così di fornire JavaScript IntelliSense. Al fine di sfruttare appieno il supporto IntelliSense, dobbiamo fornire l'IDE con pochi "suggerimenti" sotto forma di "riferimenti" che raccontano l'IDE i file da includere nella sua pseudo-execution. Con il progetto demo, tutti i file iniziano con un commento di riferimento che racconta l'IDE per includere il file intellisense.js. Il contenuto di questo file è semplicemente un elenco di riferimenti che assicurano che l'IDE include tutti i file JavaScript importante applicazione, fornendo supporto IntelliSense di qualità attraverso l'applicazione, come illustrato di seguito:

/// Ensure IntelliSense includes all the files from this project.
///
/// <reference path="app.js" />
/// <reference path="viewModel/ApplicationViewModel.js" />
/// <reference path="viewModel/SearchResultsViewModel.js" />
/// <reference path="viewModel/TweetViewModel.js" />
/// <reference path="viewModel/TwitterSearchViewModel.js" />
/// <reference path="lib/jquery-1.6.4.js" />
/// <reference path="lib/cordova-1.5.0.js" />
/// <reference path="lib/knockout-1.2.1.js" />

JavaScript è un linguaggio indulgente e rilassato, con funzioni come la coercizione del valore e semi­inserimento del colon, che lo rende facile da usare in un ambiente di scripting. Tuttavia, queste stesse caratteristiche spesso diventano problematiche durante la gestione di grandi quantità di codice. Per questo motivo mi raccomando utilizzando JSLint, uno strumento che applica un modello di codifica standard a JavaScript più rigido. Un popolare estensione di Visual Studio aggiunge il supporto JSLint (jslint4vs2010.codeplex.com), segnalazione degli errori di lanugine interno della console di errore. Ho usato per l'applicazione di ricerca Twitter JSLint (e praticamente ogni altro progetto JavaScript ho lavorato su).

Si potrebbe notare un commento "globals" all'inizio di ogni file JavaScript all'interno del progetto. JSLint aiuta a prevenire le variabili "perdite" in ambito globale per omissione accidentale, la parola chiave var. Il commento di "globals" JSLint fornisce una definizione formale di cui le variabili sono ammessi ad occupare un ambito globale.

La struttura dell'applicazione MVVM

L'applicazione di ricerca Twitter è, dal punto di vista del controllo browser del telefono cellulare, una pagina singola applicazione. Al contrario, dal punto di vista utente, esso ha pagine multiple, come visto Figura 5. Al fine di sostenere questo, un ViewModel Knockout è costruito che contiene una pila di istanze ViewModel, ognuno che rappresenta una pagina all'interno dell'applicazione. L'utente si sposta su una nuova pagina, ViewModel corrispondente viene aggiunto a questo stack e quando l'utente si sposta indietro, il ViewModel in primo piano è spuntato stack (vedere Figura 6).

Nella figura 6 il ApplicationViewModel Knockout

/// <reference path="..//intellisense.js" />
/*globals ko*/
function ApplicationViewModel() {
  /// <summary>
  /// The ViewModel that manages the ViewModel back-stack.
/// </summary>
  // --- properties
  this.viewModelBackStack = ko.observableArray();
  // --- functions
  this.
navigateTo = function (viewModel) {
    this.viewModelBackStack.push(viewModel);
  };
  this.back = function () {
    this.viewModelBackStack.pop();
  };
  this.templateSelector = function (viewModel) {
    return viewModel.template;
  }
}

All'avvio dell'applicazione, un'istanza del ApplicationViewModel viene creata e associata all'interfaccia utente utilizzando Knockout:

document.addEventListener("deviceready", initializeViewModel, false);
var application;
function initializeViewModel() {
  application = new ApplicationViewModel();
  ko.applyBindings(application);
}

L'interfaccia utente di sé è abbastanza semplice, che comprende un elemento div che utilizza il modello di Knockout associazione per eseguire il rendering dello stack ViewModel:

    <body>
      <h1>Cordova Twitter Search</h1>
      <div class="app"
        data-bind="template: {name: templateSelector,
                              foreach: viewModelBackStack}">
      </div>
    </body>

L'associazione del modello Knockout funziona in modo simile all'oggetto Silverlight ItemsControl in quanto si associa a una matrice di istanze ViewModel ed è responsabile della generazione la vista per ciascuna tramite un modello. In questo caso, viene richiamata la funzione templateSelector sulla ApplicationViewModel al fine di determinare il modello denominato per ogni ViewModel.

Se si esegue questa applicazione troverete che esso in realtà non fa nulla — che è perché non ci sono qualsiasi ViewModels per rappresentare le pagine dell'applicazione!

La TwitterSearchViewModel

I'll introdurre il primo ViewModel, TwitterSearchViewModel, che rappresenta la prima pagina dell'applicazione. Questo ViewModel espone alcune semplici osservabile proprietà che supportano l'interfaccia utente, vale a dire il termine, che è associata al campo input utente, e isSearching, che è un booleano osservabile che disabilita il pulsante Cerca quando le API di Twitter sono sottoposta a query tramite il protocollo HTTP. Essa espone anche una funzione di ricerca è associata al pulsante di ricerca, più o meno allo stesso modo che è necessario associare un oggetto ICommand a un pulsante all'interno di Silverlight (vedere Figura 7).

Nella Figura 7, il TwitterSearchViewModel

/// <reference path="..//intellisense.js" />
/*globals $ application ko localStorage SearchResultsViewModel TweetViewModel*/
function TwitterSearchViewModel() {
  /// <summary>
  /// A ViewModel for searching Twitter for a given term.
/// </summary>
  // --- properties
  this.template = "twitterSearchView";
  this.isSearching = ko.observable(false);
  this.searchTerm = ko.observable("");
  // --- public functions
  this.search = function () {
    /// <summary>
    /// Searches Twitter for the current search term.
/// </summary>
    // implementation detailed later in this article ...
};
}

La proprietà template di ViewModel i nomi del parere che è associata a questo ViewModel. Questo punto di vista è descritto come un modello di jQuery all'interno del file index. html:

    <script type=text/x-jquery-tmpl" charset="utf-8" id="twitterSearchView" 
      <div>
        <form data-bind="submit: search">
          <input type="text"
            data-bind="value: searchTerm, valueUpdate: 'afterkeydown'" />
          <button type="submit"
            data-bind="enable: searchTerm().length > 0 &&
              isSearching() == false">Go</button> 
        </form>     
      </div>
    </script>

Se si aggiunge un'istanza della TwitterSearchViewModel allo stack ViewModel applicazione, l'applicazione ora mostra la prima pagina, come mostrato nella Figura 8.

The TwitterSearchViewModel Rendered via the twitterSearchView Template
Figura 8 The TwitterSearchViewModel reso tramite il modello twitterSearchView

Creazione di una Metro di interfaccia utente con i CSS

Una delle caratteristiche del sistema operativo Windows Phone colpisce di più è il linguaggio del design della metropolitana, cui si ispira tutti gli aspetti dell'aspetto del telefono cellulare. Questo linguaggio del design, che privilegia i contenuti rispetto alla cromo, non è solo piacevole per gli occhi, è anche pratico, offrendo le interfacce altamente leggibile per il fattore di forma piccolo telefono cellulare.

L'interfaccia utente corrente, come mostrato in Figura 8, viene utilizzato lo stile standard del browser e di conseguenza non è molto piacevole per gli occhi! Ci sono già alcuni quadri consolidati per la creazione di interfacce utente mobile bell'aspetto utilizzando HTML e CSS, come ad esempio jQuery Mobile (jquerymobile.com). Attualmente questi quadri tendono a concentrarsi sull'emulazione di iOS look and feel. Un'applicazione Windows Phone Cordova potrebbe disegnata utilizzando jQuery Mobile, anche se probabilmente dovrebbe affrontare qualche rifiuto utente perché semplicemente non sarebbe "rientra" con l'aspetto complessivo del sistema operativo.

Fortunatamente, il senza cromo tema della metropolitana è in realtà abbastanza facile da replicare utilizzando HTML e CSS. In realtà, 8 Windows considera HTML come un cittadino di prima classe, consentendo di sviluppare applicazioni di HTML5 Metro utilizzando le API di Runtime di Windows.

Introducendo il corretto font, dimensioni dei caratteri e colori tramite alcuni semplici CSS (mostrato in Figura 9), è possibile creare un'interfaccia utente che segue da vicino il tema della metropolitana, come mostrato nella Figura 10.

Figura 9 codice per seguire il tema della metropolitana

    body
    {
      background: #000 none repeat scroll 0 0;
      color: #ccc;
      font-family: Segoe WP, sans-serif;
    }
    h1
    {
      font-weight: normal;
      font-size: 42.667px; /* PhoneFontSizeExtraLarge */
    }
    button
    {
      background: black;
      color: white;
      border-color: white;
      border-style: solid;
      padding: 4px 10px;
      border-width: 3px; /* PhoneBorderThickness */
      font-size: 25.333px; /* PhoneFontSizeMediumLarge */
    }
    input[type="text"]
    {
      width: 150px;
      height: 34px;
      padding: 4px;
    }

The Twitter Search Application with a Metro CSS Style Applied
Figura 10 applicata all'applicazione di ricerca Twitter con uno stile CSS Metro

Un aspetto finale che è un po ' di un omaggio che questa è un'applicazione di HTML5, piuttosto che un nativo è che l'utente può ancora "pizzico" l'interfaccia utente al fine di renderlo lo zoom. Questo può essere parzialmente risolto aggiungendo la seguente proprietà meta alla pagina index. html:

    <meta name="viewport" content="user-scalable=no" />

Questo informa il browser che l'utente non è consentito di scalare il contenuto visualizzato. Purtroppo, il modo in cui che questo viene implementato dal browser Windows Phone consente all'utente di ridimensionare il contenuto, ma scatta torna alla scala originale quando finisce l'interazione. Questo non sembra terribilmente bene!

Ho scoperto che, controllando la struttura ad albero visuale del controllo WebBrowser, è possibile associare gestori per gli eventi di modifica e impedire che ribolle fino alla TileHost nativo che rende l'HTML5 contenuto. Ho pubblicato un post sul blog di breve (bit.ly/vU2o1q) che include una classe semplice utility che consente di ottenere questo. Ma è questo dovrebbe utilizzare con cautela perché dipende la struttura interna del controllo WebBrowser, che ben può cambiare in futuro le versioni del sistema operativo Windows Phone.

Alla ricerca di Twitter

Se si guarda più in dettaglio la funzione di ricerca di TwitterSearchViewModel, una query le API di Twitter tramite la funzione di "ajax" jQuery, che restituisce una risposta JSONP. Un'istanza TweetViewModel ciascuno dei tweets restituiti è costruita, e questi sono utilizzati per costruire un'istanza di SearchResultsViewModel (vedere Figura 11).

Figura 11 la funzione di ricerca TwitterSearchViewModel

this.search = function () {
  /// <summary>
  /// Searches Twitter for the current search term.
/// </summary>
  this.isSearching(true);
  var url = "http://search.twitter.com/search.json?q=" +
    encodeURIComponent(that.searchTerm());
  var that = this;
  $.ajax({
    dataType: "jsonp",
    url: url,
    success: function (response) {
      // Create an array to hold the results.
var tweetViewModels = [];
      // Add the new items.
$.each(response.results, function () {
        var tweet = new TweetViewModel(this);
        tweetViewModels.push(tweet);
      });
      // Navigate to the results ViewModel.
application.
navigateTo(new SearchResultsViewModel(tweetViewModels));
      that.isSearching(false);
    }
  });
};

Il SearchResultsViewModel contiene semplicemente un elenco di tweets:

/// <reference path="..//intellisense.js" />
/*globals ko*/
function SearchResultsViewModel(tweetViewModels) {
  /// <summary>
  /// A ViewModel that renders the results of a twitter search.
/// </summary>
  /// <param name="tweetViewModels">An array of TweetViewModel instances</param>
  // --- properties
  this.template = "searchResultsView";
  this.tweets = ko.observableArray(tweetViewModels);
}

E il TweetViewModel espone le proprietà di un tweet individuali e una funzione di seleziona che si sposta la vista tweet individuale, come mostrato nella Figura 12.

Figura 12 la TweetViewModel

/// <reference path="..//intellisense.js" />
/*globals application*/
function TweetViewModel(tweet) {
  /// <summary>
  /// A ViewModel that represents a single tweet
  /// </summary>
  /// <param name="tweet">A tweet as returned by the twitter search API</param>
  // --- properties
  this.template = "tweetDetailView";
  this.author = tweet.from_user;
  this.text = tweet.text;
  this.id = tweet.id;
  this.time = tweet.created_at;
  this.thumbnail = tweet.profile_image_url;
  // --- public functions
  this.select = function () {
    /// <summary>
    /// Selects this tweet, causing the application to navigate to a tweet-view.
/// </summary>
    application.
navigateTo(this);
  };
}

Ancora una volta, i modelli che descrivono la vista per ognuno di questi ViewModels vengono aggiunte al file index. html, come mostrato nella Figura 13.

Figura 13 aggiunta di modelli per il File index. html

    <script type=text/x-jquery-tmpl" charset="utf-8" id="searchResultsView">
      <div>
        <ul data-bind="template: {name: 'tweetView',
                                  foreach: tweets}"> </ul>
      </div>
    </script>
    <script type="text/x-jquery-tmpl" charset="utf-8" id="tweetView">
      <li class="tweet"
          data-bind="click: select">
        <div class="thumbnailColumn">
          <img data-bind="attr: {src: thumbnail}"
                                 class="thumbnail"/>
        </div>
        <div class="detailsColumn">
          <div class="author"
               data-bind="text: author"/>
          <div class="text"
               data-bind="text: text"/>
          <div class="time"
               data-bind="text: time"/>
        </div>
      </li>
    </script>

Con questo codice, quando l'utente preme il pulsante "vanno" per la ricerca di Twitter, un nuovo SearchResultsViewModel viene aggiunto allo stack ViewModel. Ciò comporterà automaticamente il modello searchResultsView, viene eseguito il rendering nell'ambito del "app" div. Tuttavia, poiché lo stack ViewModel viene eseguito il rendering tramite un'associazione modello foreach, questo non nasconde le istanze del modello twitterSearchView; invece si potrai essere impilati uno sopra l'altro. Questo può essere risolto mediante l'aggiunta di un paio di semplici regole CSS:

    .app>div
    {
      display: none;
    }
    .app>*:last-child
    {
      display: block;
    }

Il primo selettore nasconde tutti i bambini immediati del div contrassegnato con la classe app, mentre il secondo selettore, che ha una precedenza più alta, assicura che l'ultimo elemento figlio viene mostrato.

Con queste regole CSS in luogo, l'applicazione di ricerca Twitter è pienamente funzionale e navigabile.

Gestione Back Stack

Con la ricerca attuale di Twitter applicazione è possibile spostarsi dalla ricerca pagina dei risultati di un tweet individuali, ma se si preme il pulsante indietro del telefono l'applicazione termina immediatamente. Questo è perché la navigazione applicazione avviene interamente all'interno di un controllo del browser, quindi, dal punto di vista del framework Silverlight, l'applicazione dispone di una singola pagina. Questo si traduce non solo in un'esperienza utente poveri, quasi certamente provocherà l'applicazione respinto se presentato al mercato Windows Phone.

Fortunatamente, la soluzione a questo problema è semplice. Il ApplicationViewModel contiene una pila di istanze ViewModel. Se c'è più di un'istanza di ViewModel in questo stack, è necessario gestire la pressione del tasto Back hardware e pop ViewModel in primo piano dallo stack. In caso contrario, è possibile consentire il quadro di Silverlight per uscire dall'applicazione.

Per sostenere questo, si aggiunge un osservabile dipendente backButtonRequired ViewModel:

function ApplicationViewModel() {
  // --- properties
  this.viewModelBackStack = ko.observableArray();
  this.backButtonRequired = ko.dependentObservable(function () {   
    return this.viewModelBackStack().length > 1;
  }, this);
  // --- functions
  // ...
}

Quando viene inizializzato il ViewModel, potete gestire le modifiche a questo osservabile e sottoscrivere gli eventi backbutton che rifornisce di Cordova. Quando l'evento viene generato, richiamare la funzione posteriore su ApplicationViewModel, che si apre il primo piano ViewModel stack. L'associazione del modello Knockout si prende cura di rimozione di visualizzazione associate di ViewModel dall'interfaccia utente e lo stile CSS assicura l'opinione che ora è in primo piano è visibile (vedere Figura 14).

Figura 14 movimentazione a premere il tasto Back

function initializeViewModel() {
  application = new ApplicationViewModel();
  ko.applyBindings(application);
  // Handle the back button.
application.backButtonRequired.subscribe(function (backButtonRequired) {
    if (backButtonRequired) {
      document.addEventListener("backbutton", onBackButton, false);
    } else {
      document.removeEventListener("backbutton", onBackButton, false);
    }
  });
  var viewModel = new TwitterSearchViewModel();
  application.
navigateTo(viewModel);
}
function onBackButton() {
  application.back();
}

Perché l'evento backbutton è fornito tramite Cordova, il codice in Figura 14 funzionerà bene se si esegue l'applicazione utilizzando un telefono diverso OS (a condizione che il telefono cellulare ha un pulsante Back hardware).

Persistenza dello stato

Aggiungeremo una caratteristica finale per l'applicazione di ricerca Twitter: Quando una ricerca restituisce con successo, il termine di ricerca viene aggiunto a un elenco di ricerche recenti (vedere Figura 15).

Figura 15 aggiungendo un termine di ricerca ad una lista di ricerche recenti

function TwitterSearchViewModel() {
  /// <summary>
  /// A ViewModel for searching Twitter for a given term.
/// </summary>
  // --- properties
  // ...
some properties omitted for clarity ...
this.recentSearches = ko.observableArray();
  // --- functions
  // ...
some functions omitted for clarity ...
this.loadState = function () {
    /// <summary>
    /// Loads the persisted ViewModel state from local storage.
/// </summary>
    var state = localStorage.getItem("state");
    if (typeof (state) === 'string') {
      $.each(state.split(","), function (index, item) {
        if (item.trim() !== "") {
          that.recentSearches.push(item);
        }
      });
    }
  };
  function saveState() {
    /// <summary>
    /// Saves the ViewModel state to local storage.
/// </summary>
    localStorage.setItem("state", that.recentSearches().toString());
  }
  function addSearchTermToRecentSearches() {
    /// <summary>
    /// Adds the current search term to the search history.
/// </summary>
    that.recentSearches.unshift(that.searchTerm());
    saveState();
  }
}

La funzione addSearchTermToRecentSearches utilizza la funzione di convenienza ad eliminazione diretta, unshift, che aggiunge un elemento all'inizio della matrice. Ogni volta che viene aggiunto una recente ricerca, lo stato viene archiviato utilizzando l'archiviazione locale di HTML5. In questo caso lo stato della matrice è convertito in un elenco delimitato da virgole tramite la funzione toString e convertito tramite Spalato. Un ViewModel più complesso risparmierebbe molto probabilmente più valori di proprietà in formato JSON.

È interessante notare che, mentre il browser Windows Phone supporta archiviazione locale, questa funzione è disattivata quando il browser esegue il rendering di pagine dall'archiviazione isolata. Al fine di rendere il codice precedente lavoro, il team di Cordova dovuto scrivere un'implementazione "shim" di memoria locale di API che salva lo stato all'interno di spazio di memorizzazione isolato del telefono cellulare.

Con questa ultima modifica all'applicazione Twitter Search, è ora pienamente funzionale.

Dimostrazione di portabilità: In esecuzione su un iPhone

Come potete vedere, il quadro di Cordova rende possibile la creazione di applicazioni basate su HTML5 per Windows Phone. È inoltre possibile simulare il nativo Metro look and feel utilizzando semplici tecniche di HTML5 e CSS, mentre Framework come Knockout consentono di strutturare correttamente il codice.

In questo articolo si è concentrata sulla creazione di applicazioni per Windows Phone, ma l'applicazione di ricerca Twitter è portabile e deve essere eseguita su un iPhone o un telefono Android senza alcuna modifica. Ma sarebbe un'applicazione di tipo Metro soddisfare questi telefoni?

Come una manifestazione finale della versatilità di questo approccio, ho creato una versione di iOS dell'applicazione Twitter Search, utilizzando jQuery Mobile di imitare l'aspetto nativo. Questo fa grande uso del modello MVVM, in quanto solo la vista deve essere cambiato — tutta la logica di ViewModel è esattamente lo stesso. Utilizzando il servizio di generazione basato su cloud era in grado di creare un pacchetto "ipa" iOS e installarlo su un iPhone, tutto da una macchina Windows. Si possono vedere le due applicazioni in esecuzione side by side in Figura 16.

Twitter Search Running on an iPhone and a Windows Phone Device
Figura 16 Twitter Search in esecuzione su un iPhone e un dispositivo di Windows Phone

Il codice sorgente per l'iOS e le versioni dell'applicazione Windows Phone accompagna questo articolo.

Colin Eberhardt è un architetto tecnico presso Scott logica Ltd. e piombo architetto presso Visiblox (visiblox.com), che fornisce controlli grafici per una gamma di Microsoft.Tecnologie di NET Framework. Può seguirlo su Twitter a twitter.com/ColinEberhardt.

Grazie ai seguenti esperti tecnici per la revisione di questo articolo: Olivier Bloch, Glen Gordon e Jesse MacFadyen