Browser Extension Ordne Tumblr Innlegg i kronologisk rekkefølge

Å lage små nettleserutvidelser er en fin måte å lære JavaScript på. Du trenger ikke å bekymre deg for kryssbrowser-kompatibilitet, du kan gjøre prosjektet så lite eller stort som du vil, og du kan løse problemer på andre folks nettsteder som feiler deg, spesielt. I dette innlegget oppretter vi et kort skript som automatisk omarrangerer Tumblr arkivsider for å lese i kronologisk rekkefølge - og vi lærer om NodeList er på vei.


Problemet

Denne uken startet Ryan North en ny Tumblr, hvor han går gjennom novelliseringen av den første Back to the Future-filmen, en side av gangen. Dette er en ting jeg ønsker å lese.

Klikk for å lese.

Imidlertid viser Tumblr sine innlegg i omvendt kronologisk rekkefølge - det vil si med de nyeste innleggene først. Dette gir mening for mange nettsteder på Tumblr, men i dette tilfellet vil jeg virkelig lese dem i den rekkefølgen de ble skrevet. Det nåværende nettstedet layout betyr at for å gjøre det, må jeg bla ned til toppen av det første (første skriftlige) innlegget, bla ned mens jeg leser det, og deretter bla opp til toppen av det andre innlegget og bla nedover gjennom det ...

Dette er et lite, lite første verdensproblem - helt trivielt og nesten pinlig å nevne. Men det betyr ikke at jeg ikke vil fikse det.

Ved slutten av denne opplæringen vil du gjøre denne Tumblr - eller hvilken som helst Tumblr du velger - vise innleggene i kronologisk rekkefølge på siden, automatisk.


Hvordan kan vi gjøre dette?

Vi har ikke kontroll over BtotheFs nettsteddesign; Det gir ingen alternativer til oss, så vi kan ikke endre rekkefølgen der innleggene vises på siden server-side.

Men når HTML er sendt til nettleseren, er det vår. Vi kan manipulere det vi ønsker. Og selvfølgelig er språket vi kan gjøre med dette JavaScript.

Jeg gir en rask demo. Jeg bruker Chrome, og anbefaler at du gjør det også - hvis du ikke kan, eller ikke vil, ta en kopi av Firebug.

Bla til http://btothef.tumblr.com/ og åpne JavaScript-konsollen (Verktøy> JavaScript-konsoll, i Chrome). Type:

 alert ( "Hei");

... og trykk Enter.

Wow! ... Ok, det visste ikke mye. Prøv dette:

 document.body.appendChild (document.createTextNode ( "Hei"));

Dette vil ta HTML-dokumentet element, og legg til en ny tekst node - et stykke tekst, i utgangspunktet - som inneholder ordet "Hei". Hvis du ikke fulgte noe av det, kom deg raskt til HTML.

For å se resultatet, bla til høyre ned til bunnen av Tumblr:

Litt mer imponerende, siden vi faktisk har endret innholdet på siden. Den nye tekstnoden er helt nederst fordi vi har brukt appendChild () - som legger til den angitte noden etter alt annet inne i . Når det gjelder nettleseren vår, ser de siste linjene i HTML nå ut som dette:

  Hei  

Så! Nå har vi to problemer:

  1. Hvordan bruker vi JavaScript til å omorganisere alle innleggene på siden?
  2. Hvordan får vi dette til å skje automatisk, uten at vi må rote rundt i konsollen hver gang vi leser Tumblr?

Vi adresserer disse i rekkefølge.


Omarrangere innleggene

Først må vi finne ut hvordan du "finner" alle innleggene i HTML-koden. I Chrome høyreklikker du et sted i øverste innlegget, og velger "Inspiser element". (Firebug bør legge til samme snarvei til Firefox; for andre nettlesere kan du prøve forstørrelsesglassikonet.)

Elementer-fanen i utviklerverktøyene vises, med elementet du valgte uthevet:

Mens du beveger deg over forskjellige elementer i denne HTML-visningen, ser du dem fremhevet på selve siden. Til slutt finner du at hele innlegget er inneholdt i en div med en klasse av post. Som du kan se fra skjermbildet ovenfor, er det flere andre slike div elementer, og de er alle inneholdt i en mester div med et id av innhold.

Vi kan velge alle disse innleggselementene samtidig med en enkelt linje med kode; skriv inn dette i JavaScript-konsollen:

 document.getElementById ( "innholdet") getElementsByClassName ( "post").;

(Teknisk sett kunne vi nettopp ha skrevet document.getElementsByClassName ( "post"), men hvem bryr seg?)

Du får se - igjen, i Chrome - noe tilbakemelding:

Flott! Dette indikerer at det fungerte. Hvis du klikker på pilene, ser du innholdet i hver div.

Vi kan like godt tildele dette til en variabel, for å redde oss å måtte skrive det ut igjen og igjen:

 var innlegg = document.getElementById ("innhold"). getElementsByClassName ("post");

