Creați un site de conștientizare a locației cu Sencha Touch

Ce veți crea

Acest tutorial vă va îndruma prin dezvoltarea unui site web mobil bazat pe locație utilizând motorul de căutare Google Place și Sencha Touch 2.1. Acesta este un tutorial în două părți și în această primă parte vom învăța cum să creați un proiect cu ajutorul lui Sencha cmd, să creați o temă interesantă utilizând SASS / Compass și să găsiți servicii aproape de locația utilizatorului.


1. API Google Search Search

Google oferă un set de API-uri pentru căutarea diferitelor servicii pe tipuri și pe locația utilizatorilor. În prezent, Google acceptă un total de 96 tipuri de servicii. Există încă 30 de servicii care pot fi preluate numai prin căutare. Google are o listă completă a acestora.

Pentru a accesa API-ul Locații, obiectivul principal este înregistrarea aplicației la consola API Google. Odată ce ne autentificăm, vom obține o cheie API necesară pentru fiecare solicitare API. Google are un ghid pas cu pas.

API-ul Google Locații utilizează o cheie API pentru a identifica aplicația dvs. Cheile API sunt gestionate prin Consola API Google. Veți avea nevoie de cheia API proprie pentru a putea începe să utilizați API-ul. Pentru a activa API-ul Places și a crea cheia:

  1. Vizitați Consola API la https://code.google.com/apis/console și conectați-vă cu Contul dvs. Google.
  2. Un proiect implicit numit Proiectul API este creat pentru dvs. atunci când vă conectați pentru prima oară la Consola API. Puteți utiliza proiectul sau creați unul nou făcând clic pe Proiectul API butonul din partea de sus a ferestrei și selectarea Crea. API-urile Maps API pentru companii trebuie să utilizeze proiectul API creat pentru aceștia, ca parte a achiziției Locații pentru companii.
  3. Apasă pe Servicii din meniul din stânga.
  4. Apasă pe stare comutați lângă Locații API intrare. Comutatorul trece în poziția Pe.
  5. Clic Acces API din navigarea din stânga. Cheia este listată în Acces simplu API secțiune.

2. Creați și structurați aplicația

Presupun că aveți un server local și că configurația Sencha este terminată. Dacă nu, treceți prin documentația detaliată aici cu toți pașii. Generăm aplicația Locator folosind această comandă în interiorul serverului nostru local.

sencha -sdk / path / to / sdk genera aplicația Locator c: / xampp / htdocs / locator

După ce terminăm, vom deschide aplicația în browser cu ajutorul adresei URL http: // localhost / Locator și vedeți o aplicație tabulară de bază.


Acum trebuie să structurăm aplicația cu componentele MVC.

controlerele

  1. App.js

Vizualizări

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

Magazine

  1. Categories.js
  2. Places.js

modele

  1. Categorie
  2. Loc

O aplicație Sencha poate avea mai multe fișiere controler. Cu toate acestea, pentru o aplicație mică ca aceasta, un controler va fi în regulă. Vom păstra toate legăturile evenimentului și funcționalitatea conexă în interiorul acestui controler.

Vizualizările reprezintă paginile aplicației.

  • Vedere principală funcționează ca un părinte al tuturor opiniilor.
  • Categorii va lista toate serviciile pe care Google le acceptă.
  • Afișare locație va afișa o listă a tuturor locurilor din apropierea locației utilizatorului și pe baza unui anumit serviciu.

Din moment ce avem două liste, menținem două modele: Categorie și Loc. În mod similar, două depozitare Categorii și Locuri sunt necesare pentru recuperarea și salvarea datelor conexe. Trebuie să adăugăm toate aceste detalii despre componente app.js astfel încât motorul Sencha le poate încărca la început.

