La creazione di estensioni per browser è un ottimo modo per imparare JavaScript. Non devi preoccuparti della compatibilità tra browser, puoi rendere il progetto piccolo o grande quanto vuoi e puoi risolvere problemi nei siti Web di altre persone che ti infastidiscono, in particolare. In questo post creeremo un breve script che riorganizza automaticamente le pagine di Tumblr di Tumblr in ordine cronologico e impareremo a conoscere NodeList
sulla strada.
Questa settimana, Ryan North ha iniziato un nuovo Tumblr, in cui sta affrontando la novelizzazione del primo film Ritorno al futuro, una pagina alla volta. Questa è una cosa che desidero leggere.
Clicca per leggere.Tuttavia, Tumblr mostra i suoi post in ordine cronologico inverso, cioè con i post più recenti per primi. Questo ha senso per molti siti su Tumblr, ma in questo caso, voglio davvero leggerli nell'ordine in cui sono stati scritti. L'attuale layout del sito significa che, per farlo, devo scorrere verso il basso fino alla cima del primo post (scritto per primo), scorrere verso il basso mentre lo leggo, quindi scorrere fino all'inizio del secondo post e scorrere verso il basso attraverso quello ...
Questo è un piccolo, minuscolo problema del primo mondo - totalmente banale e quasi imbarazzante da menzionare. Ma questo non significa che non voglio aggiustarlo.
Alla fine di questo tutorial, renderai questo Tumblr - o qualsiasi Tumblr che scegli - i suoi post in ordine cronologico sulla pagina, automaticamente.
Non abbiamo il controllo sul design del sito di BtotheF; non ci offre alcuna opzione, quindi non possiamo modificare l'ordine in cui i post vengono visualizzati sul lato server della pagina.
Ma una volta che l'HTML è stato inviato al browser, è nostro. Possiamo manipolarlo come vogliamo. E, naturalmente, la lingua con cui possiamo farlo è JavaScript.
Darò una rapida demo. Userò Chrome, e lo raccomando, se non puoi o non vuoi, prendi una copia di Firebug.
Passare a http://btothef.tumblr.com/ e aprire la console JavaScript (Strumenti> Console JavaScript, in Chrome). Genere:
alert ( "Ciao");
... e premi Invio.
Wow! ... Ok, va bene, non è stato un granché. Prova questo:
document.body.appendChild (document.createTextNode ( "Ciao"));
Questo prenderà il documento HTML elemento, e aggiungere un nuovo nodo di testo - una porzione di testo, in pratica - contenente la parola "Ciao". Se non hai seguito nulla di tutto ciò, inizia subito a utilizzare HTML.
Per vedere il risultato, scorri fino alla fine di Tumblr:
Un po 'più impressionante, dato che abbiamo effettivamente cambiato il contenuto della pagina. Il nuovo nodo di testo è proprio in fondo perché abbiamo usato appendChild ()
- che aggiunge il nodo specificato dopo tutto il resto . Per quanto riguarda il nostro browser, le ultime righe di HTML ora appaiono come questa:
Ciao
Così! Ora abbiamo due problemi:
Li affronteremo in ordine.
Innanzitutto, vediamo come "trovare" tutti i post nell'HTML. In Chrome, fai clic con il pulsante destro del mouse nel post superiore e seleziona "Ispeziona elemento". (Firebug dovrebbe aggiungere lo stesso collegamento a Firefox, per altri browser, prova l'icona della lente d'ingrandimento.)
Apparirà la scheda Elementi degli Strumenti di sviluppo, con l'elemento selezionato evidenziato:
Quando passi con il mouse su diversi elementi in questa visualizzazione HTML, li vedrai evidenziati nella pagina stessa. Alla fine, scoprirai che l'intero post è contenuto in a div
con una classe di inviare
. Come puoi vedere dallo screenshot qui sopra, ce ne sono molti altri simili div
elementi, e sono tutti contenuti in un div master con un id di contenuto
.
Possiamo selezionare tutti questi elementi del post contemporaneamente con una singola riga di codice; digita questo nella console JavaScript:
document.getElementById ( "Contenuti") getElementsByClassName ( "post").;
(Tecnicamente, potremmo aver appena scritto document.getElementsByClassName ( "post")
, ma a chi importa?)
Vedrai, ancora una volta, in Chrome, alcuni feedback:
Grande! Questo indica che ha funzionato. Se fai clic sulle frecce, vedrai il contenuto di ciascuna div
.
Potremmo anche assegnarlo a una variabile, per risparmiarci di doverlo scrivere più e più volte:
var posts = document.getElementById ("contents"). getElementsByClassName ("post");
(Questa volta, la console tornerà non definito
; puoi verificare che abbia assegnato correttamente la variabile semplicemente digitando la parola messaggi
nella console.)
Possiamo scorrere tutti gli elementi in messaggi
come se fosse un array:
per (var i = 0; i < posts.length; i++) console.log(posts[i]);
Premi Maiusc + Invio per aggiungere una nuova riga al tuo codice senza eseguirlo, nella console JavaScript. console.log ()
traccia solo il suo contenuto nella console, che è molto meno fastidioso di un mettere in guardia()
e molto meno dirompente dell'aggiunta di testo al DOM HTML.
Il risultato di questo semplice ciclo sarà solo una lista di tutti i div
elementi. Freddo. Quindi presumibilmente possiamo fare qualcosa del genere ...
var numPosts = posts.length; for (var i = numPosts - 1; i> = 0; i--) posts.push (post [i]);
Provalo! Vedrai questo:
TypeError: Object #non ha metodo 'push'
ratti.
Quando usiamo getElementsByClassName ()
, non recuperiamo una semplice matrice di elementi, recuperiamo una NodeList. Come un array, questa è una raccolta di elementi; a differenza di un array, la collezione viene aggiornata in tempo reale. Se il DOM HTML viene modificato, il contenuto di messaggi
viene modificato per corrispondere.
Ad esempio, creiamo un nuovo div con una classe di inviare
e aggiungilo al contenuto
div:
var newPostDiv = document.createElement ("div"); newPostDiv.setAttribute ("class", "post"); document.getElementById ( "Contenuti") appendChild (newPostDiv).;
Eseguilo, quindi digita messaggi
e premi Invio. Vedrai un extra div
nella lista - anche se non abbiamo toccato il messaggi
variabile.
Dal NodeList
non è un array, non ha la maggior parte dei metodi e delle proprietà di schieramento
, ad esempio Spingere()
In effetti, abbiamo già utilizzato l'unica proprietà: lunghezza
. L'unico metodo è .item (n)
, che ottiene il n
l'articolo nella lista.
Tuttavia, la nostra precedente dimostrazione con appendChild ()
suggerisce una soluzione alternativa: cosa succede se, invece di cercare di riorganizzare gli elementi del NodeList
all'interno del NodeList
, li abbiamo riordinati all'interno della pagina?
Per prima cosa, esamineremo l'elenco in ordine inverso e aggiungiamo ogni elemento a turno al contenuto
div; quindi, rimuoveremo i post originali.
Aggiorna la pagina di Tumblr per eliminare tutti i rifiuti extra che abbiamo aggiunto al DOM, quindi fai il primo passo, aggiungendo gli elementi in ordine inverso:
// devo definire nuovamente i post, poiché li abbiamo persi quando abbiamo aggiornato var posts = document.getElementById ("contents"). getElementsByClassName ("post"); var numPosts = posts.length; for (var i = numPosts - 1; i> = 0; i--) document.getElementById ("contents"). appendChild (post [i]);
Ok, ora ... aspettiamo, cosa?
Il primo post (cronologico) è già in cima e l'ultimo post è in fondo, senza post ripetuti. Questo può sembrare sorprendente, ma ha senso: non lo abbiamo fatto clone qualsiasi elemento del NodeList
, li abbiamo appena aggiunti al contenuto
div, in ordine inverso. Dal momento che il NodeList
riflette sempre il contenuto del DOM HTML, noi semplicemente mosso ciascuno degli 11 elementi in una nuova posizione - l'undicesimo elemento è stato aggiunto alla fine (nessun cambiamento di posizione); poi il 10 è stato spostato per essere dopo quello; il 9 dopo, e così via, fino alla fine del 1 ° elemento.
Quindi, problema risolto, in cinque semplici righe di codice. Ora automatizziamolo.
Tre dei quattro principali browser ti consentono di creare estensioni del browser - componenti aggiuntivi installabili - utilizzando JavaScript. (Non ti sorprenderà sapere che Internet Explorer è l'eccezione.) Ecco le istruzioni per Chrome, le istruzioni per Firefox e le istruzioni per Safari.
Ma non useremo nessuno di questi. Invece, utilizzeremo un ottimo componente aggiuntivo chiamato Greasemonkey, che consente di installare piccoli script JS senza la necessità di comprimerli come estensioni del browser in piena regola. In sostanza, inserisce snippet di JavaScript nella pagina, una volta caricato.
Chrome ha già fornito il supporto per Greasemonkey. Opera ha qualcosa di molto simile a Greasemonkey in: UserJS. Per Firefox, dovrai installare l'estensione Greasemonkey. Per Safari, installa SIMBL e quindi GreaseKit. Per IE, installare IE7Pro o Trixie.
Crea un nuovo file di testo e nominalo ChronologicalTumblr.user.js
. Assicurati di rimuovere il valore predefinito .testo
estensione e che usi .user.js
, piuttosto che solo .js
- questa è l'estensione per uno script Greasemonkey.
Copia il nostro codice di riorganizzazione post nel file:
var posts = document.getElementById ("contents"). getElementsByClassName ("post"); var numPosts = posts.length; for (var i = numPosts - 1; i> = 0; i--) document.getElementById ("contents"). appendChild (post [i]);
Ora, abbiamo bisogno di aggiungere alcuni metadati extra nella parte superiore dello script - dettagli sullo script stesso. Tutti questi dettagli dovrebbero essere inclusi nei commenti, a partire da == userscript ==
e termina con == / userscript ==
:
// == UserScript == // // == / UserScript == var posts = document.getElementById ("contents"). GetElementsByClassName ("post"); var numPosts = posts.length; for (var i = numPosts - 1; i> = 0; i--) document.getElementById ("contents"). appendChild (post [i]);
Innanzitutto, aggiungeremo un nome e una descrizione:
// == UserScript == // @name Chronological Tumblr // @description Visualizza i post di Tumblr in ordine cronologico // == / UserScript == var posts = document.getElementById ("contents"). GetElementsByClassName ("post"); var numPosts = posts.length; for (var i = numPosts - 1; i> = 0; i--) document.getElementById ("contents"). appendChild (post [i]);
Quindi, specificheremo a namespace. La combinazione del nome e dello spazio dei nomi è ciò che identifica in modo univoco lo script; se si tenta di installare un altro script Greasemonkey con lo stesso nome e namespace come uno script esistente, sovrascriverà quello vecchio - se solo il nome o la corrispondenza dello spazio dei nomi, sarà sufficiente installare la nuova accanto alla vecchia.
È comune utilizzare un URL qui, quindi userò Activetuts +. Dovresti usare il tuo, dal momento che ne hai il controllo:
// == UserScript == // @name Chronological Tumblr // @description Visualizza i post di Tumblr in ordine cronologico // @namespace http://active.tutsplus.com/ // == / UserScript == var posts = document. getElementById ( "contenuti") getElementsByClassName ( "post").; var numPosts = posts.length; for (var i = numPosts - 1; i> = 0; i--) document.getElementById ("contents"). appendChild (post [i]);
Ora dobbiamo specificare quali URL questo script dovrebbe influenzare, cioè su quali pagine web deve essere iniettato automaticamente JavaScript. Voglio che questo script funzioni sulla homepage di BtotheF, oltre alle altre pagine di archivio, come http://btothef.tumblr.com/page/2:
// == UserScript == // @name Chronological Tumblr // @description Visualizza i post di Tumblr in ordine cronologico // @namespace http://active.tutsplus.com/ // @include http://btothef.tumblr.com / // @include http://btothef.tumblr.com/page/* // == / UserScript == var posts = document.getElementById ("contents"). getElementsByClassName ("post"); var numPosts = posts.length; for (var i = numPosts - 1; i> = 0; i--) document.getElementById ("contents"). appendChild (post [i]);
Il *
è un jolly; assicura che lo script venga inserito in ogni singola pagina di archivio di BtotheF Tumblr.
Potremmo usare un carattere jolly per visualizzare tutte le pagine di un archivio di Tumblr in ordine cronologico:
// == UserScript == // @name Chronological Tumblr // @description Visualizza i post di Tumblr in ordine cronologico // @namespace http://active.tutsplus.com/ // @include http: //*.tumblr.com / // @include http: //*.tumblr.com/page/* // == / UserScript == var posts = document.getElementById ("contents"). getElementsByClassName ("post"); var numPosts = posts.length; for (var i = numPosts - 1; i> = 0; i--) document.getElementById ("contents"). appendChild (post [i]);
In questo caso, potrebbe essere una buona idea migliorare lo script per inserire un pulsante o un collegamento nella pagina che riorganizza i post quando si fa clic. In questo modo, puoi utilizzarlo quando opportuno, senza dover aggiungere manualmente l'URL di ogni singolo Tumblr come @includere
parametro.
Ci sono altri parametri di metadati che potresti aggiungere, ma per ora è tutto ciò di cui abbiamo bisogno.
Installare lo script in Chrome è semplice: basta trascinarlo dal disco rigido in una finestra del browser. Ti avvertirà che gli script potrebbero essere potenzialmente pericolosi (fai semplicemente clic su Continua), quindi verifica nuovamente che desideri installare questo specifico:
Hit Installa. Se stai utilizzando un altro browser, fai riferimento al manuale dello script di Greasemonkey pertinente - in ogni caso, sarà semplice.
Una volta installato, puoi vederlo nell'elenco delle estensioni:
Torna a http://btothef.tumblr.com/, oppure premi Aggiorna se lo hai ancora aperto.
I post ora vengono visualizzati automaticamente in ordine cronologico!
Non è perfetto: potresti aver notato che i pulsanti di navigazione sono stati spostati nella parte superiore della pagina, poiché sono contenuti in un div con una classe di inviare
. Ma hey - se ti infastidisce, hai gli strumenti per sistemarlo ora.