Lag en Amazon Bøker Widget med jQuery og XML

Det er fornuftig å avvise databasen tabeller og server-side kode når du trenger å lagre en begrenset mengde ikke-sensitive data. Å få tilgang til disse dataene kan være et snap med jQuery fordi biblioteket ble bygget for å krysse XML-dokumenter med letthet. Med noen egendefinerte JavaScript og jQuery magi kan du lage noen interessante widgets. En god måte å demonstrere denne funksjonaliteten på er å bygge en browselig Amazon.com bøker widget.




Forord

En ting å huske når du prøver å prøve dette ut på egen hånd, er at sikkerhetsinnstillingene i Internet Explorer ikke lar deg lage XmlHttpRequest-anrop fra det lokale filsystemet. Selv om du ikke bruker et server-side språk, må du fortsatt kjøre kildekoden fra en webserver som Apache's HTTP Server. Opplasting av filene til en web hosting-konto vil også fungere.

Denne opplæringen bruker den minifiserte jQuery 1.2.6 kjerne JavaScript-filen, som kan lastes ned her fra Google Code. Ingen andre plugins er nødvendige. Her er et skjermbilde av widgeten i sin endelige form:

Trinn 1: Dissecting Interface

Jeg opprettet følgende grafikk med Illustrator, og dette er rammen for bøker widgeten. De endelige skivede bildene kan enkelt byttes for å skape designelementer som passer dine behov. Illustrasjonen inneholder de neste og forrige knappene, samt beholderen for bokbildene. Kilden ZIP-filen inneholder et lagdelt EPS hvis du vil gjøre endringer uten å starte fra begynnelsen.

En ting jeg ønsket å gjøre med denne widgeten var å sørge for at den var fleksibel nok for omtrent hvilken som helst kolonnestørrelse. Det betydde at det ikke bare behøvde å være en væskebredde, men det trengte også å akseptere pikselmåleenheter. Bøker kan brytes grasiøst til flere rader fordelt jevnt fra hverandre, ned til en enkelt kolonne, eller kan strekke seg over i en enkelt rad så bredt som du vil. Dette neste skjermbildet bidrar til å visualisere hvordan det vil skje.

De lys rosa faste blokkene skal demonstrere bildeskjæringsgitteret. Det er de to knappene, samt fire hjørner, topp- og bunnbakgrunnen, og deretter venstre og høyre bakgrunn. De mørkerosa solide linjene skal demonstrere inneslutningsblokker, som til slutt vil ende opp som et par divs og en uordnet liste. For å tillate en fluid layout vil en indre div inneholde venstre side bakgrunn, og den uordnede listen vil bli nestet i denne foreldre div, som vil inneholde høyre side bakgrunn.

Trinn 2: HTML

Før jeg kommer til HTML, er det verdt å merke seg at jeg ikke bruker PNG-filer. Du kan veldig godt erstatte PNGs for GIF, og det ville ikke påvirke funksjonaliteten. Det ville imidlertid bety at du må implementere en løsning for mangel på PNG-gjennomsiktighetsstøtte i Internet Explorer. Det er flere jQuery-plugins som er tilgjengelige.

     Amazon.com Bøker Widget    
Tidligere
neste

Det er ikke noe banebrytende om HTML, men jeg vil gjerne påpeke noen få ting. Den første er med hensyn til "overclear" klassen som vises på flere elementer. Dette er en utmerket metode for å rydde flyter uten behov for ytterligere markering. Jeg diskuterer denne teknikken i et blogginnlegg med tittelen Seks uunnværlige CSS tips og triks jeg bruker på hvert prosjekt. Ved å erklære en bredde og sette overløpsegenskapen til skjult på en foreldre div, vil barnelementer som er floated ikke lenger trenge et etterfølgende element med den klare egenskapen.

Den andre tingen jeg vil gjerne påpeke er elementet for lasterlisten. Siden jeg skal ta alle bøkene i XML-filen på en gang, burde loaderen vises umiddelbart. Jeg genererte en laster fra Ajaxload, og deretter sentrert den som bakgrunn. Når XML er ferdig lastet, fjerner jeg listeposten fra DOM, og lasteren forsvinner. Her er et skjermbilde av hvordan det ser ut med bare HTML og CSS som er brukt.