Ext.Loader.setPath ('Ext': 'touch / src', 'Locator': 'app')); Ext.application (nume: 'Locator', necesită: ['Ext.MessageBox', 'Locator.util.Util'], vizualizări: ['Main', 'Categories','ListList ' '], modele: [' Categorie ',' Loc '], magazine: [' Categorii ',' Locuri '], icon: ' 57 ':' resources / icons / /icons/Icon.ipad.png ',' 114 ':' resources/icons/[email protected] ',' 144 ':' resources/icons/[email protected] ', isIconPrecompus: true, startupImage : '320x460': 'resurse / startup / 320x460.jpg', '640x920': 'resurse / startup / 640x920.png', '768x1004': 'resources / startup / 768x1004.png', '748x1024' /startup/748x1024.png ',' 1536x2008 ':' resurse / startup / 1536x2008.png ',' 1496x2048 ':' resurse / startup / 1496x2048.png ', lansare: function () // Distruge elementul #appLoadingIndicator Ext.fly ('appLoadingIndicator') distruge (); // Inițializează vizualizarea principală Ext.Viewport.add (Ext.create ('Locator.view.Main')) ;, peUpdate: function () Ext.Msg .confirm ("Actualizare aplicație", "Această aplicație tocmai a fost reușită actualizat la cea mai recentă versiune. Reîncărcați acum? ", Funcția (buttonId) if (buttonId === 'da') window.location.reload ();););

3. Funcții comune

Pentru fiecare aplicație, avem nevoie de un set de funcții și proprietăți comune care vor fi utilizate în întreaga aplicație. Cream o clasă Util singleton pentru același lucru și a pus fișierul sub app / UTIL / director. Nu aveți nevoie să înțelegeți funcțiile acestui fișier în prezent. Vom continua să discutăm despre aceste funcții pe măsură ce avansăm.

Ext.define ('Locator.util.Util', singleton: true, // Dacă vizualizările aplicației vor avea o animație în timp ce se schimbă on = r nu enablePageAnimations: true, // Locația curentă a utilizatorului este salvată aici userLocation: null, / Google loc API cheie API_KEY: 'AIzaSyBmbmtQnXfq22RJhJfitKao60wDgqrC5gA', // Toate api urls api: (functie () // var baseUrl = 'https://maps.googleapis.com/maps/api/place/'; var baseUrl = 'php / action.php'; return baseUrl: baseUrl, categorii: 'resources / data / categories.json', nearestPlaces: baseUrl + ', closeBySearch: )) (), // Distruge o imagine Sencha viewCmp: functie (copil, parinte) parent = parent || Ext.Viewport; daca (copil) Ext.defer (function () parent.remove (child); , // Afișați alerta generală a mesajului showMsg: funcția (msg, title, cb, scope) if (msg) Ext.Msg.alert (title || 'Eroare' , msg.toString (), cb || function () , domeniul de aplicare ||); return this;, // Animat e elementul activ showActiveItem: funcție (parentPanel, childPanel, animație) animation = Ext.apply (type: 'slide', duration: LocatrConfig.amimationDuration, animație || ); dacă (parentPanel && childPanel) dacă (this.enablePageAnimations && animație && animation.type) parentPanel.animateActiveItem (childPanel, animație);  altceva parentPanel.setActiveItem (childPanel);  returnați acest lucru; , // Afișați o casetă de încărcare pe o funcție de afișareLoading: (panou, doShow, mesaj) panel = panel || Ext.Viewport; dacă (panoul) if (doShow) panel.setMasked (xtype: 'loadmask', mesaj: message || 'Loading ...');  altfel panel.setMasked (false);  returnați acest lucru; , // capitalizați primul caracter al fiecărui cuvânt al unui șir toTitleCase: funcția (str) if (! Str) return "; return str.replace (/ \ w \ S * / g, funcția (txt) txt.charAt (0) .toUpperCase () + txt.substr (1) .toLowerCase ();););

4. Lista de categorii

Am creat Principal vizualizare, care este învelișul tuturor opiniilor. Folosim Navigare Vizualizați același lucru, ceea ce este destul de util pentru gestionarea simplă a layout-ului cardului și a butonului de returnare. La lansare, are doar lista de categorii ca și copilul său.

/ ** * Vizualizarea principală - titularul tuturor vizualizărilor. * Layout de card în mod implicit pentru a suporta mai multe vizualizări ca elemente * / Ext.define ('Locator.view.Main', extinde: 'Ext.NavigationView', xtype: 'main', config: cls: bg ', elemente: [xtype:' categories ']);

Acum se face instalarea aplicației. Avem cheia API pentru Google Locații și suntem gata să creăm o listă cu toate tipurile și să o afișăm în pagina de pornire. Există însă o problemă. Google nu furnizează un API pentru recuperarea tuturor acestor tipuri. Trebuie să creați manual un fișier de date care să includă toate tipurile. Am creat o JSON fișier numit categories.json listați toate tipurile disponibile și puneți-o în interiorul resurse / date director.

Categorii: [tip: "contabilitate", tip: "aeroport", tip: "amusement_park", tip: "acvariu", tip: "art_gallery", tip: "atm" , tip: "brutărie", tip: "bancă", tip: "bar", tip: "beauty_salon", tip: "bicycle_store", tip: "BOOK_STORE", tip: "bowling_alley", tip: "bus_station", tip: "cafe", tip: "campground", tip: "car_dealer", tip: "car_rental", tip : "car_repair", tip: "car_wash", tip: "cazinou", tip: "cimitir", tip: "biserică", tip: "city_hall", tip:“ clothing_store ", tip:" convenience_store ", tip:" courthouse ", tip:" dentist ", tip:" department_store ", tip:" doctor ", tip:" electrician“ , tip: "electronics_store", tip: "ambasadă", tip: "unitate", tip: "finance", tip: "fire_station", tip: "florar", tip: "produs alimentar", tip: "funeral_home", tip: "furniture_store", tip: "gas_station", tip: "general_contractor", tip: "grocery_or_supermarket", tip : "sală de sport", tip: "hair_care", tip: "hardware_store", tip: "sănătate", tip: "hindu_temple", tip: "home_goods_store", tip : "Spital", tip: "insurance_agency", tip: "jewelry_store", tip: "rufe", tip: "avocat", tip: "bibliotecă", tip:“ liquor_store ", tip:" local_government_office ", tip:" lăcătuș ", tip:" cazare ", tip:" meal_delivery ", tip:" meal_takeaway ", tip:" moschee“ , tip: "movie_rental", tip: "movie_theater", tip: "moving_company", tip: "muzeu", tip: "night_club", tip: "pictor", tip: "parc", tip: "parcare", tip: "pet_store", tip: "farmacie", tip: "fizioterapeut", tip: "place_of_worship", tip : "instalator", tip: "poliție", tip: "post_office", tip: "real_estate_agency", tip: "restaurant", tip: "roofing_contractor", tip:“ rv_park ", tipul:" școală ", tip:" shoe_store ", tip:" shopping_mall ", tip:" spa ", tip:" stadion ", tip:" stocare“ , tip: "store", tip: "subway_station", tip: "sinagogă", tip: "taxi_stand", tip: "train_station", tip: "travel_agency", tip: "universitate", tip: "veterinary_care", tip: "zoo"]

Categorie Model: Model / Categorie.js

Ext.define ('Locator.model.Category', extinde: 'Ext.data.Model', config: fields: ["type", nume: "name", type: "string", convert: v, record) // Convertește la cazul titlu și întoarce returul Locator.util.Util.toTitleCase (record.get ('type') split ('_'). ]);

Proprietatea "nume" a acestui model utilizează aceeași valoare "tip" a categoriei. Deoarece majoritatea tipurilor au o "subliniere", această funcție de conversie creează o valoare care omite "_" și convertește șirul în cazul titlurilor. Astfel, "travel_agency" devine "Agentie turistica"și îl salvăm sub proprietatea numelui acestui model.

Categorii Magazin: Magazin / Categorii.js

Ext.define ('Locator.store.Categories', extinde: 'Ext.data.Store', config: model: 'Locator.model.Category', autoLoad: true, sortare: 'name', grouper: groupFn : functie (inregistrare) return record.get ('nume') [0];, proxy: type: 'ajax', url: Locator.util.Util.api.categories, reader: type: ', rootProperty:' categorii ');

Încărcăm automat magazinul, deoarece ar trebui să fie prima cerere din aplicație. Utilizăm o funcție de grouper pentru o listă grupată și sortează după primul caracter al fiecărui nume de serviciu.

Categorii View: View / Categories.js

Vizualizarea categoriei este o listă simplă. Utilizăm indexBar și funcționalitatea grupată pentru a avea acces ușor la toate tipurile.

Ext.define ('Locator.view.categories', extindeți: 'Ext.List', xtype: 'categories', config: cls: 'default-bg category-list', itemTpl: 'name' : "Categorii", grupate: true, indexBar: true, title: Lang.home);

Lista arată astfel:



5. Ajustarea temei existente

Putem adăuga anumite seturi de variabile pre-existente pentru a schimba tema actuală a Sencha și pentru a obține un aspect nou. Următorul este fișierul SASS. Dacă nu aveți deja instalat SASS, urmați acest post de blog pentru un ghid pas cu pas.

// Definiții de bază ale culorii $ base-color: # 333; $ gradient de bază: "mat"; $ active-color: # 36B8FF; // stiluri bara de instrumente $ bara de instrumente-bază-culoare: # 444; // Stiluri listă $ list-header-bg-color: # ABE2FF; @import "sencha-touch / implicit / toate"; // Puteți elimina oricare dintre următoarele module pe care nu le / o utilizați pentru a crea un fișier css mai mic. @ include sencha-panel; @ include butoane sencha; @ include sencha-foaie; @ include sencha-picker; @ includeți tabele sencha; @ include sencha-toolbar; @ includeți formularele de bare de instrumente sencha; @ include sencha-indexbar; @ include sencha-list; @ include sencha-layout; @ include carusel sencha; @ includeți forma sencha; @include sencha-msgbox; @ include sencha-loading-spinner; @ include sencha-list-pullrefresh;

Schimbați culoarea barei de instrumente de top și listați culoarea antetului și adăugați pluginul de listă mix-in.


6. Geolocalizarea și preluarea datelor API

După ce dăm clic pe unul dintre elementele categoriei, vom dori să vedem toate companiile din apropierea locației curente a utilizatorului în acea categorie. Trebuie să urmăm acest set de sarcini:

  1. Obțineți locația curentă a utilizatorului utilizând API-ul GeoLocation
  2. Cu latitudinea și longitudinea, trimiteți o solicitare API-ului Google pentru a prelua datele
  3. Afișați pagina cu lista locurilor

Localizarea geografică

Putem folosi fie funcția de geolocalizare a navigatorului direct, fie folosim Sencha Ext.device.Geolocation. Salvăm latitudinea și longitudinea în UTIL exemplu pentru utilizare ulterioară.

Ext.device.Geolocation.getCurrentPosition (succes: funcție (poziție) me.util.userLocation = position.coords.latitude + ',' + position.coords.longitude;, eșec: function () me.util. showMsg (Lang.locationRetrievalError););

Recuperare de date

API-ul Google Locații nu acceptă încă solicitări JSONP, deci nu vom putea să preluăm datele direct din partea clientului. Trebuie să folosim un server proxy pentru a prelua datele. Această problemă poate fi rezolvată folosind PHP și cURL.

config fișierul deține un număr de constante. Am setat urlul API de bază, tipul de ieșire a datelor și detaliile dimensiunii imaginii.

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

Locator.php

Aceasta este o clasă PhP care deține funcționalitatea pentru setarea adresei URL, trimiterea cererilor cURL și recuperarea datelor.

clasa Locatr / ** * Setează urlul conform parametrilor parcurși * @return String Un url complet cu toate șirurile de interogare * / funcția statică privată getFinalUrl () retur html_entity_decode (BASE_API_URL. $ REQUEST ["action"]. / "DATA_OUTPUT_TYPE". "" $ _ SERVER ['QUERY_STRING']);  / ** * O funcție generică pentru a trimite toate cererile cURL * @return String Response pentru acea solicitare cURL * / funcția statică privată sendCurlRequest () // Obținere resursă cURL $ curl = curl_init (); // Setați câteva opțiuni - trecem și într-un useragent aici curl_setopt_array ($ curl, array (CURLOPT_RETURNTRANSFER => 1, CURLOPT_URL => auto :: getFinalUrl (), CURLOPT_SSL_VERIFYPEER => false, CURLOPT_USERAGENT = )); // Trimiteți cererea și salvați răspunsul la $ resp $ response = curl_exec ($ curl); // Închideți solicitarea de curățare a unor resurse curl_close ($ curl); returnați răspunsul $;  / ** * Returnează toate locurile din apropiere și o imagine a fiecăruia dacă este disponibil * @return String Returnează toate locurile în json * / funcția statică publică getNearBySearchLocations () try $ data = json_decode (self :: sendCurlRequest () ; $ item = ""; pentru ($ i = 0; $ i < count($data -> rezultate); $ i ++) $ articol = $ date -> rezultate [$ i]; dacă (isset ($ item -> photos)) $ imageUrl = BASE_API_URL. "photo = photoreference =". $ item -> photos [0] -> photo_reference. "& Senzor = false & maxheight = 300 & maxwidth = 300 & = cheie" $ _ GET [ "cheie"].; $ date -> rezultate [$ i] -> fotografii [0] -> url = $ imageUrl;  returnează json_encode ($ data);  captură (Excepție $ e) print "Eroare la getNearBySearchLocations:". $ e -> getMessage (); 

Iată funcționalitatea fiecărei metode din această clasă:

  1. getFinalUrl: Setează adresa URL completă cu adresa URL de bază, tipul de date de răspuns și cururile de interogare trimise de la client. Se numește această funcție din action.php fişier.
  2. sendCurlRequest: Aceasta este o cerere CURL GET de bază pentru preluarea datelor. Puteți utiliza funcția file_get_contents () precum și pentru obținerea datelor aici.
  3. getNearBySearchLocations: Aceasta preluă datele de la Google API pentru tipul asociat într-o anumită rază. Cu toate acestea, există un truc: Google nu transmite fotografiile unei companii cu aceste date. În schimb, trimite trimiteri la imagini. Trebuie să construiți o adresă URL cu înălțimea, lățimea, cheia API și referința fotografiei pentru a obține imaginea respectivă.

    Această adresă URL este construită cu prima referință de imagine și transmisă cu datele de răspuns pentru fiecare loc. Acest lucru ne ajută să afișăm cel puțin o imagine disponibilă pentru fiecare afacere.

    action.php

    Acest fișier este doar folosit pentru a apela getNearBySearchLocations funcția clasei Locator. Trimiteți cererile ajax de la clientul nostru direct la acest fișier.

    include_once 'config.php'; include_once 'Locatr.php'; $ action = $ _REQUEST ["acțiunea"]; dacă (! isset ($ action)) aruncați o excepție nouă (parametrul "acțiune" nu este furnizat ");  comutare ($ action) case "nearbysearch": print Locatr :: getNearBySearchLocations (); pauză; 

    7. Lista locurilor

    Pentru lista de locuri, avem nevoie de un magazin și un model similar cu lista de categorii.

    Modelul locului: model / loc

    Ext.define ('Locator.model.Place', extindeți: 'Ext.data.Model', config: fields: ["formatted_address", "geometry", "icon", "id", " evaluare "," referință "," tipuri "," vecinătate "," fotografii "]);

    Stocarea locațiilor: Stocare / Locații

    Ext.define ('Locator.store.Places', extindeți: 'Ext.data.Store', config: model: 'Locator.model.Place', proxy: type: 'ajax', url: Locator.util .Util.api.nearestPlaces, cititor: type: 'json', rootProperty: 'rezultate');

    Controler principal: Controler / App.js

    Până acum, nu am avut nevoie de un controler pentru nici o funcționalitate, deoarece lista categoriilor a fost populată automat de magazinul său. Acum avem nevoie de controler pentru a face față evenimentelor. Vom lista toate componentele necesare sub proprietatea proprietarului refs.

    refs: categoriesList: 'categorii', principala: 'main', placeList: 'placelist'

    Evenimentul cu clicuri din listă în comenzi:

    control: categoriesList: itemtap:'loadPlaces '

    Când faceți clic pe o categorie, dorim să afișăm lista locurilor disponibile în acea categorie. Așa cum am discutat mai devreme, mai întâi vom prelua locația curentă a utilizatorului și apoi, cu latitudinea și longitudinea, vom trimite o cerere ajax la fișierul action.php. Controlorul cu "loadPlaces"funcționează astfel:

    Ext.define ('Locator.controller.App', extinde: 'Ext.app.Controller', necesită: ['Ext.device.Geolocation', 'Ext.Map'], util: Locator.util.Util, config : categoriesList: categoriesList: 'categories', main: 'main', placeList: 'listă de locuri', control: categoriesList: itemtap:'loadPlaces ', / ** * categorie * / loadPlaces: functie (lista, index, tinta, inregistrare) var me = this, loadPlaces = function () // Afiseaza pagina cu lista locurilor me.showPlaceList (inregistrare); // Incarca magazinul cu locatia utilizatorului, (location: me.util.userLocation, acțiune: me.util.api.nearBySearch, raza: me.util.defaultSearchRadius, senzor: false, key: me.util .API_KEY, tipuri: record.get ('type')); store.load (funcția (înregistrări) me.util.showLoading (me.getPlaceList (), false);)); ("Locații"); // Dacă locația utilizatorului nu este deja setată, preluați-o. // Încărcați în alt mod locurile pentru locația utilizatorului salvat dacă (! Me.uti l.userLocation) Ext.device.Geolocation.getCurrentPosition (succes: funcție (poziție) me.util.userLocation = position.coords.latitude + ',' + position.coords.longitude; loadPlaces (); , eșec: funcția () me.util.showMsg (Lang.locationRetrievalError); );  altceva // Curățați magazinul dacă există date anterioare store.removeAll (); loadPlaces (); , / ** * Afișează lista locurilor * / showPlaceList: funcția (record) this.getMain () push (xtype: 'placelist', title: record.get ('name')); );

    Afișarea listei de locuri: Vizualizare / listă loc

    PlaceList vizualizare este, de asemenea, o listă simplă. Folosim XTemplate aici pentru a folosi anumite funcții de filtrare. getImage funcția primește imaginea afacerii. Dacă imaginea nu este disponibilă, aceasta returnează pictograma pentru afacerea respectivă.

    Ext.define ('Locator.view.PlaceList', extinde: 'Ext.List', xtype: 'listă de locuri', config: cls: 'default-bg placelist', magazin: 'Places', emptyText: Lang.placeList .emptyText, itemTpl: Ext.create ('Ext.XTemplate', '[this.getImage (valori)]', '
    ","
    Nume
    ","
    apropiere
    ',' rating: this.getRating ','
    ', // Returnează imaginea de afacere dacă este disponibilă. Altfel arata pictograma disponibila pentru acea afacere getImage: function (data) if (data.photos && data.photos.length> 0) return '
    „; întoarcere '
    „; , // Afișează o evaluare bazată pe stele. Detaliile funcționale sunt date în clasa Util getRating: funcție (evaluare) return Locator.util.Util.getRating (evaluare); ));

    Avem un rating de la zero la cinci pentru companii. În loc să arătăm numărul de rating, putem scrie o funcție simplă pentru a afișa evaluările ca stele. Adăugăm getRating funcția la UTIL fișierul, care poate fi utilizat în interiorul funcțiilor de șablon PlaceList:

    Există trei imagini: nu-stea, jumătate de stea și cu stea întreagă. CSS este prezentat mai jos:

    getRating: funcție (rating, max, hideRatingValue) if (evaluare! == undefined) var str = '
    „; rating = parseFloat (evaluare); max = max || 5; // Împărțim evaluarea într-o parte până la valoarea maximă pentru (var i = 1; i < = max; i++) // For each 1 rating, add a full star if (i < = rating) str += '
    „; dacă (i> rating) // Dacă ratingul de parte este o zecimală între 0 și 1, adăugați o jumătate de stea dacă (rating% 1! == 0 &&; < 1) str += '
    „; // Pentru orice valoare de rating a piesei 0, nu adăugați altă stea str + = '
    „; dacă (! hideRatingValue) str + = '
    "+ evaluare +"
    „; str + = '
    „; str. invers; returnați Lang.noRating;

    Evaluare CSS:

    .evaluări overflow: auto;  .ratings div.star float: left; înălțime: 14px; lățime: 14px; dimensiune de fundal: 12px! important; pozitie fundal: 50%;  .ratings .full-star (fundal: url (... /images/full_star.png) no-repeat;  .ratings .half-star background: url (... /images/half_star.png) nu-repeta;  .ratings .no-stea background: url (... /images/no_star.png) nu-repeta;  .ratings .value float: left; font-size: 13px; font-weight: bold; margin-stânga: 5px; 

    Aici este finala PlaceList vedere.


    CSS pentru pagina de locație:

    / ****************************** Lista locurilor ***************** ************* / .loclist.x - list - emptytext font - size: 14px; culoare: #fff; padding: 20px;  .x - listă.locație.x - listă - item.x - doc - orizontal graniță: 0! important;  .x - list.placelist.x - list - item.item / * fundal: rgba (255, 255, 255, 0.8); font-size: 14px; * / fundal: -webkit - gradient (liniar, stânga sus, jos stânga, culoare - stop (0%, #ffffff), culoare - stop (47%, # f6f6f6), oprire culori (100%, #ededed)); / * Chrome, Safari4 + * / fundal: -webkit - gradient liniar (top, #ffffff 0%, # f6f6f6 47%, #ededed 100%); / * Chrome10 +, Safari5.1 + / / font - dimensiune: 14px; frontieră - rază: 5px; padding: 8px; - webkit - caseta - umbra: 0 0 10px 2px rgba (0, 0, 0, 0.6); umplutură - dreapta: 82px;  .x - listă.locație.x - listă - element.it.name font - greutate: bold; margine: 3px 0 8px 0;  .x - list.placelist.x - list - item.item.vicinity font - size: 12px; culoare: # 222; margin-bottom: 10px;  .x-list.listul .x-list-item .item .rating  .x-lista.localizare listă .x-list-item .photo, .x-list.placelist .x-list-item .icon-wrapper poziție: absolută; afișare: -webkit-box; -webkit-box-align: centru; -webkit-box-pack: centru; dreapta: 25px; top: 6px;  .x-list.placelist .x-list-item .fotografie img max-width: 75px; max-height: 63px; margine: 2 pix solid alb; -webkit-box-shadow: 0 0 5px 0px rgba (0, 0, 0, 0.5); fundal: negru;  .x-list.placelist .x-list-item .icon-wrapper fundal: # 960000; margine: 2 pix solid alb; - webkit - caseta - umbra: 0 0 5px 0px rgba (0, 0, 0, 0.5);  .x - listă. listlist.x - listă - item.icon width: 50px; înălțime: 50px; fundal: alb; - webkit - mască - imagine: url (http: //maps.gstatic.com/mapfiles/place_api/icons/restaurant-71.png); - webkit - mască - dimensiune: 35px; - webkit - mască - repetați: nu - repetați; - webkit - mască - poziție: 50%;  / ****************************** Lista locurilor ENDS *************** *************** /  

    Putem adăuga un plugin pentru tragere-reîmprospătare la această listă de locații. Doar adăugați codul de mai jos în PlaceList configurare array.

    pluginuri: [xclass: 'Ext.plugin.PullRefresh', pullRefreshText: Lang.placeList.pullToRefresh]
    Și pentru că folosim un fundal întunecat, trebuie să schimbăm puțin css-ul de reîncărcare. Deci, adăugați următoarele css în fișierul locator.css:
    / * Trageți pentru a actualiza pluginul * / .x-list-pullrefresh culoare: #fff;  .X-list-pullrefresh-săgeată -webkit - masca: centru centru url (date: image / png; base64, iVBORw0KGgoAAAANSUhEUgAAACgAAAA8CAYAAAAUufjgAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAjFJREFUeNrsmU8oREEYwOexdtNuKBfFwdVhCyfuysnFiXISS + 1BLopyUpKLXETkRLaUi1LK3Q2lpPbiQLnIn03a / + Hm z86Ttv0zM ++ bfbOar36Hbad5v535Zp7v47iuy0wOpyoEHccRHV9L9NxPkUE / bhKCOKiOSPAdn69DsJ5I8E2HYA0QJRJ8Bb50CDYRCT7pEMQD0kwk + CByUFQEW4gE73UIhoA2IsFb4ENEMCQ5MdU1IxwygpT3oKNLMGyyYFVscdhusc8tDpu + xRG7xf95BW0O2kNiV1AgIvaQ2BzUJNgJNJYZGyUU7OG1cal4Bi68oqkDPszy2teEwJp5Cdyu / lZ1g8CwIYJ7wEF + 2YmrNw90Byx3BizgKhaqizEP1wg7CLLxCEzy / CtauMeBlQDyEfNuGrgU6SyM8F9SyVgHdmRaH6tAb4XkToEp2d4M5mOK0TWMigU2koa8vJMRZPxEb2ss2LEVPMpPLlMRxBgDZjQJLgNbxb6Uab9tAn3EcifAeKkBMoLY + j0GWonk7oB + lmsFkwhidAGHBPmIeTcAnJcbKCuIMQEs + hScAzZEBqoIYuzyFVCJI36lMJ2CDfxibZeUu + EX / 4uMIFP8ZyLejxkgK0hG5a8kP4IYSZbr1IuQVHmAX0HGX4VuGfZVJ6cQxPd1uoRcWqDW0SroFVzZAnJZ / h0LWhAjUUAw4XdSSsH8fExRTEgtGAOuOTETBb16Jk412e + bxOSwglYw6PgWYABvLk8P7zGJFwAAAABJRU5ErkJggg == ) nu - repetați; fundal: #fff; 

    Aici merge:



    Concluzie

    Aceasta este prima parte a tutorialului. Am creat o listă de servicii furnizate de API-ul Google Locații și apoi pentru un anumit serviciu și am arătat o listă cu toate locațiile din apropiere. În următoarea și ultima parte a acestui tutorial, vom acoperi următoarele funcționalități:

    1. Se afișează toate locațiile pentru o categorie în Hărți Google
    2. Se afișează detaliile fiecărui loc. Aceasta va include afișarea unei hărți individuale pentru un anumit loc, crearea unei galerii foto bazate pe mozaicul Sencha, a unui carusel de imagine complet pe ecran și o listă de recenzii.

    Sencha este în prezent una dintre cele mai puternice biblioteci mobile bazate pe HTML5. Odată ce ați setat-o, veți putea să scrieți aplicații mobile minunate și netede. Aceste aplicații pot fi utilizate fie ca site-uri mobile, fie pot fi înfășurate în Phonegap pentru a crea aplicații hibride pentru iOS și Android.


    ACTUALIZAȚI!

    A doua parte a acestui tutorial este disponibilă acum. Găsiți-o aici: Creați un site de conștientizare a locației cu Sencha Touch - Afișarea locațiilor.

Cod