Crear un sitio de localización con Sencha Touch

Lo que vas a crear

Este tutorial lo guiará a través del desarrollo de un sitio web móvil basado en Ubicación utilizando el motor de búsqueda Google Place y Sencha Touch 2.1. Este es un tutorial de dos partes y en esta primera parte aprenderemos cómo crear un proyecto con Sencha cmd, crear un tema genial con SASS / Compass y encontrar servicios cerca de la ubicación del usuario..


1. API de búsqueda de lugar de Google

Google proporciona un conjunto de API para buscar diferentes servicios por tipos y ubicación del usuario. En la actualidad, Google admite un total de 96 tipos de servicios. Hay 30 servicios más que solo se pueden recuperar a través de la búsqueda. Google tiene una lista completa de ellos.

Para acceder a la API de Places, el objetivo principal es registrar la aplicación en la consola API de Google. Una vez que nos autentiquemos, obtendremos una clave de API que se requiere para cada solicitud de API. Google tiene una guía paso a paso.

La API de Google Places utiliza una clave de API para identificar su aplicación. Las claves de API se administran a través de la consola de Google API. Necesitará su propia clave de API antes de poder comenzar a utilizar la API. Para activar la API de Places y crear tu clave:

  1. Visite la Consola de API en https://code.google.com/apis/console e inicie sesión con su cuenta de Google.
  2. Un proyecto por defecto llamado Proyecto API se crea para usted cuando inicia sesión por primera vez en la API Console. Puede utilizar el proyecto o crear uno nuevo haciendo clic en el botón Proyecto API botón en la parte superior de la ventana y seleccionando Crear. Los clientes de Maps API for Business deben usar el proyecto API creado para ellos como parte de la compra de Places for Business..
  3. Haga clic en el Servicios enlace desde el menú de la izquierda.
  4. Haga clic en el Estado cambiar al lado de la API de lugares entrada. El interruptor se desliza a En.
  5. Hacer clic Acceso API Desde la navegación de la izquierda. Su clave está en la lista API simple de acceso sección.

2. Crea y estructura la aplicación

Supongo que tienes un servidor local y la configuración de Sencha está lista. De lo contrario, lea la documentación detallada aquí con todos los pasos. Generamos la aplicación Locator usando este comando dentro de nuestro servidor local..

sencha -sdk / ruta / a / sdk genera la aplicación Locator c: / xampp / htdocs / locator

Una vez que hayamos terminado, abriremos la aplicación en el navegador con la url http: // localhost / locator y ver una aplicación tabulada básica.


Ahora necesitamos estructurar la aplicación con los componentes MVC..

Controladores

  1. App.js

Puntos de vista

  1. Main.js
  2. Categories.js
  3. PlaceList.js

Víveres

  1. Categories.js
  2. Places.js

Modelos

  1. Categoría
  2. Lugar

Una aplicación Sencha puede tener múltiples archivos de controlador. Sin embargo, para una aplicación pequeña como esta, un controlador estará bien. Mantendremos todos los enlaces del evento y la funcionalidad relacionada dentro de este controlador.

Las vistas representan las páginas de la aplicación..

  • Vista principal Funciona como un padre de todas las vistas..
  • Categorías listará todos los servicios que soporta Google.
  • Vista PlaceList mostrará una lista de todos los lugares cercanos a la ubicación del usuario y en función de un servicio en particular.

Como tenemos dos listas, mantenemos dos modelos: Categoría y Lugar. Del mismo modo, dos de almacenamiento. Categorías y Lugares Son necesarios para recuperar y guardar datos relacionados. Necesitamos agregar todos estos detalles de componentes en app.js Para que el motor Sencha pueda cargarlos al inicio..

