Este artículo muestra los cambios más recientes realizados como parte del lanzamiento de Windows Release Review y Visual Studio 2012.
Este fichero tiene una estructura sencilla de seguir. En primer lugar, aparece una serie de valores por defecto para descripciones e imágenes, seguido por la definición de ítems y grupos de ítems, cada uno con una serie de propiedades que va a estar conectada a la vista. En el siguiente fragmento podemos ver ejemplos de las propiedades de un grupo y de un ítem.
// Grupo
{
key: "group1",
title: "Group Title: 1",
subtitle: "Group Subtitle: 1",
backgroundImage: darkGray,
description: groupDescription
}
// Item
{
group: sampleGroups[0],
title: "Item Title: 1",
subtitle: "Item Subtitle: 1",
description: itemDescription,
content: itemContent,
backgroundImage: lightGray
}
Una vez definida la información y su estructura, aparece una serie de métodos que van a servir para localizar información dentro de los grupos e ítems:
Esto se conseguirá haciendo uso de WinJS.Binding.List, tal como se ve en el fichero. Mediante el método createGrouped, la lista recibirá dos funciones:
var list = new WinJS.Binding.List();
var groupedItems = list.createGrouped(
function groupKeySelector(item) { return item.group.key; },
function groupDataSelector(item) { return item.group; }
);
La variable groupedItems es una suerte de "proyección" sobre la lista original, de forma que al introducir nuevos elementos en la lista, groupedItems va a actualizarse también de forma automática. Eso es, precisamente, lo que hace la iteración sobre sampleItems, que va a introducir en la lista todos los ítems, de forma que groupedItems se cargará con ellos agrupados con base en el grupo de cada uno de ellos.
El último fragmento del fichero es muy interesante: define un nuevo espacio de nombres denominado "Data", con varios elementos.
WinJS.Namespace.define("Data", {
items: groupedItems,
groups: groupedItems.groups,
getItemsFromGroup: getItemsFromGroup,
getItemReference: getItemReference,
resolveGroupReference: resolveGroupReference,
resolveItemReference: resolveItemReference
});
Una de las buenas prácticas que deberíamos utilizar siempre al desarrollar aplicaciones Metro con JavaScript (y, en general, cuando programemos con cualquier lenguaje) es reducir la visibilidad de la información a lo mínimo imprescindible. De este modo, entre otros muchos beneficios, conseguiremos evitar interacciones inesperadas entre partes del código.
Una de las formas de implementar esta ocultación de la información en JavaScript es el uso de funciones anónimas. Si nos fijamos atentamente, nos daremos cuenta que todos los ficheros JavaScript de las plantillas de proyecto de aplicación Metro cumplen la siguiente estructura:
(function () {
Bibliografía
"use strict";
Bibliografía
// Eliminado por claridad...
})();
Con ello conseguimos que todos los elementos definidos en el interior del método no sean visibles desde fuera de la función, evitando también que sean manipulados. Esta clara ventaja tiene un inconveniente: en ocasiones necesitamos definir elementos para que sean visibles desde fuera de la función anónima.
Ahí entra en juego el método WinJS.Namespace.define. Nos permite definir un nuevo espacio de nombres en el que colocar elementos que sí van a ser visibles desde fuera de la función anónima. En el caso del código que veíamos antes se trata de datos y funciones que van a ser llamados por la vista o por otro código JavaScript de la aplicación.
<div class="itemtemplate" data-win-control="WinJS.Binding.Template">
<img class="item-image" src="#" data-win-bind="src: backgroundImage; alt: title" />
<div class="item-overlay">
<h4 class="item-title" data-win-bind="textContent: title"></h4>
<h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: subtitle"></h6>
</div>
</div>
En la etiqueta <img> estamos usando la propiedad data-win-bind para enlazar los atributos src y alt de la etiqueta con, precisamente, las propiedades backgroundImage y title que ya habíamos visto definidas en Data.sql, en concreto en sus ítems. Lo mismo aplica para los atributos de las etiquetas <h4> y <h6>, enlazado su contenido a las propiedades title y subtitle de cada ítem. Como vemos, declarativamente en HTML estamos identificando qué propiedades de la fuente de información subyacente de la lista queremos mostrar.
// This function updates the ListView with new layouts
initializeLayout: function (listView, viewState) {
/// <param name="listView" value="WinJS.UI.ListView.prototype" />
if (viewState === appViewState.snapped) {
listView.itemDataSource = Data.groups.dataSource;
listView.groupDataSource = null;
listView.layout = new ui.ListLayout();
} else {
listView.itemDataSource = Data.items.dataSource;
listView.groupDataSource = Data.groups.dataSource;
listView.layout = new ui.GridLayout({ groupHeaderPosition: "top" });
}
}
Dependiendo del estado de la vista, cargaremos en la lista como fuente de información Data.groups, mostrando sólo los grupos para crear una vista más simplificada; o Data.items para mostrar toda la información, organizándola mediante Data.groups.