(Denne gangen kommer konsollen tilbake udefinert; Du kan kontrollere at den tildelte variabelen riktig ved bare å skrive ordet innlegg i konsollen.)

Vi kan gå gjennom alle elementene i innlegg som om det var en matrise:

 for (var i = 0; i < posts.length; i++)  console.log(posts[i]); 

Hit Shift-Enter for å legge til en ny linje i koden din uten å kjøre den, i JavaScript-konsollen. console.log () bare sporer innholdet til konsollen, som er langt mindre irriterende enn en varsling() og langt mindre forstyrrende enn å legge til tekst i HTML DOM.

Resultatet av denne enkle sløyfen vil bare være en liste over alle div elementer. Kul. Så antagelig kan vi gjøre noe sånt ...

 var numPosts = posts.length; for (var i = numPosts - 1; i> = 0; i--) posts.push (innlegg [i]); 

Prøv det! Du ser dette:

 TypeError: Objekt # har ingen metode 'push'

rotter.

En NodeList er ikke en array

Når vi bruker getElementsByClassName (), Vi henter ikke en enkel rekke elementer, vi henter en NodeList. Som en matrise er dette en samling av elementer; i motsetning til en matrise, oppdateres samlingen i sanntid. Hvis HTML DOM er endret, innholdet i innlegg blir modifisert for å matche.

For eksempel, la oss lage en ny div med en klasse av post og legg det til innhold div:

 var newPostDiv = document.createElement ("div"); newPostDiv.setAttribute ("class", "post"); document.getElementById ( "innholdet") appendChild (newPostDiv.);

Kjør det, skriv deretter innlegg og trykk Enter. Du får se en ekstra div på listen - selv om vi ikke har rørt innlegg variabel.

Siden a NodeList er ikke en matrise, det har ikke de fleste metodene og egenskapene til Array, som for eksempel trykk() Faktisk har vi allerede brukt den eneste eiendommen: lengde. Den eneste metoden er .punkt (n), som bare får nposten i listen.

Men vår tidligere demonstrasjon med appendChild () foreslår en alternativ løsning: hva hvis, i stedet for å prøve å omorganisere elementene i NodeList innen NodeList, Vi reorganiserte dem på siden?

Først løper vi gjennom listen i omvendt rekkefølge, og legger til hvert element i sin tur til innhold div; Da fjerner vi de opprinnelige innleggene.

Oppdater Tumblr-siden for å fjerne alt det ekstra søppelet vi har lagt til DOM, og gjør det første trinnet, ved å legge til elementene i omvendt rekkefølge:

 // må definere innlegg igjen, siden vi mistet det når vi oppdaterte var innlegg = document.getElementById ("innhold"). getElementsByClassName ("post"); var numPosts = posts.length; for (var i = numPosts - 1; i> = 0; i--) document.getElementById ("innhold"). appendChild (innlegg [i]); 

Ok, nå ... vent, hva?

Det (kronologiske) første innlegget er allerede øverst, og det siste innlegget er nederst, uten innlegg igjen. Dette kan virke overraskende, men det er fornuftig: det gjorde vi ikke klone noen elementer av NodeList, vi bare vedlagt dem til innhold div, i omvendt rekkefølge. Siden NodeList gjenspeiler alltid innholdet i HTML DOM, vi bare flyttet hver av de 11 elementene til en ny posisjon - det 11. elementet ble lagt til slutten (ingen endring i posisjon); da ble 10. flyttet for å være etter det; den 9. etter det, og så videre, til det første elementet var rett på slutten.

Så problemet løses, i fem enkle linjer med kode. La oss nå automatisere det.


Slå den inn i en nettleserutvidelse

Tre av de fire fire nettleserne lar deg lage nettleserutvidelser - installerbare tilleggsprogrammer - ved hjelp av JavaScript. (Det vil ikke overraske deg for å lære at Internet Explorer er unntaket.) Her er instruksjonene for Chrome, instruksjonene for Firefox og instruksjonene for Safari.

Men vi skal ikke bruke noen av dem. I stedet bruker vi et flott tillegg, kalt Greasemonkey, som lar deg installere små JS-skript uten å måtte pakke dem opp som fullblåste nettleserutvidelser. I hovedsak injiserer det utklipp av JavaScript i siden, når den er lastet.

Chrome har allerede Greasemonkey-støtte baket inn. Opera har noe veldig lik Greasemonkey baket i: UserJS. For Firefox må du installere Greasemonkey-utvidelsen. For Safari, installer SIMBL og deretter GreaseKit. For IE, installer IE7Pro eller Trixie.

Skrive Greasemonkey Script

Opprett en ny tekstfil, og gi den navnet ChronologicalTumblr.user.js. Pass på at du fjerner standardinnstillingen .tekst utvidelse, og det du bruker .user.js, heller enn bare .js - Dette er utvidelsen for et Greasemonkey-skript.