Ext.Loader.setPath ('Ext': 'touch / src', 'Locator': 'app'); Ext.application (name: 'Locator', requiere: ['Ext.MessageBox', 'Locator.util.Util'], vistas: ['Main', 'Categories', 'PlaceList'], Controles: ['App '], modelos: [' Categoría ',' Lugar '], tiendas: [' Categorías ',' Lugares '], icono: ' 57 ':' recursos / iconos / Icon.png ',' 72 ':' recursos /icons/Icon~ipad.png ',' 114 ':' resources/icons/[email protected] ',' 144 ':' resources/icons/[email protected] ', isIconPrecomposed: true, startupImage : '320x460': 'recursos / inicio / 320x460.jpg', '640x920': 'recursos / inicio / 640x920.png', '768x1004': 'recursos / inicio / 768x1004.png', '748x1024': 'recursos /startup/748x1024.png ',' 1536x2008 ':' resources / startup / 1536x2008.png ',' 1496x2048 ':' resources / startup / 1496x2048.png ', launch: function () // Destruye el elemento #appLoadingIndicator Ext.fly ('appLoadingIndicator'). Destroy (); // Inicializa la vista principal Ext.Viewport.add (Ext.create ('Locator.view.Main'));, onUpdated: function () Ext.Msg .confirm ("Actualización de la aplicación", "Esta aplicación acaba de ser exitosa actualizado a la última versión. ¿Recargar ahora? ", Función (buttonId) if (buttonId === 'yes') window.location.reload ();););

3. Funciones comunes

Para cada aplicación, necesitamos un conjunto de funciones y propiedades comunes que se utilizarán en toda la aplicación. Creamos una clase Singleton de Util para la misma cosa y ponemos el archivo bajo el app / util / directorio. No es necesario que comprenda las funciones de este archivo en este momento. Seguiremos discutiendo estas funciones a medida que avanzamos..

Ext.define ('Locator.util.Util', singleton: true, // Si las vistas de la aplicación tendrán una animación mientras se cambia on = r no enablePageAnimations: true, // la ubicación actual del usuario se guarda aquí UserLocation: null, / / Google place api key API_KEY: 'AIzaSyBmbmtQnXfq22RJhJfitKao60wDgqrC5gA', // Todas las api urls api: (function () // var baseUrl = 'https://maps.googleapis.com/maps/api/place/'; var baseUrl / = 'php / action.php'; return baseUrl: baseUrl, categories: 'resources / data / categories.json', closestPlaces: baseUrl + ", nearBySearch: 'nearbysearch', foto: 'foto', detalles: 'detalles' ) (), // Destruye una vista Sencha destroyCmp: function (child, parent) parent = parent || Ext.Viewport; if (child) Ext.defer (function () parent.remove (child); , Locator.util.Util.animDuration);, // Mostrar alerta de mensaje general showMsg: function (msg, title, cb, scope) if (msg) Ext.Msg.alert (title || 'Error' , msg.toString (), cb || function () , alcance || ventana); devolver esto;, // Animat e el elemento activo showActiveItem: function (parentPanel, childPanel, animation) animation = Ext.apply (type: 'slide', duration: LocatrConfig.amimationDuration, animation || ); if (parentPanel && childPanel) if (this.enablePageAnimations && animation && animation.type) parentPanel.animateActiveItem (childPanel, animation);  else parentPanel.setActiveItem (childPanel);  devuelve esto; , // Mostrar un cuadro de carga en una función showLoading: (panel, doShow, mensaje) panel = panel || Ext.Viewport; if (panel) if (doShow) panel.setMasked (xtype: 'loadmask', mensaje: mensaje || 'Cargando ...');  else panel.setMasked (false);  devuelve esto; , // Poner en mayúscula el primer carácter de cada palabra de una cadena aTitleCase: function (str) if (! Str) return "; return str.replace (/ \ w \ S * / g, function (txt) return txt.charAt (0) .toUpperCase () + txt.substr (1) .toLowerCase ();););

4. Lista de categorías

Establecimos el Principal Vista, que es el envoltorio de todas las vistas. Usamos Navegación Ver para la misma cosa, que es bastante útil para el diseño simple de la tarjeta y la administración del botón Atrás. En el lanzamiento, solo tiene la lista de categorías como su hijo..

/ ** * Vista principal - titular de todas las vistas. * El diseño de la tarjeta por defecto para admitir múltiples vistas como elementos * / Ext.define ('Locator.view.Main', extend: 'Ext.NavigationView', xtype: 'main', config: cls: 'default- bg ', elementos: [xtype:' categories ']);

Ahora la configuración de la aplicación está hecha. Tenemos la clave de la API de Google Places y estamos listos para crear una lista de todos los tipos y mostrarla en la página de inicio. Sin embargo, hay un problema. Google no proporciona una API para recuperar todos estos tipos. Tenemos que crear manualmente un archivo de datos con todos los tipos. He creado un json archivo llamado categorías.json Listar todos los tipos disponibles, y ponerlo dentro de la recursos / datos directorio.

categories: [type: "contabilidad", type: "airport", type: "amusement_park", type: "aquarium", type: "art_gallery", type: "atm" , type: "bakery", type: "bank", type: "bar", type: "beauty_salon", type: "bicycle_store", type: "book_store", type: "bowling_alley", type: "bus_station", type: "cafe", type: "campground", type: "car_dealer", type: "car_rental", type : "car_repair", type: "car_wash", type: "casino", type: "cemetery", type: "church", type: "city_hall", type: " clothing_store ", type:" conveniencia_store ", type:" courthouse ", type:" dentist ", type:" department_store ", type:" doctor ", type:" electrician " , type: "electronics_store", type: "embassy", type: "establishment", type: "finance", type: "fire_station", type: "florist", type: "food", type: "funeral_home", type: "furniture_store", type: "gas_station", type: "general_contractor", type: "grocery_or_supermarket", type : "gym", type: "hair_care", type: "hardware_store", type: "health", type: "hindu_temple", type: "home_goods_store", type : "hospital", type: "insurance_agency", type: "jewelry_store", type: "laundry", type: "lawyer", type: "library", type: " liquor_store ", type:" local_government_office ", type:" locksmith ", type:" lodging ", type:" meal_delivery ", type:" meal_takeaway ", type:" mosque " , type: "movie_rental", type: "movie_theater", type: "moving_company", type: "museum", type: "night_club", type: "painter", type: "park", type: "parking", type: "pet_store", type: "pharmacy", type: "fisioterapeuta", type: "place_of_worship", type : "fontanero", tipo: "police", tipo: "post_office", type: "real_estate_agency", type: "restaurant", type: "roofing_contractor", type: " rv_park ", type:" school ", type:" shoe_store ", type:" shopping_mall ", type:" spa ", type:" stadium ", type:" storage " , type: "store", type: "subway_station", type: "synagogue", type: "taxi_stand", type: "train_station", type: "travel_agency", type: "university", type: "veterinary_care", type: "zoo"]

Categoría Modelo: Modelo / Categoría.js

Ext.define ('Locator.model.Category', extend: 'Ext.data.Model', config: fields: ["type", name: "name", type: "string", convert: function ( v, record) // Convierte a mayúsculas y minúsculas y devuelve el retorno Locator.util.Util.toTitleCase (record.get ('type'). split ('_'). join ("));," size " ]);

La propiedad "nombre" de este modelo usa el mismo valor "tipo" de la categoría. Dado que la mayoría de los tipos tienen un "guión bajo", esta función de conversión crea un valor que omite "_" y convierte la cadena en el título. Entonces, "travel_agency" se convierte en "Agencia de viajes"y lo guardamos bajo la propiedad de nombre de este modelo.

Categorías Tienda: Tienda / Categorías.js

Ext.define ('Locator.store.Categories', extend: 'Ext.data.Store', config: model: 'Locator.model.Category', autoLoad: true, sorters: 'name', grouper: groupFn : function (record) return record.get ('name') [0];, proxy: type: 'ajax', url: Locator.util.Util.api.categories, reader: type: 'json ', rootProperty:' categories ');

Nosotros cargamos automáticamente la tienda porque debería ser la primera solicitud en la aplicación. Usamos una función de agrupador para una lista agrupada, y ordenamos por el primer carácter de cada nombre de servicio.

Categorías Ver: Ver / Categorías.js

La vista de categoría es una lista simple. Utilizamos indexBar y funcionalidad agrupada para acceder fácilmente a todos los tipos.

Ext.define ('Locator.view.Categories', extend: 'Ext.List', xtype: 'categories', config: cls: 'default-bg category-list', itemTpl: 'name', store : 'Categorías', agrupadas: true, indexBar: true, title: Lang.home);

La lista se ve así:



5. Ajustar el tema existente

Podemos agregar ciertos conjuntos de variables preexistentes para cambiar el tema Sencha existente y obtener un nuevo aspecto. El siguiente es el archivo SASS. Si aún no tiene la configuración de SASS, siga esta publicación del blog para obtener una guía paso a paso..

// Definiciones básicas de color $ base-color: # 333; $ base-gradiente: 'mate'; $ de color activo: # 36B8FF; // Estilos de la barra de herramientas $ toolbar-base-color: # 444; // Lista de estilos $ list-header-bg-color: # ABE2FF; @import 'sencha-touch / default / all'; // Puede eliminar cualquiera de los siguientes módulos que // no usa para crear un archivo css más pequeño. @include sencha-panel; @include sencha-buttons; @incluir hoja de sencha; @include sencha-picker; @include sencha-tabs; @include sencha-toolbar; @include sencha-toolbar-forms; @include sencha-indexbar; @include sencha-list; @include sencha-layout; @include sencha-carrusel; @include sencha-form; @include sencha-msgbox; @include sencha-loading-spinner; @include sencha-list-pullrefresh;

Cambiamos el color de la barra de herramientas superior y el color del encabezado de la lista, y agregamos el complemento de la lista.


6. Geolocalización y recuperación de datos API

Una vez que hacemos clic en uno de los elementos de la categoría, desearemos ver todas las empresas cercanas a la ubicación actual del usuario en esa categoría. Debemos seguir este conjunto de tareas:

  1. Recupera la ubicación actual del usuario usando la API de GeoLocation
  2. Con la latitud y la longitud, envíe una solicitud a la API de Google para obtener los datos
  3. Mostrar la página de la lista de lugares

Geolocalización

Podemos usar la función de geolocalización del navegador directamente o usar Sencha Ext.device.Geolocation. Guardamos la latitud y longitud en el Util instancia para uso futuro.

Ext.device.Geolocation.getCurrentPosition (success: function (position) me.util.userLocation = position.coords.latitude + ',' + position.coords.longitude;, failure: function () me.util. showMsg (Lang.locationRetrievalError););

Recuperación de datos

La API de Google Places aún no admite solicitudes JSONP, por lo que no podremos recuperar los datos directamente del lado del cliente. Tenemos que usar un servidor proxy para recuperar los datos. Este problema puede resolverse usando PHP y cURL.

los Config archivo contiene una serie de constantes. Establecemos la URL base de la API, el tipo de salida de datos y los detalles del tamaño de la imagen.

define ("BASE_API_URL", "https://maps.googleapis.com/maps/api/place/"); define ("DATA_OUTPUT_TYPE", "json"); define ("IMAGE_MAX_HEIGHT", 500); define ("IMAGE_MAX_WIDTH", 500);

Locator.php

Esta es una clase de PhP que contiene la funcionalidad para configurar la URL, enviar solicitudes de CURS y recuperar datos..

class Locatr / ** * Configura la url de acuerdo con los parámetros pasados ​​* @return String Una url completa con todas las cadenas de consulta * / función estática privada getFinalUrl () return html_entity_decode (BASE_API_URL. $ _ REQUEST ["action". ". /".DATA_OUTPUT_TYPE. "?". $ _ SERVER ['QUERY_STRING']);  / ** * Una función genérica para enviar todas las solicitudes de cURL * @return String Response para esa solicitud de cURL * / función estática privada sendCurlRequest () // Get cURL resource $ curl = curl_init (); // Establezca algunas opciones. También estamos pasando un agente de usuario aquí curl_setopt_array ($ curl, array (CURLOPT_RETURNTRANSFER => 1, CURLOPT_URL => self :: getFinalUrl) )); // Envía la solicitud y guarda la respuesta a $ resp $ response = curl_exec ($ curl); // Cerrar solicitud para borrar algunos recursos curl_close ($ curl); devuelve $ respuesta;  / ** * Recupera todos los lugares cercanos y una imagen de cada uno si está disponible * @return String Devuelve todos los lugares en json * / public static function getNearBySearchLocations () try $ data = json_decode (self :: sendCurlRequest ()) ; $ item = ""; para ($ i = 0; $ i < count($data -> resultados); $ i ++) $ item = $ data -> resultados [$ i]; if (isset ($ item -> photos)) $ imageUrl = BASE_API_URL. "photo? photoreference =". $ item -> photos [0] -> photo_reference. "& sensor = false & maxheight = 300 & maxwidth = 300 & key =". $ _ GET ["key"]; $ data -> resultados [$ i] -> fotos [0] -> url = $ imageUrl;  devolver json_encode ($ data);  catch (Exception $ e) print "Error en getNearBySearchLocations:". $ e -> getMessage (); 

Aquí está la funcionalidad de cada método en esta clase:

  1. getFinalUrl: Esto configura la URL completa con la URL base, el tipo de datos de respuesta y las cadenas de consulta enviadas desde el lado del cliente. Llamamos a esta función desde el action.php expediente.
  2. sendCurlRequest: Esta es una solicitud básica CURL GET para recuperar los datos. Puedes usar el file_get_contents () Método también para obtener los datos aquí.
  3. getNearBySearchLocations: Esto obtiene los datos de la API de Google para el tipo relacionado dentro de un radio determinado. Sin embargo, hay un truco: Google no pasa las fotos de una empresa con estos datos. En su lugar envían referencias a las imágenes. Necesitas construir una URL con la altura de la imagen, el ancho, la clave API y la referencia de la foto para obtener esa imagen.

    Esta URL se construye con la primera referencia de imagen y se pasa con los datos de respuesta para cada lugar. Esto nos ayuda a mostrar al menos una imagen disponible para cada negocio..

    action.php

    Este archivo solo se usa para llamar al getNearBySearchLocations Función de la clase Locator. Enviamos las solicitudes ajax de nuestro lado del cliente directamente a este archivo.

    include_once 'config.php'; include_once 'Locatr.php'; $ action = $ _REQUEST ["action"]; if (! isset ($ action)) lanzar una nueva excepción ("el parámetro '' action 'no se suministra");  switch ($ action) case "nearbysearch": print Locatr :: getNearBySearchLocations (); descanso; 

    7. Lista de lugares

    Para la lista de lugares, necesitamos una tienda y un modelo similar a la lista de categorías.

    Modelo de lugar: Modelo / lugar

    Ext.define ('Locator.model.Place', extend: 'Ext.data.Model', config: fields: ["formatted_address", "geometry", "icon", "id", "name", " calificación "," referencia "," tipos "," vecindad "," fotos "]);

    Lugares Tienda: Tienda / Lugares

    Ext.define ('Locator.store.Places', extend: 'Ext.data.Store', config: model: 'Locator.model.Place', proxy: type: 'ajax', url: Locator.util .Util.api.nearestPlaces, reader: type: 'json', rootProperty: 'results');

    Controlador principal: Controlador / App.js

    Hasta ahora, no necesitábamos un controlador para ninguna funcionalidad porque la lista de categorías se llenaba automáticamente por su tienda. Ahora necesitamos el controlador para manejar los eventos. Listaremos todos los componentes requeridos bajo la propiedad refs del controlador.

    refs: categoriesList: 'categories', main: 'main', placeList: 'placelist'

    La lista hace clic en evento en controles:

    control: categoriesList: itemtap: 'loadPlaces'

    Al hacer clic en una categoría, queremos mostrar la lista de lugares disponibles en esa categoría. Como comentamos anteriormente, primero buscaremos la ubicación actual del usuario y luego, con la latitud y la longitud, enviaremos una solicitud ajax al archivo action.php. El controlador con el "loadPlaces"La función se ve así:

    Ext.define ('Locator.controller.App', extend: 'Ext.app.Controller', requiere: ['Ext.device.Geolocation', 'Ext.Map'], util: Locator.util.Util, config : refs: categoriesList: 'categories', main: 'main', placeList: 'placelist', control: categoriesList: itemtap: 'loadPlaces', / ** * Recuperar todos los lugares para un particlur category * / loadPlaces: function (list, index, target, record) var me = this, loadPlaces = function () // Mostrar la página de lista de lugares me.showPlaceList (record); // Cargar la tienda con la ubicación del usuario, radius, type y api key store.getProxy (). setExtraParams (location: me.util.userLocation, action: me.util.api.nearBySearch, radius: me.util.defaultSearchRadius, sensor: false, clave: me.util .API_KEY, tipos: record.get ('type')); store.load (function (records) me.util.showLoading (me.getPlaceList (), false););, store = Ext.getStore ('Lugares'); // Si la ubicación del usuario ya no está establecida, consíguela. // Si no, cargue los lugares para la ubicación del usuario guardado si (! Me.uti l.userLocation) Ext.device.Geolocation.getCurrentPosition (success: function (position) me.util.userLocation = position.coords.latitude + ',' + position.coords.longitude; loadPlaces (); , failure: function () me.util.showMsg (Lang.locationRetrievalError); );  else // Limpie el almacén si hay algún almacén de datos anterior.removeAll (); loadPlaces (); , / ** * Mostrar lista de lugares * / showPlaceList: function (record) this.getMain (). Push (xtype: 'placelist', title: record.get ('name')); );

    Vista de lista de lugares: Ver / Lista de lugares

    los PlaceList La vista es también una lista simple. Usamos XTemplate aquí para usar algunas funciones de filtrado. los obtener la imagen La función recibe la imagen del negocio. Si la imagen no está disponible, devuelve el ícono para ese negocio.

    Ext.define ('Locator.view.PlaceList', extend: 'Ext.List', xtype: 'placelist', config: cls: 'default-bg placelist', store: 'Places', emptyText: Lang.placeList .emptyText, itemTpl: Ext.create ('Ext.XTemplate', '[this.getImage (valores)]', '
    ','
    nombre
    ','
    vecindad
    ',' rating: this.getRating ','
    ', // Devuelve la imagen comercial si está disponible. De lo contrario, muestra el icono disponible para esa empresa. GetImage: function (data) if (data.photos && data.photos.length> 0) return '
    '; regreso '
    '; , // Muestra una calificación basada en estrellas. Los detalles funcionales se dan en la clase Util Util getRating: function (rating) return Locator.util.Util.getRating (rating); ));

    Obtenemos una calificación de cero a cinco para las empresas. En lugar de mostrar el número de clasificación, podemos escribir una función simple para mostrar las calificaciones como estrellas. Añadimos el getRating función a la util archivo, que se puede utilizar dentro de las funciones de esta plantilla PlaceList:

    Hay tres imágenes: no-star, half-star y full-star. El CSS se da a continuación:

    getRating: function (rating, max, hideRatingValue) if (rating! == undefined) var str = '
    '; rating = parseFloat (rating); max = max || 5; // Dividimos la calificación en una parte hasta el valor máximo para (var i = 1; i < = max; i++) // For each 1 rating, add a full star if (i < = rating) str += '
    '; if (i> rating) // Si el rating de la parte es un decimal entre 0 y 1, agregue media estrella if (rating% 1! == 0 &&; (i - rating) < 1) str += '
    '; // Para todo el valor de calificación de parte 0, no agregue ninguna estrella else str + = '
    '; if (! hideRatingValue) str + = '
    '+ calificación +'
    '; str + = '
    '; volver str return Lang.noRating;

    Calificación CSS:

    .calificaciones desbordamiento: auto;  .ratings div.star float: left; altura: 14px; ancho: 14px; tamaño de fondo: 12px! importante; posición de fondo: 50%;  .ratings .full-star background: url (… /images/full_star.png) no se repite;  .ratings .half-star background: url (… /images/half_star.png) no se repite;  .ratings .no-star background: url (… /images/no_star.png) no se repite;  .ratings .value float: left; tamaño de fuente: 13px; font-weight: negrita; margen izquierdo: 5px; 

    Aquí está la final. PlaceList ver.


    CSS para la página PlaceList:

    / ****************************** Lista de lugares ***************** ************* / .placelist.x - list - emptytext font - size: 14px; color: #fff; relleno: 20px;  .x - list.placelist.x - list - item.x - dock - horizontal border: 0! important;  .x - list.placelist.x - list - item.item / * background: rgba (255, 255, 255, 0.8); tamaño de fuente: 14px; relleno: 8px; * / / * fondo: rgba (255, 255, 255, 0.8); * / background: -webkit - gradiente (lineal, izquierda superior, izquierda inferior, color - detener (0%, #ffffff), color - detener (47%, # f6f6f6), color - detener (100%, # editado)); / * Chrome, Safari4 + * / background: -webkit - linear - gradient (top, #ffffff 0%, # f6f6f6 47%, #ededed 100%); / * Chrome10 +, Safari5.1 + * / font - tamaño: 14px; borde - radio: 5px; relleno: 8px; - webkit - caja - sombra: 0 0 10px 2px rgba (0, 0, 0, 0.6); relleno - derecho: 82px;  .x - list.placelist.x - list - item.item.name fuente - peso: negrita; margen: 3px 0 8px 0;  .x - list.placelist.x - list - item.item.vicinity font - size: 12px; color: # 222; margen inferior: 10px;  .x-list.placelist .x-list-item .item .rating  .x-list.placelist .x-list-item .photo, .x-list.placelist .x-list-item .icon-wrapper posición: absoluta; pantalla: -webkit-box; -webkit-box-align: center; -webkit-box-pack: centro; derecha: 25px; arriba: 6px;  .x-list.placelist .x-list-item .photo img max-width: 75px; altura máxima: 63px; borde: 2px blanco sólido; -webkit-box-shadow: 0 0 5px 0px rgba (0, 0, 0, 0.5); fondo: negro;  .x-list.placelist .x-list-item .icon-wrapper background: # 960000; borde: 2px blanco sólido; - webkit - caja - sombra: 0 0 5px 0px rgba (0, 0, 0, 0.5);  .x - list.placelist.x - list - item.icon width: 50px; altura: 50px; fondo: blanco; - webkit - máscara - imagen: url (http: //maps.gstatic.com/mapfiles/place_api/icons/restaurant-71.png); - webkit - máscara - tamaño: 35px; - webkit - máscara - repetir: no - repetir; - webkit - máscara - posición: 50%;  / ****************************** Lista de lugares ENDS *************** *************** /  

    Podemos agregar un complemento de extracción para actualizar a esta lista de lugares. Solo agregue el siguiente código en el PlaceList configuración de la matriz.

    complementos: [xclass: 'Ext.plugin.PullRefresh', pullRefreshText: Lang.placeList.pullToRefresh]
    Y debido a que estamos utilizando un fondo oscuro, necesitamos cambiar un poco el css para actualizar. Entonces, agregue el siguiente css en el archivo locator.css:
    / * Tire para actualizar el complemento * / .x-list-pullrefresh color: #fff;  .X-list-pullrefresh flecha -webkit - Máscara: Centro url (datos: image / png; base64, iVBORw0KGgoAAAANSUhEUgAAACgAAAA8CAYAAAAUufjgAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAjFJREFUeNrsmU8oREEYwOexdtNuKBfFwdVhCyfuysnFiXISS + 1BLopyUpKLXETkRLaUi1LK3Q2lpPbiQLnIn03a / Hm + ++ z86Ttv0zM bfbOar36Hbad5v535Zp7v47iuy0wOpyoEHccRHV9L9NxPkUE / bhKCOKiOSPAdn69DsJ5I8E2HYA0QJRJ8Bb50CDYRCT7pEMQD0kwk + + CByUFQEW4gE73UIhoA2IsFb4ENEMCQ5MdU1IxwygpT3oKNLMGyyYFVscdhusc8tDpu xRG7xf95BW0O2kNiV1AgIvaQ2BzUJNgJNJYZGyUU7OG1cal4Bi68oqkDPszy2teEwJp5Cdyu / lZ1g8CwIYJ7wEF + 2YmrNw90Byx3BizgKhaqizEP1wg7CLLxCEzy / CtauMeBlQDyEfNuGrgU6SyM8F9SyVgHdmRaH6tAb4XkToEp2d4M5mOK0TWMigU2koa8vJMRZPxEb2ss2LEVPMpPLlMRxBgDZjQJLgNbxb6Uab9tAn3EcifAeKkBMoLY + j0GWonk7oB + + lmsFkwhidAGHBPmIeTcAnJcbKCuIMQEs hScAzZEBqoIYuzyFVCJI36lMJ2CDfxibZeUu + EX / 4uMIFP8ZyLejxkgK0hG5a8kP4IYSZbr1IuQVHmAX0HGX4VuGfZVJ6cQxPd1uoRcWqDW0SroFVzZAnJZ / h0LWhAjUUAw4XdSSsH8fExRTEgtGAOuOTETBb16Jk412e + bxOSwglYw6PgWYABvLk8P7zGJFwAAAABJRU5ErkJggg == ) no - repetir; fondo: #fff; 

    Aquí va:



    Conclusión

    Esta es la primera parte del tutorial. Creamos una lista de servicios provistos por la API de Google Places y luego para un servicio en particular, y mostramos una lista de todos los lugares cercanos. En la siguiente y última parte de este tutorial, cubriremos la siguiente funcionalidad:

    1. Mostrando todos los lugares para una categoría en Google Maps
    2. Mostrando los detalles de cada lugar. Esto incluirá mostrar un mapa individual para un lugar determinado, crear una galería de fotos basada en Sencha en mosaico, un carrusel de imágenes a pantalla completa y una lista de reseñas..

    Sencha es actualmente una de las bibliotecas móviles basadas en HTML5 más sólidas. Una vez que lo configure, podrá escribir excelentes aplicaciones móviles sin problemas. Estas aplicaciones se pueden usar como sitios web móviles o se pueden incluir en Phonegap para crear aplicaciones híbridas de iOS y Android.


    ACTUALIZAR!

    La segunda parte de este tutorial está disponible ahora. Encuéntrelo aquí: cree un sitio de localización con Sencha Touch - Visualización de ubicaciones.