PhoneGap Construiți un cititor de fluxuri - Logica aplicațiilor

Aceasta este a doua parte a seriei despre Audero Feed Reader. În acest articol, vom aborda logica de afaceri a aplicației noastre și vom furniza informații suplimentare despre pluginurile și API-urile folosite pentru proiectul nostru.


1. Prezentare generală API și plugin

Pluginul de notificare

La mai multe puncte din cadrul Audero Feed Reader app vom folosi alerta() metoda Pluginului de notificare. Modul în care se va afișa alerta depinde de platforma pe care va funcționa aplicația. De fapt, majoritatea sistemelor de operare acceptate utilizează o casetă de dialog nativă, dar altele, cum ar fi Bada 2.x, folosesc browserul clasic alerta() funcție, care este mai puțin personalizabil. Această metodă acceptă până la patru parametri:

  1. mesaj: Un șir care conține mesajul care urmează să fie afișat.
  2. alertCallback: Un apel invocat pentru a invoca când dialogul de avertizare este respins.
  3. titlu: Titlul dialogului (valoarea implicită este "alertă").
  4. BUTTONNAME: Textul butonului inclus în dialog (valoarea implicită este "OK")

Rețineți că Windows Phone 7 și 8 nu au o alertă încorporată în browser. Deci, dacă vrei să o folosești alert ( 'mesaj');, trebuie să alocați window.alert = navigator.notification.alert.

Pluginul InAppBrowser

În prima parte a acestei serii, am menționat că un punct interesant al paginii de credite este atributul target = "_ blank" aplicate la link-uri. Această secțiune va explica modul în care openLinksInApp () metodă a cerere clasa de lucrări.

InAppBrowser este un browser web care este afișat în aplicația dvs. atunci când utilizați window.open apel. Așa cum am spus în prima parte, începând cu versiunea 2.3.0, ea are două metode noi: executeScript () și insertCSS (). În prezent, acest plugin oferă următoarele cinci metode în total:

  • addEventListener (): Permite utilizatorului să asculte trei evenimente (loadstart, loadstop, și Ieșire) și pentru a atașa o funcție care rulează de îndată ce acele evenimente sunt declanșate.
  • removeEventListener (): Utilizat pentru a elimina un ascultător atașat anterior.
  • închide(): Utilizat pentru a închide fereastra InAppBrowser.
  • executeScript (): Permite injectarea codului JavaScript în InAppBrowser fereastră.
  • executeScript (): Permite injectarea codului CSS în InAppBrowser fereastră.

Dacă nu ați folosit Cordova timp de mai multe luni sau dacă rămâneți la versiunea 2.0.0, vă veți aminti că, în mod implicit, a deschis legături externe în același Cordova WebView care rula aplicația. Prin urmare, odată ce o pagină externă a fost vizitată, ultima pagină afișată a fost afișată exact așa cum a fost înainte ca utilizatorul să o lase. Din această versiune, aceasta nu mai este comportamentul standard. De fapt, linkurile externe sunt deschise acum folosind Cordova WebView dacă adresa URL este în lista albă a aplicației. Adresele URL care nu se află pe lista dvs. albă sunt deschise utilizând pluginul InAppBrowser (mai multe despre acestea din documentație). Dar ce înseamnă asta practic? Aceasta înseamnă că dacă nu gestionați corect link-urile și dacă utilizatorii aplicației dvs. dau clic pe un link și apoi revin la aplicație, toate jQuery Mobile sau alte astfel de îmbunătățiri se pierd. Acest lucru se întâmplă deoarece toate fișierele CSS și JavaScript sunt încărcate numai în pagina principală, iar adresele URL ulterioare sunt încărcate utilizând AJAX (sistemul implicit adoptat de jQuery Mobile).