Kopier vår post omleggingskode i filen:

 var innlegg = document.getElementById ("innhold"). getElementsByClassName ("post"); var numPosts = posts.length; for (var i = numPosts - 1; i> = 0; i--) document.getElementById ("innhold"). appendChild (innlegg [i]); 

Nå må vi legge til noen ekstra metadata øverst på skriptet - detaljer om selve skriptet. Alle disse detaljene skal gå i kommentarer, fra og med == UserScript == og slutter med == / UserScript ==:

 // == UserScript == // // == / UserScript == var innlegg = document.getElementById ("innhold"). GetElementsByClassName ("post"); var numPosts = posts.length; for (var i = numPosts - 1; i> = 0; i--) document.getElementById ("innhold"). appendChild (innlegg [i]); 

Først legger vi til et navn og en beskrivelse:

 // == UserScript == // @name Chronological Tumblr // @description Viser Tumblr innlegg i kronologisk rekkefølge // == / UserScript == var innlegg = document.getElementById ("innhold"). GetElementsByClassName ("post"); var numPosts = posts.length; for (var i = numPosts - 1; i> = 0; i--) document.getElementById ("innhold"). appendChild (innlegg [i]); 

Deretter angir vi en namespace. Kombinasjonen av navnet og navneområdet er det som unikt identifiserer skriptet; hvis du prøver å installere et annet Greasemonkey-skript med samme navn og namespace som et eksisterende skript, vil det overskrive den gamle - om bare navnet eller navneområdet matcher, vil det bare installere den nye sammen med den gamle.

Det er vanlig å bruke en nettadresse her, så jeg bruker Activetuts + s. Du bør bruke din egen, siden du har kontroll over det:

 // == UserScript == // @navn Chronological Tumblr // @description Viser Tumblr innlegg i kronologisk rekkefølge // @namespace http://active.tutsplus.com/ // == / UserScript == var innlegg = dokument. getElementById ( "innholdet") getElementsByClassName ( "post").; var numPosts = posts.length; for (var i = numPosts - 1; i> = 0; i--) document.getElementById ("innhold"). appendChild (innlegg [i]); 

Nå må vi angi hvilke nettadresser dette skriptet skal påvirke - det vil si hvilke websider JavaScript automatisk skal injiseres på. Jeg vil at dette skriptet skal fungere på BtotheF-hjemmesiden, pluss de andre arkivsidene, som http://btothef.tumblr.com/page/2:

 // == UserScript == // @navn Chronological Tumblr // @description Viser Tumblr innlegg i kronologisk rekkefølge // @namespace http://active.tutsplus.com/ // @include http://btothef.tumblr.com / // @include http://btothef.tumblr.com/page/* // == / UserScript == var innlegg = document.getElementById ("innhold"). getElementsByClassName ("post"); var numPosts = posts.length; for (var i = numPosts - 1; i> = 0; i--) document.getElementById ("innhold"). appendChild (innlegg [i]); 

De * er et jokertegn; Det sikrer at manuset vil bli satt inn i hver enkelt arkivside av BtotheF Tumblr.

Vi kunne bruke et jokertegn for å gjøre hver enkelt Tumblrs arkivssider vist i kronologisk rekkefølge:

 // == UserScript == // @navn Chronological Tumblr // @description Viser Tumblr innlegg i kronologisk rekkefølge // @namespace http://active.tutsplus.com/ // @include http: //*.tumblr.com / // @include http: //*.tumblr.com/page/* // == / UserScript == var innlegg = document.getElementById ("innhold"). getElementsByClassName ("post"); var numPosts = posts.length; for (var i = numPosts - 1; i> = 0; i--) document.getElementById ("innhold"). appendChild (innlegg [i]); 

I dette tilfellet kan det være lurt å forbedre skriptet ditt for å sette inn en knapp eller lenke til siden som omarrangerer innleggene når de klikkes. På den måten kan du bruke den når det er hensiktsmessig, uten å måtte manuelt legge til hver enkelt Tumblrs URL som en @inkludere parameter.

Det finnes andre metadataparametere du kan legge til, men dette er alt vi trenger for nå.

Avslutting

Det er enkelt å installere skriptet i Chrome: bare dra og slipp det fra harddisken til et nettleservindu. Det vil advare deg om at skriptene potensielt kan være farlige (bare klikk Fortsett), og kontroller deretter at du vil installere denne spesifikke:

Hit installer. Hvis du bruker en annen nettleser, kan du se den tilhørende Greasemonkey-håndboken - i alle fall vil det være enkelt.

Når den er installert, kan du se den i listen over utvidelser:

Gå tilbake til http://btothef.tumblr.com/, eller trykk på Oppdater hvis du fortsatt har den åpen.

Innleggene vises nå automatisk i kronologisk rekkefølge!

Det er ikke perfekt: du har kanskje lagt merke til at navigasjonsknappene har blitt flyttet til toppen av siden, siden de er inneholdt i en div med en klasse av post. Men hei - hvis det feiler deg, har du verktøyene for å fikse det nå.