Widgeten har en fast bredde, og for denne opplæringen vil det være en enkelt rad med fire bøker som vises på hver visning. Hvis det ikke ble brukt bredde, ville den spenne hele sidens lengde, eller bredden av dens overordnede beholder.

Trinn 3: CSS

CSS er ganske enkelt og selvforklarende, så jeg vil ikke bruke mye tid på å forklare alle fasene til hver velger. Nesten alle selektorer er barnelementer i foreldrebeholderen med identifikatoren "bøker". Du kan se at bredden som er brukt er valgfri. Fjerning av det vil tillate widgeten å utvide og kontrakten fritt.

 / * foundation * / body font: 100% normal "Arial", "Helvetica", sans-serif;  #bøker bredde: 515px; / * valgfritt * / #bøker img grense: 0;  #books.clear_both clear: both;  #books .float_left, #books ul li float: left; skjerm: inline;  #books .float_right float: right;  #books.overclear width: 100%; overløp: skjult;  / * stiler * / #books .buttons posisjon: relative; høyde: 30px; margin: 0 0 5px 0;  #bøker .prev posisjon: absolutt; topp: 0; venstre: 0; synlighet: skjult;  #bøker .neste posisjon: absolutt; topp: 0; høyre: 0;  #books.showing margin: 5px 60px 0 60px; tekst-align: center; skriftstørrelse: .8em;  #books .top background: url (... /images/books_top.gif) repeat-x;  #books .inner padding: 0 0 0 20px; margin: 0 0 -20px 0; bakgrunn: url (... /images/books_left_mid.gif) repeat-y;  #books ul margin: 0; polstring: 0; liste-stil-type: none; bakgrunn: url (... /images/books_right_mid.gif) Gjenta-y øverst til høyre;  #books ul li display: none; stilling: relativ; margin: 0; polstring: 0 20px 20px 0; skriftstørrelse: .8em; z-indeks: 1;  #books ul li.loader display: block; flyte: ingen; høyde: 115px; margin: 0 0 20px -20px; bakgrunn: url (... /images/books_loader.gif) no-repeat center center;  #books ul li a.info posisjon: absolutt; bunn: 20px; høyre: 20px;  #books ul li a.thumb display: block; grense: 1px solid #ddd;  #books ul li a.thumb img display: block; margin: 0; polstring: 3px;  #books .btm bakgrunn: url (... /images/books_btm.gif) repeat-x;  .books_tool_tip display: none; posisjon: absolutt; topp: 0; venstre: 0; bredde: 350px; z-indeks: 9999;  .books_tool_tip .books_pointer_left posisjon: absolutt; topp: 0; venstre: 0; bredde: 10px; høyde: 10px; bakgrunn: url (... /images/books_pointer_left.gif);  .books_tool_tip .books_pointer_right posisjon: absolutt; topp: 0; høyre: 0; bredde: 10px; høyde: 10px; bakgrunn: url (... /images/books_pointer_right.gif);  .books_tool_tip .inner border: 1px solid #ddd; polstring: 15px 15px 3px 15px; margin: 0 0 0 9px; bakgrunn: #fff;  .books_tool_tip .inner_right margin: 0 9px 0 0;  .books_tool_tip .inner p font-size: .8em; margin: 0; polstring: 0 0 12px 0; 

Det er ett unntak, og det er informasjonsverktøyet som brukes til en bok når du ruller over informasjonsikonet. Hvert verktøytips inneholder klassen "books_tool_tip", og er barnelementer i sidekroppen. Disse er plassert med JavaScript i henhold til museposisjonen for øyeblikket en bruker beveger markøren på ikonet.

Klassene "books_pointer_left" og "books_pointer_right" administrerer pilene som er knyttet til boktipsverktøytipset. Verktøyspissen faller til høyre for markøren, men hvis den er utenfor det visbare nettleservinduet (kalt visningsporten), vil det skifte til venstre side. Klassene byttes, og pilen skifter til motsatt side også. Dette lar deg plassere widgeten i en venstre kolonne eller høyre kolonneoppsett.

Trinn 4: XML