Remedierea acestei probleme este implementată în openLinksInApp () metodă. De fapt, soluția este de a prinde clicurile pe toate legăturile externe prin setarea target = "_ blank" atributul, prevenirea comportamentului implicit nedorit și deschiderea legăturilor utilizând window.open () metodă. Pentru a funcționa, această soluție va necesita setarea unei liste albe în fișierul de configurare.

API-ul Google Feed

Înainte de a vorbi despre clasele Audero Feed Reader, trebuie să intrăm în lumea magică a API-ului Google Feed și a interfeței Google Feed JSON, deoarece le vom folosi în cadrul caracteristicii principale a aplicației noastre. După cum am subliniat în prima parte a acestei serii, interfața analizează un feed RSS sau ATOM și returnează un obiect JSON unificat și ușor de analizat. Desigur, putem gestiona fericit acest obiect JSON folosind JavaScript.

Această interfață acceptă două tipuri de interogări: Găsire feed și încărcare feed. Primele căutări pentru feed-uri pe baza cuvintelor cheie date au fost transmise ca argument, în timp ce al doilea căutări pentru feed-uri se bazează pe un URL de feed furnizat. În aplicația noastră, vom folosi doar caracteristica Feed încărcare.

Fiecare solicitare la acest API Google trebuie să trimită cel puțin doi parametri: v și q. Da, au nume foarte criptice! Primul parametru, v, specifică numărul versiunii protocolului. La momentul acestei scrieri, singura valoare validă este "1.0". În al doilea parametru, q, trecem URL-ul pentru a analiza. În plus față de acestea, aplicația noastră va folosi și Num parametru. Documentația specifică numărul de intrări de încărcat din fluxul specificat de q. O valoare de -1 indică numărul maxim de intrări acceptate, în prezent 100. În mod implicit, feedul de încărcare returnează patru rezultate. Prin urmare, este esențial să implementăm funcția noastră de a încărca 10 intrări în mod implicit și apoi să creștem cu încă 10, de fiecare dată când este necesar ca utilizatorul să afișeze mai mult.

Acum că sunteți conștient de modul în care vom interoga serviciul Google, este important să clarificăm rezultatul pe care îl va reveni. Dacă adresa URL pe care am furnizat-o a fost corectă, vom găsi intrările din Feed în interiorul responseData.feed.entries proprietate. Fiecare intrare are o mulțime de informații, dar vom folosi doar câteva dintre ele. În special, vom tipări următoarele proprietăți:

  • titlu: Titlul intrării.
  • legătură: Adresa URL pentru versiunea HTML a intrării.
  • autor: Autorul înregistrării.
  • contentSnippet: Un fragment de mai puțin de 120 de caractere din atributul de conținut. Fragmentul nu conține etichete HTML.

Detaliile pe care le-am furnizat mai sus sunt suficiente pentru scopul aplicației noastre, însă dacă doriți să aflați mai multe, consultați documentația Google Feed.


2. Construirea clasei de alimentare

Această secțiune va descrie A hrani clasa și metodele sale, toate incluse în feed.js fişier. După cum am subliniat în partea anterioară, vom salva numai două câmpuri pentru fiecare feed: titlul și adresa URL. Deci, această clasă acceptă aceste două puncte de date ca parametri. În interiorul acestuia, creăm două proprietăți private: _db și _tableName. Amintiți-vă că JavaScript nu are de fapt modificatori de proprietăți și de metodă de vizibilitate, deci emitem de fapt date private.

Prima este o scurtătură pentru localStorage proprietate a fereastră obiect. Este folosit pentru a accesa metodele expuse de pluginul de stocare, pe care se bazează aplicația noastră și pe care îl vom folosi pentru a stoca fluxurile. Al doilea este un șir care conține numele cheii în care vom salva datele. De fapt, reamintind specificațiile de depozitare, stochează datele utilizând un format cheie-valoare. Prin urmare, pentru a stoca spectrul nostru de feed-uri, trebuie să-l fie JSON. Asta e exact ceea ce avem Salvați() metoda va face. În același mod, pentru a prelua datele trebuie să analizăm un șir JSON pentru al transforma într-un obiect. Această sarcină este realizată de sarcină() metodă. Aceste metode sunt singurele două care trebuie să se afle în interiorul definiției clasei deoarece folosesc proprietăți private.

