Este artículo proviene de un motor de traducción automática.
HTML5
Desarrolle aplicaciones de Windows Phone en HTML5 con Apache Cordova
Descargar el código de ejemplo
Este artículo introduce Apache Córdoba, un marco para la creación de aplicaciones móviles multiplataforma usando HTML5 y JavaScript y muestra cómo puede utilizarse para desarrollar aplicaciones para Windows Phone.
Windows Phone y su plataforma de desarrollo nativo permiten crear aplicaciones de estilo Metro hermosas con facilidad.Con la reciente asociación de Nokia, Windows Phone está empezando a encontrar su camino en bolsillos más y más.
Últimos datos publicados por la investigación de la firma Gartner Inc.predice un futuro prometedor para el sistema operativo de Microsoft (bit.ly/h5Ic32), con mercado significativo compartir en un mercado fragmentado.Si está desarrollando una aplicación de smartphone, esta fragmentación del mercado significa que o bien tienen que elegir qué OS a destino o escribir la misma aplicación varias veces utilizando la amplia gama de idiomas estos teléfonos requiere (C#, Java y Objective-C).
Sin embargo, hay otra manera.Todos estos smartphones disponer de un navegador muy capaz, en muchos sentidos más capaces que sus contrapartes de escritorio, donde algunas personas todavía usan navegadores arcaicos!Smartphones modernos permiten crear aplicaciones que se ejecutan dentro del navegador mediante una combinación de HTML5, JavaScript y CSS.Con estas tecnologías potencialmente puede escribir una sola aplicación basada en explorador que se ejecuta a través de una amplia gama de dispositivos smartphone.
Introducción de Córdoba de Apache
Puede crear una aplicación móvil basada en HTML5, creando una página Web pública con contenido JavaScript y HTML5 y dirigir a personas a la URL de hospedaje.Sin embargo, hay un par de problemas con este enfoque.El primero es el modelo de distribución a través de tiendas y mercados en línea.No se puede enviar la URL que aloja la aplicación Web a un mercado, entonces, ¿cómo puede usted monetizar?El segundo problema es cómo acceder hardware del teléfono.No hay ningún navegador ampliamente admitido APIs para acceder a contactos telefónicos, notificaciones, cámaras, sensores y así sucesivamente.Apache Córdoba (sólo Córdoba en adelante por brevedad) es un marco de libre y de código abierto que resuelve estos problemas.
Córdoba comenzó su vida como PhoneGap, que fue desarrollado por Nitobi.En octubre de 2011 Nitobi fue adquirido por Adobe Systems Inc., con el marco de PhoneGap está abierto obtenidos bajo la Apache Software Foundation y renombrado como Córdoba.Esta transición está todavía en marcha.
Córdoba proporciona un entorno para alojar el contenido HTML5 y JavaScript dentro de un contenedor nativo delgado.Para cada smartphone OS, utiliza un control de explorador nativo para representar el contenido de la aplicación, con los activos de aplicación se incluye en el distribuible.Con Windows Phone, sus activos de HTML5 son empaquetados dentro del archivo XAP y cargados en almacenamiento aislado cuando se inicia la aplicación de Córdoba.En tiempo de ejecución, un control WebBrowser representa su contenido y ejecuta el código JavaScript.
Córdoba también proporciona un conjunto de APIs estándar para acceder a la funcionalidad que es común a través de diferentes smartphones.Algunas de estas funcionalidades incluyen:
- Eventos de ciclo de vida de la aplicación
- Storage (almacenamiento de información local de HTML5 y bases de datos)
- Contactos
- Cámara
- Geolocalización
- Acelerómetro
Cada una de las funciones anteriores se expone como un JavaAPI de Script, que se utiliza desde el código JavaScript.Córdoba hace todo el trabajo duro involucrado en proveer la implementación nativa requiere, asegurando que trabaje contra la misma API de JavaScript, independientemente del teléfono OS el código se está ejecutando, como se ilustra en figura 1.
Figura 1 Córdoba permite la misma aplicación de HTML5 ejecutar a través de una gama de Mobile SO
La mayor parte de este artículo explica Córdoba desde la perspectiva de un desarrollador de Windows Phone, donde el desarrollo lleva a cabo dentro de Visual Studio y probar la aplicación en el emulador o en un dispositivo físico.Mientras que Córdoba es una tecnología multiplataforma, desarrollas normalmente usando su editor o IDE de elección, por lo que un desarrollador iOS sería desarrollar una aplicación de Córdoba en Xcode y desarrollador Android utilizaría probablemente Eclipse.
Córdoba también dispone de un servicio de generación basados en cloud llamado generación (build.phonegap.com), donde puede enviar su contenido HTML5 y JavaScript.Poco tiempo después devuelve distribuciones para la mayoría de las plataformas compatibles de Córdoba.Esto significa que no necesita tener copias de los diversos IDEs específica de la plataforma (o un ordenador Mac) a fin de generar la aplicación de una amplia gama de plataformas.El servicio de compilación es propiedad de Adobe y está actualmente en fase beta y uso gratuito.Seguirá siendo gratuita para proyectos de código abierto.
Adquirir las herramientas
Se supone que ya tiene Visual Studio, el SDK de Windows Phone y (opcionalmente) Zune para desarrollo de Windows Phone.Si no, puede obtener las herramientas gratis Descargar Visual Studio 2010 Express para Windows Phone (bit.ly/dTsCH2).
Puede obtener las últimas herramientas de desarrollador de Córdoba desde el sitio PhoneGap Web (phonegap.com), aunque las versiones futuras se distribuirá mediante Apache (incubator.apache.org/cordova).La descarga incluye plantillas, bibliotecas y secuencias de comandos necesarias para desarrollar aplicaciones de Córdoba a través de todas las plataformas soportadas.Usted querrá utilizar la versión de Windows Phone, por supuesto.
Una vez que haya descargado las herramientas de Córdoba, siga la Windows Phone Get Started Guide (phonegap.com/start#wp) e instalar la plantilla de Visual Studio.Creación de un "Hello World"-aplicación de estilo es tan simple como crear un nuevo proyecto basado en la plantilla proporcionada, como se muestra en figura 2.
Figura 2 Córdoba para Windows Phone incluye una plantilla de estudio Visual
Si usted construir e implementa el proyecto creado por la plantilla a su emulador, usted debe saludó con el mensaje "¡ Hola Córdova," como se muestra en figura 3.
Figura 3 la aplicación de la plantilla de Córdoba que se ejecuta en un emulador
La anatomía de una aplicación de Córdoba Windows Phone
Aunque puede desarrollar una aplicación de Córdoba sin mucho conocimiento de cómo funciona bajo el capó, vale la pena entender cuáles son los archivos generados por la plantilla, como se muestra en figura 4.
Figura 4 la estructura de carpetas de la plantilla de Córdoba
Centrarse sólo en los archivos de Córdoba en figura 4 (de arriba a abajo), tenga en cuenta lo siguiente:
- GapLib/WP7CordovaClassLib.dll es la Asamblea de Córdoba.Contiene la implementación nativa de Windows Phone de la API de Cordova.
- www es la carpeta donde colocar sus activos de aplicación, HTML5, JavaScript, CSS e imágenes.La plantilla genera un archivo index.html básica y la hoja de estilos master.css.
- www/Cordova-1.5.0.js proporciona la imple Windows Phonedocumentación de la API de JavaScript de Córdoba.Esto se interrelaciona con el código nativo dentro de WP7CordovaClassLib.
- BuildManifestProcessor.js es un archivo JavaScript que se invoca a un paso posterior.Este archivo genera la CórdobaSourceDictionary.xml archivo, asegurando que nada que agrega a la carpeta de www se cargarán en almacenamiento aislado.
- CordovaSourceDictionary.xml es un archivo XML generado que enumera todos los activos de sus aplicación.Cuando su aplicación se inicia primero, este archivo XML indica los archivos para ser cargados en almacenamiento aislado.
El archivo MainPage.xaml contiene una instancia del control CordovaView, un control de usuario que contenga un control WebBrowser:
<Grid x:Name="LayoutRoot">
<my:CordovaView Name="PGView" />
</Grid>
Cuando se inicia la aplicación, el control de CordovaView se encarga de cargar sus activos de aplicación en el almacenamiento local y desplácese hasta el archivo www/index.html, iniciando así su aplicación. Por supuesto, puede colocar otros controles de Silverlight en la página editando este XAML, aunque no recomendarlo. Si está escribiendo una aplicación HTML5, su intención es probablemente hacer este trabajo multiplataforma. Los controles que se agregar a MainPage.xaml por supuesto será específicos para su generación de Windows Phone.
Desarrollo de aplicaciones de Córdoba
Puede agregar los archivos HTML, JavaScript y CSS a la carpeta www y — como marcarlos con un construir medidas de contenido — van a estar incluidos en el proyecto y accesible mediante el control del explorador cuando se ejecuta la aplicación. Puede utilizar cualquiera de las bibliotecas estándar de JavaScript/HTML5 o marcos en su aplicación de Córdoba, como son compatibles con el explorador del teléfono.
Las API de Córdoba están documentadas en el sitio Web de Córdoba; No describirlas en detalle aquí. Tenga en cuenta una cosa importante es que debe esperar para el evento de deviceready antes de hacer uso de cualquiera de los otros métodos de la API. Si inspeccionar el archivo index.html generado a partir de la plantilla, puede ver que espera hasta que el dispositivo está listo antes de actualizar la interfaz de usuario:
<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>
El objeto de consola utilizado en el código anterior permite agregar resultado de depuración a la aplicación. Estos mensajes se envían a la consola de Visual Studio por Córdoba.
Sola página o varias páginas arquitectura de aplicaciones
Al crear aplicaciones de Córdoba, puede emplear dos modalidades distintas:
- Aplicaciones de varias páginas: En aplicaciones de varias páginas, varias páginas HTML se utilizan para representar las distintas pantallas de la aplicación. Navegación entre páginas utiliza la mecánica de navegador estándar, con vínculos definidos por etiquetas de anclaje. Cada página HTML incluye referencias de script a la
- Código Cordova JavaScript y su aplicación JavaScript.
- Sola página aplicaciones: En las aplicaciones de una página, un único archivo HTML hace referencia a Córdoba y su aplicación JavaScript. Navegación entre las distintas páginas de su aplicación se logra actualizar dinámicamente el código HTML procesado. Desde la perspectiva del navegador del teléfono, la dirección URL sigue siendo la misma y no hay ninguna navegación entre páginas.
La elección que entre estos dos patrones tiene un impacto significativo en la estructura del código.
En términos generales, el patrón de varias páginas es ideal para aplicaciones que abarcan principalmente contenido estático. Con este enfoque puede tomar HTML/CSS/JavaScript que se utiliza actualmente en el sitio Web y paquete, utilizando Córdova, para la entrega en el teléfono como una aplicación. Pero el enfoque de varias páginas tiene algunas desventajas. En primer lugar, cuando el explorador se desplaza de una página a la siguiente, tiene que volver a cargar y analizar todo el código JavaScript asociado con la nueva página. Hay una pausa notable como el ciclo de vida de Córdoba, que crea el vínculo entre la API de JavaScript y homólogos de C#, es ejecutado. En segundo lugar, porque se se vuelve a cargar el código JavaScript, se pierde el estado de aplicación todos.
El patrón de sola página supera los problemas asociados con el enfoque de varias páginas. El Córdoba y aplicación código JavaScript está cargado de una sola vez, resultando en una interfaz de usuario más receptiva y eliminando la necesidad de pasar a estado de aplicación de una página a la siguiente. La única desventaja de este enfoque es la complejidad añadida, con código JavaScript que se requiere para actualizar la interfaz de usuario cuando se produce de la navegación.
La aplicación de demostración descrita en este artículo utiliza el patrón de una página. Un ejemplo del enfoque multipágina en acción, recomiendo mirar el proyecto de DemoGAP CodePlex (demogap.codeplex.com), que proporciona una demostración sencilla de las funciones de la API de Córdoba dentro de una aplicación Windows Phone.
La aplicación de demostración
El resto de este artículo describen "Córdoba Twitter Search," una sencilla aplicación de Windows Phone que permite al usuario buscar Twitter basado en una o más palabras clave, como se muestra en figura 5.
Figura 5 la aplicación de demostración de búsqueda de Twitter Cordova
Así como Córdoba, esta aplicación hace uso de los siguientes marcos:
- jQuery y jQuery plantillas: jQuery se ha convertido en el marco estándar de facto para la manipulación del navegador Document Object Model (DOM). plantillas jQuery son plug-ins que Microsoft ha desarrollado (bit.ly/8ZO2V1), lo que facilita crear plantillas HTML reutilizables que se pueden procesar al DOM. Twitter que Search utiliza jQuery plantillas para definir la interfaz de usuario para las distintas páginas dentro de la aplicación.
- Eliminatorias JS: Knockout es un marco de modelo-vista-Perspective (MVVM) que facilita la construcción de ViewModels y mantenerlos sincronizados con vistas de manera familiar a los desarrolladores de Silverlight. Es esta familiaridad que me llevaron a elegir nocaut sobre los numerosos otros adecuados JavaScript UI marcos.
No cubre Knockout en detalle en este artículo. Si estás interesado en aprender más acerca de este marco, recomiendo leer el artículo reciente de John Papa, "Getting con Knockout" (msdn.microsoft.com/magazine/hh781029). Y si no está familiarizado con el patrón MVVM (donde han ha escondido?), recomiendo este excelente artículo de Josh Smith: "Aplicaciones de WPF con el patrón de diseño modelo-vista-Perspective" (msdn.microsoft.com/magazine/dd419663).
Desarrollo de aplicaciones JavaScript con Visual Studio
Antes de ahondar en los detalles de la aplicación, quiero decir algunas cosas sobre desarrollo de aplicaciones de JavaScript. Uno de los desafíos que enfrenta el desarrollador JavaScript es la naturaleza dinámica de la lengua. Con JavaScript no están limitados por un sistema de tipo rígido; en su lugar, los objetos pueden construirse dinámicamente. Esto plantea un reto para los desarrolladores de JavaScript editores y IDEs. Con inflexibles lenguajes como C# y Java, puede utilizarse la información de tipo para proporcionar código mejorada navegación, refactorización e IntelliSense. Con JavaScript, por otro lado, la falta de información de tipo significa que el IDE proporciona normalmente menos de desarrollador de SIDA.
Afortunadamente, las cosas han mejorado recientemente, con Visual Studio 2010 realizar pseudo-execution de código JavaScript para determinar la "forma" de cada objeto, lo que le permite proporcionar JavaScript IntelliSense. A fin de aprovechar al máximo la compatibilidad con IntelliSense, tenemos que proporcionar el IDE con algunos "consejos" en forma de "referencias" que diga el IDE qué archivos se deben incluir en su pseudo-execution. Con el proyecto de demostración, todos los archivos de inicio con un comentario de referencia que indica el IDE para incluir el archivo intellisense.js. El contenido de este archivo es simplemente una lista de referencias que aseguran que el IDE incluye todos los archivos de JavaScript aplicaciones importantes, proporcionando soporte de IntelliSense de calidad a través de la aplicación, como se muestra aquí:
/// 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 es un lenguaje indulgente y relajado, con características tales como la coacción de valor y semiinserción de Colón haciéndolo fácil de usar en un entorno de secuencias de comandos. Sin embargo, estas mismas características suelen ser problemáticas al administrar grandes cantidades de código. Por eso recomiendo utilizando JSLint, una herramienta que se aplica a un conjunto más rígido de la codificación de las normas para JavaScript. Una extensión de estudio Visual popular agrega compatibilidad con JSLint (jslint4vs2010.codeplex.com), informes de errores de pelusa dentro de la consola de errores. He usado JSLint para la aplicación de búsqueda de Twitter (y prácticamente cualquier otro proyecto de JavaScript he trabajado en).
Puede observar un comentario "globales" al comienzo de cada archivo JavaScript dentro del proyecto. JSLint ayuda a prevenir las variables "fugas" en el ámbito global por omisión accidental de la palabra clave var. El comentario de "globales" proporciona JSLint con una definición formal de que variables pueden ocupar un ámbito global.
La estructura de la aplicación de MVVM
La aplicación de búsqueda de Twitter es, desde la perspectiva del control del explorador del teléfono, la aplicación de una sola página. Por el contrario, desde la perspectiva del usuario, tiene varias páginas, como puede verse en figura 5. Para apoyar esto, se construye una Perspective de nocaut que contiene una pila de instancias Perspective, cada uno representando a una página dentro de la aplicación. El usuario se desplaza a una nueva página, la Perspective correspondiente se agrega a esta pila y cuando el usuario navega de regreso, se extrae la Perspective superior la pila (consulte figura 6).
Figura 6 el ApplicationViewModel de 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;
}
}
Cuando se inicia la aplicación, una instancia de la ApplicationViewModel es creada y enlazada a la interfaz de usuario utilizando la eliminatoria:
document.addEventListener("deviceready", initializeViewModel, false);
var application;
function initializeViewModel() {
application = new ApplicationViewModel();
ko.applyBindings(application);
}
La interfaz de usuario es bastante simple, que comprende un elemento div que utiliza el enlace de la plantilla de nocaut para representar la pila Perspective:
<body>
<h1>Cordova Twitter Search</h1>
<div class="app"
data-bind="template: {name: templateSelector,
foreach: viewModelBackStack}">
</div>
</body>
El enlace de la plantilla de Knockout funciona de manera similar a la Silverlight ItemsControl que se enlaza a una matriz de instancias Perspective y es responsable de generar la vista para cada uno a través de una plantilla. En este caso, se invoca la función templateSelector en la ApplicationViewModel a fin de determinar la plantilla con nombre para cada perspective.
Si se ejecuta esta aplicación encontrará que realmente no hace nada, es porque no hay ningún ViewModels para representar a las páginas de la aplicación!
La TwitterSearchViewModel
Presentaré el primer Perspective, TwitterSearchViewModel, que representa la primera página de la aplicación. Este Perspective expone unas simples observables propiedades que admiten la interfaz de usuario, es decir el searchTerm, que es dependiente del campo de entrada de usuario, y isSearching, que es un booleano observable que desactiva el botón de búsqueda cuando las APIs de Twitter están siendo consultadas a través de HTTP. También expone una función de búsqueda que está enlazada el botón de búsqueda, en gran parte del mismo modo que vincularía una ICommand en un botón dentro de Silverlight (véase figura 7).
Figura 7 la 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 propiedad de plantilla de la Perspective nombra a la vista que se ha asociado con este perspective. Esta vista es descrita como una plantilla de jQuery dentro del archivo 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>
Si agrega una instancia de la TwitterSearchViewModel a la pila de Perspective de aplicación, la aplicación muestra la primera página, como se muestra en figura 8.
Figura 8 el TwitterSearchViewModel prestados a través de la plantilla de twitterSearchView
Crear un interfaz de usuario de Metro con CSS
Una de las características más sorprendentes de la Windows Phone OS es el lenguaje de diseño del Metro, que guía todos los aspectos de la apariencia del teléfono. Este lenguaje de diseño, que favorece el contenido en cromo, no sólo es agradable a la vista, también es práctico, ofreciendo interfaces muy legibles en el factor de forma pequeño teléfono.
La interfaz de usuario actual, como se muestra en figura 8, utiliza el estilo de navegador estándar y como resultado no es muy agradable a la vista! Ya hay unos marcos establecidos para la creación de guapos UIs móviles utilizando HTML y CSS, como jQuery Mobile (jquerymobile.com). Actualmente estos marcos tienden a concentrarse en emular la apariencia iOS. Una aplicación de Windows Phone Córdoba podría ser de estilo utilizando jQuery Mobile, aunque probablemente enfrentaría algunos rechazo de usuario porque simplemente no "concuerda" con la apariencia general del sistema operativo.
Afortunadamente, el cromo libre Metro tema es realmente muy fácil de replicar mediante HTML y CSS. De hecho, Windows 8 trata HTML como un ciudadano de primera clase, lo que le permite desarrollar aplicaciones de Metro de HTML5 mediante las API de tiempo de ejecución de Windows.
Introduciendo las fuentes correctas, tamaños de fuentes y colores mediante algún CSS simple (se muestra en figura 9), puede crear una interfaz de usuario que sigue de cerca el tema de Metro, como se muestra en figura 10.
Figura 9 código para seguir el tema de Metro
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;
}
Figura 10 la aplicación de búsqueda de Twitter con un estilo CSS de Metro aplicada
Un último aspecto que es un poco un regalo que esta es una aplicación de HTML5 en lugar de un nativo es que el usuario puede todavía "pellizcar" la interfaz de usuario para hacer zoom. Esto puede ser parcialmente resuelto agregando la siguiente propiedad de meta a la página index.html:
<meta name="viewport" content="user-scalable=no" />
Esto informa el navegador que el usuario no está permitido para escalar el contenido representado. Lamentablemente, la manera en que esto se implementa mediante el explorador de Windows Phone permite al usuario escalar el contenido, pero se ajusta atrás a la escala original cuando finalice la interacción. Esto no se ve terriblemente bueno!
He descubierto que, mediante la inspección del árbol visual del control WebBrowser, es posible adjuntar controladores para los eventos de manipulación y prohibir el traspaso a los nativo TileHost que representa el HTML5 contenido. Yo he publicado un blog breve (bit.ly/vU2o1q) que incluye una clase sencilla utilidad que lo logra. Pero debe utilizar esto con precaución ya que depende de la estructura interna del control WebBrowser, que bien puede cambiar en futuras versiones del sistema operativo Windows Phone.
Buscar en Twitter
Si nos fijamos en más detalle en la función de búsqueda de TwitterSearchViewModel, consulta las APIs de Twitter a través de la función de "ajax" jQuery, que devuelve una respuesta JSONP. Se construye una instancia de TweetViewModel de cada uno de los tweets devueltos, y se utilizan para construir una instancia de SearchResultsViewModel (véase figura 11).
Figura 11 la función de búsqueda de 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);
}
});
};
Simplemente, la SearchResultsViewModel contiene una lista de 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);
}
Y el TweetViewModel expone las propiedades de un tweet individual y una función de selección que se desplaza a la vista tweet individuales, como se muestra en figura 12.
Figura 12 el 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);
};
}
Una vez más, las plantillas que describen la visión de cada uno de estos ViewModels se agregan al archivo index.html, como se muestra en figura 13.
Figura 13 plantillas agregar el archivo 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 este código en el lugar, cuando el usuario pulsa el botón "ir" para buscar en Twitter, un nuevo SearchResultsViewModel se añade a la pila de Perspective. Se generará automáticamente la plantilla de searchResultsView que se procesa en el div "app". Sin embargo, debido a que la pila de Perspective se procesa a través de un enlace de plantilla foreach, esto no ocultar las instancias de plantilla twitterSearchView; en su lugar va ser apilados uno encima del otro. Esto puede ser resuelto mediante la adición de un par de sencillas reglas CSS:
.app>div
{
display: none;
}
.app>*:last-child
{
display: block;
}
El primer selector oculta todos los niños inmediatos del div marcados con la clase app, mientras que el segundo selector, que tiene una prioridad, asegura que se muestra el último hijo.
Con estas reglas CSS en el lugar, la aplicación de Twitter Search es plenamente funcional y navegable.
Gestión de la pila de espalda
Con la actual búsqueda de Twitter aplicación puede ir desde la búsqueda resultados de página a un tweet individual, pero si consigues el botón Atrás del teléfono inmediatamente cierra la aplicación. Esto es debido a la navegación de aplicación se produce completamente dentro de un control de explorador, por lo tanto, desde la perspectiva del marco de Silverlight, la aplicación tiene una única página. Esto no sólo se traduce en una experiencia de usuario pobre, casi seguramente tendrá como resultado la aplicación sea rechazada si se presenta en el mercado de Windows Phone.
Afortunadamente, la solución a este problema es sencilla. El ApplicationViewModel contiene una pila de instancias perspective. Si hay más de una instancia de Perspective en esta pila, necesita manejar la pulsación de botón Back de hardware y pop la Perspective superior esta pila. De lo contrario, puede permitir que el marco de Silverlight salir de la aplicación.
Para apoyar esto, un observable dependiente de backButtonRequired se agrega a la Perspective:
function ApplicationViewModel() {
// --- properties
this.viewModelBackStack = ko.observableArray();
this.backButtonRequired = ko.dependentObservable(function () {
return this.viewModelBackStack().length > 1;
}, this);
// --- functions
// ...
}
Cuando se inicializa el Perspective, puede manejar los cambios a este observable y suscribirse a los eventos de backbutton suministros de Córdoba. Cuando se desencadena el evento, invocar la función posterior en el ApplicationViewModel, que aparece el Perspective superior de la pila. El enlace de la plantilla de nocaut se encarga de quitar la vista asociada de Perspective de la interfaz de usuario y el estilo CSS asegura que ahora es superior es visible (véase figura 14).
Figura 14 manejo una pulsación de botón 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();
}
Porque el evento backbutton es suministrado a través de Córdoba, el código de figura 14 funcionará bien si se ejecuta la aplicación usando un teléfono diferente OS (siempre y cuando el teléfono tiene un botón de la parte posterior de hardware).
Persistencia de Estado
Agregaremos una característica final para la aplicación de Twitter Search: Cuando una búsqueda devuelve correctamente, el término de búsqueda se agrega a una lista de búsquedas recientes (véase figura 15).
Figura 15 agregar un término de búsqueda a una lista de búsquedas recientes
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 función addSearchTermToRecentSearches utiliza la función de la conveniencia de Knockout, unshift, que agrega un elemento al principio de la matriz. Cuando se agrega una búsqueda reciente, el Estado se almacena utilizando almacenamiento local de HTML5. En este caso el estado de la matriz se convierten a una lista separada por comas a través de la función toString y convierten volver a través de la División. Una Perspective más compleja probablemente ahorraría varios valores de propiedad en formato JSON.
Curiosamente, mientras que el navegador Windows Phone soporta almacenamiento local, esta función está desactivada cuando el explorador representa páginas de almacenamiento aislado. A fin de que el código anterior funcione, el equipo de Córdoba tuvo que escribir una aplicación de "corrección" del almacenamiento local APIs que guarda el estado en almacenamiento aislado del teléfono.
Con este último cambio para la aplicación de búsqueda de Twitter, ahora es completamente funcional.
Prueba de portabilidad: Ejecutándose en un iPhone
Como puede ver, el marco Córdova hace posible crear aplicaciones basadas en HTML5 para Windows Phone. También es posible imitar el nativo Metro aspecto utilizando técnicas sencillas de HTML5 y CSS, mientras marcos como Knockout permiten estructurar adecuadamente su código.
En este artículo se ha centrado en crear aplicaciones para Windows Phone, pero la aplicación de búsqueda de Twitter es portátil y debe ejecutarse en un iPhone o teléfono Android sin modificación. ¿Pero vendría una aplicación estilo Metro estos teléfonos?
Como una manifestación final de la versatilidad de este enfoque, he creado una versión de iOS de la aplicación de búsqueda de Twitter, usando jQuery Mobile para imitar el aspecto nativo. Esto hace gran uso del patrón MVVM, en que sólo la vista necesita ser cambiado, toda la lógica de Perspective es exactamente el mismo. Mediante el servicio de generación basados en cloud fue capaz de crear un paquete de "AFI" iOS e instalarlo en un iPhone, todo desde un equipo Windows. Puede ver las dos aplicaciones ejecutándose en paralelo en figura 16.
Figura 16 Twitter búsqueda ejecutándose en un iPhone y un dispositivo de Windows Phone
El código fuente completo para el iOS y versiones de Windows Phone de la aplicación acompaña a este artículo.
Colin Eberhardt es un arquitecto técnico en Scott lógica Ltd. y principal arquitecto en Visiblox (visiblox.com), que proporciona controles gráficos para un rango de Microsoft.Tecnologías de NET Framework. Puede seguirlo en Twitter en twitter.com/ColinEberhardt.
Gracias a los siguientes expertos técnicos para revisar este artículo: Olivier Bloch, Glen Gordon y Jesse MacFadyen