Det er ikke noe revolusjonerende om dette XML-en. Som du vil se, inneholder hver bok en tittel, forfatter (e), et bilde, en Amazon-nettadresse, en anmeldelsestall og en gjennomsnittsbedømmelse. XML kan normaliseres i ett område, og det er "forfatter" node. Strengt tatt kan det være flere forfattere, og en forfatter kan være en av to typer, forfatter eller redaktør. Imidlertid holdt jeg det enkelt for å fokusere på kjernefunksjonaliteten. En god del lekser ville være å se hvordan du bedre kan optimalisere den noden, og så vellykket analysere den med jQuery.

    <![CDATA[Design Patterns: Elements of Reusable Object-Oriented Software]]> Erich Gamma, Richard Helm, Ralph Johnson, John M. Vlissides      250 4.5    <![CDATA[The Pragmatic Programmer: From Journeyman to Master]]> Andrew Hunt, David Thomas      131 4.5    <![CDATA[Refactoring: Improving the Design of Existing Code]]> Martin Fowler, Kent Beck, John Brant, William Opdyke      139 4.5    <![CDATA[Patterns of Enterprise Application Architecture]]> Martin Fowler      56 4.5    <![CDATA[Head First Design Patterns]]> Elisabeth Freeman, Eric Freeman, Bert Bates, Kathy Sierra      252 4.5    <![CDATA[Introduction to Algorithms]]> Thomas Cormen, Charles Leiserson, Ronald Rivest, Clifford Stein      167 4.0    <![CDATA[The Mythical Man-Month: Essays on Software Engineering, Anniversary Edition (2nd Edition)]]> Frederick P. Brooks      128 4.5    <![CDATA[Effective Java (2nd Edition)]]> Joshua Bloch      120 5.0    <![CDATA[Mastering Regular Expressions]]> Jeffrey Friedl      125 4.5    <![CDATA[Introduction to the Theory of Computation, Second Edition]]> Michael Sipser      52 4.5    <![CDATA[Don't Make Me Think: A Common Sense Approach to Web Usability (2nd Edition)]]> Steve Krug      453 4.5    <![CDATA[The Visual Display of Quantitative Information, 2nd edition]]> Edward R. Tufte      96 4.5    <![CDATA[JavaScript: The Definitive Guide]]> David Flanagan      278 4.5    <![CDATA[Designing Interfaces: Patterns for Effective Interaction Design]]> Jenifer Tidwell      47 4.5    <![CDATA[Universal Principles of Design]]> William Lidwell, Kritina Holden, Jill Butler      54 4.5    <![CDATA[Ambient Findability: What We Find Changes Who We Become]]> Peter Morville      46 4.0    <![CDATA[The Search: How Google and Its Rivals Rewrote the Rules of Business and Transformed Our Culture]]> John Battelle      99 4.5    <![CDATA[Beginning PHP and MySQL 5 (2nd Edition)]]> W. Jason Gilmore      100 4.0   

Trinn 5: JavaScript

JavaScript er absolutt den mest kompliserte delen av opplæringen. Så godt jeg kan, begynner jeg vanligvis skript som dette ved å stikke ut tilstanden og oppførelsen til et objekt for å få en følelse av funksjonalitet. Dette bestemte objektet kalles bare "BØKER". Jeg bruker også det som kalles Modulmønsteret, som er detaljert av Eric Miraglia på Yahoo! Brukergrensesnitt Blogg. Dette designmønsteret gir deg muligheten til å lage private metoder og egenskaper. Når det løses et skript i naturen (som nå), bidrar dette mønsteret til å eliminere muligheten for konflikter med andre funksjoner og gjenstander som andre utviklere allerede kan bruke.

 var BOOKS = funksjon () var _P = init: funksjon (parameter) , parameter: null, data: null, loadXml: funksjon () , først: 0, max: 0, telle: 0, preloadBooks: funksjon () , skjul: funksjon (e, $ o) , getMouseCoord: funksjon (v, e) , getViewport: funksjon () ; return init: funksjon (params) _P.init (params); ;  ();

Alle mine private medlemmer jeg plasserte inne i et objekt som heter "_P". Dette har mer å gjøre med organisatorisk innsats enn noe annet. Så lenge et medlem ikke er i tilbakemeldingen til BOOKS, kunne jeg veldig godt ha opprettet det som en frittstående variabel eller funksjon. Siden jeg trenger en måte å knytte offentlige parametere (innstillinger) med private medlemmer, har jeg en offentlig metode. Denne offentlige initialiseringsmetoden vil overføre innstillingene til en privat initialiseringsmetode som fungerer som en mellomrom. Jeg vil se på disse innstillingene i siste trinn.

Her er en titt nå på den endelige JavaScript:

 var BOOKS = funksjon () var _P = init: funksjon (params) _P.params = params; _P.loadXml (); , parametre: null, data: null, loadXml: funksjon () $ .ajax (type: "GET", url: _P.params.xmlPath, dataType: "xml", suksess: funksjon (data) _P. data = data; _P.max = _P.params.perView; _P.count = $ ("bok", data) .length; _P.preloadBooks (); _P.browseBooks ();); , først: 0, max: 0, telle: 0, forhåndsbelastningsbøker: funksjon () $ ("ul", "#books") .empty (); $ ("bok", _P.data) .each (funksjon (i) var title = $ .trim ($ ("title", dette) .text ()); var href = $ .trim ", dette) .text ()); $ (" ul "," #books ") .append (["
  • src ", dette) .text ())," ", $ (" bilde ", dette) .attr (" bredde ")," ", $ (" bilde ", dette) .attr ", tittel," "/>
  • "] .join (" ")); $ (" body ") .append (["

    ", tittel" (ved ", $ .trim ($ (" forfatter ", dette) .text ()),") ","

    average_rating ", dette) .text ())," .gif "/> (", $ .trim ($ ("reviews> total", dette) .text ()), ")", "

    "] .join (" "));); $ (" .info "," #books ") .over (funksjon (e) _P.tooltip.show (e, $ (" #books_tool_tip_ "+ $ "a.info", "#books") .index (dette));, funksjon (e) _P.tooltip.hide (e, $ ("#books_tool_tip_" + $ ("a.info" #books ") .index (dette));; $ (" #books .prev ") .Click (funksjon () _P.browseBooks (" prev "); return false;); $ bøker .next ") .Click (funksjon () _P.browseBooks (" next "); return false;; browseBooks: funksjon (bla) if (browse ==" prev ") if (_P. først == _P.count && (_P.count% _P.max> 0)) _P.first = _P.first - ((_P.count% _P.max) + _P.max); else _P.first = _P.first - (_P.max * 2); varavstand = _P.first + _P.max; var start = 1; hvis (rekkevidde> _P.max) start = ((rekkevidde - _P.max) (1) ("synlighet", "synlig"); hvis (rekkevidde < _P.count ) $( "#books .next" ).css( "visibility", "visible" ); else if ( range >= _P.count) range = _P.count; $ ("#books .next") .css ("synlighet", "skjult"); $ ("bok", _P.data) .each (funksjon (i) hvis (i> = _P.first && i < range ) $( "#books li:eq(" + i + ")" ).fadeIn( "slow" ); else $( "#books li:eq(" + i + ")" ).css( "display", "none" ); ); _P.first = range; $( "#books .showing" ).html([ "Viewing ", start," - ", rekkevidde," av ", _P.count,""] .join (" "));, verktøytip: vis: funksjon (e, $ o) var v = _P.tooltip.getViewport (); var sideX = _P.tooltip.getMouseCoord (v, e) [ 0] + 15; var sideY = _P.tooltip.getMouseCoord (v, e) [1]; $ o.find (".books_pointer_right") .addClass ("books_pointer_left") .removeClass ("books_pointer_right"); + $ o.width ()> v.innerWidth + v.pageXOffset) sideX = sideX - $ o.width () - 30; $ o.find (".inner") .addClass ("inner_right"); $ o .find (".books_pointer_left") .addClass ("books_pointer_right") .removeClass ("books_pointer_left"); $ o.css ("left", sideX) .css ("topp", sideY) .css , "blokk");; skjul: funksjon (e, $ o) $ o.css ("display", "none");, getMouseCoord: funksjon (v, e) window.event: e = e; (e.pageX)? v.pageX = e.pageX: v.pageX = e.clientX + v.scrollLeft; (e.pageY)? v.pageY = e.pageY: v. pageY = e.clientY + v.scrollTop; returner [e.pageX, e.pageY];, getViewport: funksjon () var viewport = hvis (self.innerHeight) viewport. pageYOffset = self.pageYOffset; viewport.pageXOffset = self.pageXOffset; viewport.innerHeight = self.innerHeight; viewport.innerWidth = self.innerWidth; annet hvis (document.documentElement && document.documentElement.clientHeight) viewport.pageYOffset = document.documentElement.scrollTop; viewport.pageXOffset = document.documentElement.scrollLeft; viewport.innerHeight = document.documentElement.clientHeight; viewport.innerWidth = document.documentElement.clientWidth; returnere visningsport; ; return init: funksjon (params) _P.init (params); ; ();

    Jeg vil ikke dekke alle deler av funksjonaliteten, men jeg vil fremheve noen svært viktige aspekter av skriptet - den første er "loadXml" -metoden. Dette er en av jQuery's AJAX-verktøy, og en av de enkleste AJAX-implementasjonene som skal brukes. Du kan lese mer om det i den offisielle dokumentasjonen. Etter å ha hentet en XML-fil, vil mange utviklere utføre handlinger på dataene alle innenfor suksessdelen av samtalen. Dette er vanskelig å feilsøke, og jeg foretrekker å overføre dataene til andre metoder for å håndtere den. Dette tenker i objektorientert termer, og det kan være en god vane.

    "PreloadBooks" -metoden er hva som analyserer XML-dataene, og gjør hver knute til relevant XHTML, inkludert både en bok og en boks verktøketips. Den gode tingen om jQuery er at XML-noder kan behandles akkurat som HTML-noder. Du trenger ikke å lære to syntaksformer, med den eneste advarselen er at du må bruke jQuerys tekst () -metode for å hente innhold mellom en start- og sluttkode. Med HTML, vil du bruke html () metoden.

    Det er en stor del av HTML som må bygges gjennom JavaScript. Dette innebærer ofte strengkonsentrasjon. Den tradisjonelle tilnærmingen er å bruke tilleggsberegningsoperatøren, men en raskere tilnærming er å plassere deler av en streng inne i en matrise, og deretter bli med dem. Jeg gjør dette på flere steder, og spesielt når det skjer kontinuerlig gjennom en løkke, er dette den foretrukne stilen.

    Nå som bøkens HTML er satt inn i DOM, er det på tide å legge til rette hendelser for å bla. Handlingen av surfing skjer i "browseBooks" -metoden. Denne metoden aksepterer "bla" -parameteren, som tar en av to argumenter, "prev" eller "next". Dette er ikke en rullehandling, men en fade i / fade out overgang. Metoden vil etablere den første (nåværende) posisjonen, det maksimale antallet bøker du skal bla gjennom, antall bøker som du vil bla gjennom, og da vil det utføre overgangen. Dette bidrar også til å bestemme når forrige eller neste knapp skal vises for å begrense brukere fra å surfe utover antall bøker som er oppført.

    Verktøyspissen innebærer en liten mengde tilpasset JavaScript, og jeg ønsket å beskrive to funksjoner - "getMouseCoord" og "getViewport" -metodene. Dette er nettleser implementeringer for å bestemme museposisjonen i samsvar med hvor langt siden har rullet opp / ned eller venstre / høyre. Du må aldri redigere disse, og jeg har brukt dem på flere prosjekter uten problemer. "Vis" -metoden håndterer også scenariet jeg beskrev tidligere, når verktøytipset faller utenfor den beregnede visningsporten.

    Trinn 6: Den endelige widgeten

    Den siste tingen å gjøre er å overføre innstillingene til JavaScript-initialiseringsmetoden fra HTML-koden. Det er tre argumenter: banen til XML-filen, banen til bildene som brukes i JavaScript, og antall bøker du vil vise per visning. For denne opplæringen antas det at det kun er én bokkvideo per side (kalt "bøker"), og derfor er det ingen parameter for ID eller klassenavn. Her er XHTML i endelig form:

         Amazon.com Bøker Widget       
    Tidligere
    neste

    Nyt din Amazon.com bøker widget!

    • Abonner på NETTUTS RSS-feed for flere daglige webutviklinger og artikler.