Secțiunea relativă a feed.js fișierul este prezentat mai jos:

 funcția Feed (nume, url) var _db = window.localStorage; var _tableName = 'feed'; this.name = nume; this.url = url; this.save = funcția (fluxurile) _db.setItem (_tableName, JSON.stringify (feeds)); ; this.load = funcția () retur JSON.parse (_db.getItem (_tableName)); ; 

În jurul acestor două metode simple vom crea o grămadă de alte comune. Mai specific, vom construi câteva metode de exemplu, cum ar fi adăuga(), pentru a adăuga un Feed nou, șterge(), pentru a șterge un flux și compara cu(), pentru a compara o instanță Feed cu alt feed. Pe lângă acestea, vom dezvolta și câteva metode statice, cum ar fi getFeeds () pentru a prelua toate feedurile din spațiul de stocare, getFeed () pentru a recupera doar unul, și comparaţie() pentru a compara două obiecte.

Metodele de comparare merită o mică discuție de înțeles Cum le vom compara. Voi trece peste descrierea compara cu() deoarece nu face altceva decât să-și numească omologul său static, comparaţie(), care de fapt face treaba. În aceasta, vom testa mai întâi dacă una dintre valorile date este nulă. În cazul în care niciuna dintre ele nu este nulă, le vom compara lexicografic numele și, în cazul în care sunt egale, comparați adresa URL a acestora. Cu toate acestea, după cum veți descoperi mai târziu, vom forța utilizatorul să nu aibă niciodată două feeduri cu același nume sau URL.
comparaţie() metoda este importantă deoarece definește modul în care comparăm două feeduri, iar acest lucru este crucial pentru a stabili modul în care vor fi sortate fluxurile Lista-feeds.html pagină. De fapt, vom folosi nativul fel() array care acceptă un parametru opțional, o funcție care definește ordinea de sortare a matricei pe baza valorilor sale de retur.

Codul care implementează ceea ce am descris este următorul:

 Feed.prototype.compareTo = funcția (altul) returnează Feed.compare (acesta, altul); ; Feed.compare = funcție (feed, altele) if (other == null) return 1;  dacă (feed == null) return -1;  var test = feed.name.localeCompare (alt nume); retur (test === 0)? feed.url.localeCompare (other.url): test; ;

În plus față de metodele văzute până în prezent, vom crea două metode de căutare pe care le vom folosi pentru a găsi și a șterge un feed dat: cauta dupa nume() și searchByUrl (). Ultima metodă pe care vreau să o subliniez este getIndex (), și este cea utilizată pentru a prelua indexul unui anumit fișier.

Acum că am descoperit toate detaliile din această clasă, pot lista întregul cod sursă al fișierului:

 funcția Feed (nume, url) var _db = window.localStorage; var _tableName = 'feed'; this.name = nume; this.url = url; this.save = funcția (fluxurile) _db.setItem (_tableName, JSON.stringify (feeds)); ; this.load = funcția () retur JSON.parse (_db.getItem (_tableName)); ;  Feed.prototype.add = funcția () var index = Feed.getIndex (aceasta); var feeds = feed.getFeeds (); dacă (index === false) feeds.push (aceasta);  altceva feeds [index] = aceasta;  this.save (fluxuri); ; Feed.prototype.delete = funcția () var index = Feed.getIndex (aceasta); var feeds = feed.getFeeds (); dacă (index! == false) feeds.splice (index, 1); this.save (feed-uri);  returnează fluxurile; ; Feed.prototype.compareTo = funcția (altul) returnează Feed.compare (acesta, altul); ; Feed.compare = funcție (feed, altele) if (other == null) return 1;  dacă (feed == null) return -1;  var test = feed.name.localeCompare (alt nume); retur (test === 0)? feed.url.localeCompare (other.url): test; ; Feed.getFeeds = funcție () var feeds = feed nou () load (); retur (feeds === null)? []: feedurile; ; Feed.getFeed = funcție (feed) var index = Feed.getIndex (feed); dacă (index === false) return null;  var feed = feed.getFeeds () [index]; returnați Feed nou (feed.name, feed.url); ; Feed.getIndex = funcție (feed) var feeds = Feed.getFeeds (); pentru (var i = 0; i < feeds.length; i++)  if (feed.compareTo(feeds[i]) === 0)  return i;   return false; ; Feed.deleteFeeds = function ()  new Feed().save([]); ; Feed.searchByName = function (name)  var feeds = Feed.getFeeds(); for (var i = 0; i < feeds.length; i++)  if (feeds[i].name === name)  return new Feed(feeds[i].name, feeds[i].url);   return false; ; Feed.searchByUrl = function (url)  var feeds = Feed.getFeeds(); for (var i = 0; i < feeds.length; i++)  if (feeds[i].url === url)  return new Feed(feeds[i].name, feeds[i].url);   return false; ;

3. Construirea clasei de aplicație

Această secțiune discută despre clasa a doua și ultima a proiectului, cerere, conținută în interior application.js fişier. Obiectivul său este de a inițializa aspectul paginilor, de a atașa evenimentele la elementele paginii de aplicație și de a utiliza A hrani pentru a salva, a încărca și a prelua feedurile.

Această clasă este organizată pentru a avea punctul de intrare în initApplication () metodă. Se numește de îndată ce Cordova a fost inițializată și API-urile sale sunt gata să acționeze. În cadrul acestei metode, atașăm un anumit handler la fiecare inițializare a paginii astfel încât să putem gestiona evenimentele declanșate de widget-urile lor. În el, vom apela și noi Application.openLinksInApp () pentru motivele discutate anterior. În plus, pentru a îmbunătăți experiența utilizatorului, vom prinde fiecare apăsare a butonului fizic înapoi (acolo unde există) pentru a redirecționa utilizatorul la pagina de pornire a aplicației.

Funcția de bază a aplicației noastre este initShowFeedPage () deoarece utilizează interfața Google Feed JSON. Înainte de a rula solicitarea către serviciu, numărăm numărul de intrări deja încărcate (currentEntries variabilă) și să calculați numărul de intrări pe care serviciul trebuie să le aducă (entriesToShow variabil). Apoi vom rula cererea AJAX, folosind jQuery ajax () și, în același timp, afișăm widget-ul de încărcare a paginii către utilizator. Când se efectuează apelul de succes, încercăm mai întâi dacă numărul de intrări returnate să fie același cu numărul deja afișat, caz în care se afișează mesajul "Nu mai sunt încărcări". În caz contrar, îi adăugăm la listă și actualizăm widgetul acordeon ($ List.collapsibleset (Refresh)). Împreună cu fiecare intrare, atașăm și un handler la butonul care este creat, astfel încât, dacă conexiunea este dezactivată, un mesaj este solicitat în loc să accesați pagina.

În cele din urmă, updateIcons () metoda va fi discutată în următoarea și ultima parte a seriei.

Codul care implementează clasa discutată este prezentat mai jos:

 var Application = initApplication: function () $ (document) .on ('pageinit', ' # "," funcția () application.initListFeedPage ();) .on ('pageinit', '# show-feed-page' url = "", "# aurelio-page", function () Application.initAurelioPage ();. ('backbutton', funcția () $ .mobile.changePage ('index.html');; Application.openLinksInApp (); initAddFeedPage: add-feed-form ') trimite (functie (eveniment) event.preventDefault (); var feedName = $ (' "(=") "(=" Câmpul de nume este necesar și nu poate fi gol ", funcția () ," Eroare "); return false; dacă (feedUrl === ") navigator.notification.alert (" câmpul URL este necesar și nu poate fi gol ", funcția () , "Eroare"); return false;  dacă (Feed.searchByName (feedName) === false && Feed.searchByUrl (feedUrl) === false) var feed = Feed nou (feedName, feedUrl); feed.add (); navigator.notification.alert ("Feed salvat corect", funcția () $ .mobile.changePage ('index.html');, 'Success');  altfel navigator.notification.alert ("Feed-ul nu este salvat! Fie numele sau adresa URL specificată este deja în uz", funcția () , "Eroare");  return false; ); , initListFeedPage: funcția () var $ feedsList = $ ('# feeds-list'); var = Feed.getFeeds (); var htmlItems = "; $ feedsList.empty (); items = items.sort (Feed.compare); pentru (var i = 0; i < items.length; i++)  htmlItems += '
  • '+ elemente [i] .name +'
  • „; $ feedsList.append (htmlItems) .listview ("actualizare"); , initShowFeedPage: funcție (url) var step = 10; var loadFeed = funcția () var currentEntries = $ ('# feed-entries')) find ('div [data-role = collapsible]. var inputsToShow = currentEntries + step; $ .ajax (url: 'https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=' + intrăriToShow + '& q =' + encodeURI (url), dataType: 'json' , înainteSend: funcția () $ .mobile.loading ('show', text: 'Așteptați în timp ce preluați datele ...', textVisible: true); '# feed-entries'), dacă (date.responseData === null) navigator.notification.alert ('Nu se poate recupera URL-ul nevalid al feedului, funcția () ,' Eroare '); var items = data.responseData.feed.entries; var $ post; if (currentEntries === items.length) navigator.notification.alert ("Nu mai trebuie încărcate", funcția () , 'Info') ; return; pentru (var i = currentEntries; i < items.length; i++) $post = $('
    „); $ post .append ($ ('

    ') .text (elemente [i] .title)) .append ($ ('

    ') .html (' '+ elemente [i] .title +' ')) // Adăugați titlul .append ($ ('

    ') .html (elemente [i] .contentSnippet)) // Adăugați descrierea .append ($ ('

    ') .text (' Autor: '+ elemente [i] .author)) .append ($ (' Application.checkRequirements () === false) event.preventDefault (); navigator.notification.alert ('Conexiunea este oprită, vă rugăm să o porniți', funcția () , 'Error'); $ (acest) .removeClass ("ui-btn-activ");)); $ List.append ($ post); $ list.collapsibleset ("actualizare"); , eroare: functie () navigator.notification.alert ("Imposibil de recuperat Feed-ul, încercați mai târziu", funcția () , "Eroare"); , completă: funcția () $ .mobile.loading ('ascunde'); ); ; $ (this) .removeClass ("ui-btn-active");); $ ('delete delete feed') click (function () Feed.searchByUrl (url) .delete (); navigator.notification.alert (' -feeds.html ");," Succes ");); dacă (Application.checkRequirements () === true) loadFeed (); altceva navigator.notification.alert ("Pentru a utiliza această aplicație, trebuie să activați conexiunea la internet", funcția () , "Avertisment"); , initAurelioPage: function () $ ('a [target = _blank]'). ); , checkRequirements: function () if (navigator.connection.type === Connection.NONE) return false; return true; , updateIcons: funcția () var $ buttons = $ ('a [date-icon], butonul [data-icon]'); var esteMobileWidth = ($ (fereastră) .width () <= 480); isMobileWidth ? $buttons.attr('data-iconpos', 'notext') : $buttons.removeAttr('data-iconpos'); , openLinksInApp: function () $(document).on('click', 'a[target=_blank]', function (event) event.preventDefault(); window.open($(this).attr('href'), '_blank'); ); ;


    Concluzie

    În cea de-a treia și ultima tranșă a acestei serii, vom vedea cum să construim și să testați instalatorii utilizând CLI și Adobe PhoneGap Build.

    Cod