Intercetta e modifica il DOM prima che la pagina venga visualizzata all’utente

Sto provando a creare un addon di Firefox (usando l’addon SDK) che modificherà il modo in cui viene visualizzata la pagina, principalmente come un esercizio di formazione / apprendimento.

Per alcune attività (come aumentare le pagine con nuove funzionalità) utilizzando pageMod è perfettamente a posto. La pagina viene caricata ed eseguo alcune JS per mostrare / hide / aggiungere elementi.

Il mio problema è: posso eseguire modifiche su DOM (quindi: il documento HTML che viene restituito dal server) prima che la pagina inizi a essere visualizzata?

Ad esempio: la pagina restituita dal server è:

   
Item 1.1 Item 1.2 Item 1.3
Item 2.1 Item 2.2 Item 2.3

ma vorrei che FF eseguisse il rendering:

       
    • Item 1.1, Item 1.2, Item 1.3
    • Item 2.1, Item 2.2, Item 2.3

    Farlo dopo il caricamento della pagina dovrebbe prima visualizzare la tabella, quindi rapidamente si “blink” in un elenco. Potrebbe essere abbastanza veloce, ma se dovessi cambiare i tag in , per esempio evitare i carichi di immagini (non voluti), non è sufficiente.

    Stavo guardando usando contentScriptWhen: "start" in pageMod e provando ad albind listener, ma non riesco a vedere come posso effettivamente modificare il DOM ‘al volo’ (o evento prevenire qualsiasi tipo di visualizzazione della pagina prima che tutta la pagina fosse caricata ).

    Ho controllato l’ estensione cloud-to-butt , in quanto modifica la pagina al volo, ma non ero nemmeno in grado di farlo funzionare: quando collegato come pageMod start il codice non è riuscito su:

      document.getElementById('appcontent').addEventListener('DOMContentLoaded', function(e) 

    perché document.getElementById('appcontent') restituiva null.

    Sarei immensamente grato per alcuni suggerimenti: è ansible, come albind lo script, come intercettare l’HTML e rimetterlo in funzione dopo alcune modifiche.

    EDIT: Ok, quindi penso di essere in grado di intercettare i dati:

     let { Ci,Cr,CC } = require('chrome'); let { on } = require('sdk/system/events'); let { newURI } = require('sdk/url/utils'); let ScriptableInputStream = CC("@mozilla.org/scriptableinputstream;1", "nsIScriptableInputStream", "init"); on('http-on-examine-response', function (event) { var httpChannel = event.subject.QueryInterface(Ci.nsIHttpChannel); var traceChannel = event.subject.QueryInterface(Ci.nsITraceableChannel); if (/example.com/.test(event.subject.URI.spec)) { traceChannel.setNewListener(new MyListener()); } }, true); function MyListener(downloader) { this.data = ""; } MyListener.prototype = { onStartRequest: function(request, ctx) { this.data = []; }, onDataAvailable : function(request, context, inputStream, offset, count) { var scriptStream = new ScriptableInputStream(inputStream); this.data.push(scriptStream.read(count)); scriptStream.close(); }, onStopRequest: function(request, ctx, status) { console.log(this.data.join('')); } } 

    Ora su onStopRequest mi piacerebbe fare qualcosa per i dati e restituirli a dove stava originariamente andando …

    Nota, questo funziona su stringhe non DOM, quindi non è perfetto, ma è un punto di partenza 🙂

    EDIT2:

    Huh, l’ho fatto funzionare, anche se ho la sensazione che non dovrei farlo in questo modo:

     onStopRequest: function(request, ctx, status) { //var newPage = this.data.join(''); var newPage = "

    TEST!

    "; var stream = converter.convertToInputStream(newPage); var count = {}; converter.convertToByteArray(newPage, count); this.originalListener.onDataAvailable(request, ctx, stream, 0, count.value); this.originalListener.onStopRequest(request, ctx, status); },

    Il mio problema è: posso eseguire modifiche su DOM (quindi: il documento HTML che viene restituito dal server) prima che la pagina inizi a essere visualizzata?

    Sì, l’esecuzione di JavaScript inizia prima che la pagina venga visualizzata per la prima volta. Il parser DOM avvisa gli osservatori di mutazione , quindi puoi rimuovere immediatamente gli elementi non appena vengono aggiunti dal parser.

    È ansible registrare gli osservatori di mutazione anche negli script di contenuto caricati con contentScriptWhen: "start" modo che vengano notificati di tutti gli elementi aggiunti all’albero prima di essere renderizzati poiché le notifiche dell’osservatore vengono eseguite nella coda di micro attività mentre il rendering avviene sulla macro coda dei compiti.

    ma non ero nemmeno in grado di farlo funzionare: quando collegato come pageMod all’avvio il codice non è riuscito su: document.getElementById('appcontent').addEventListener('DOMContentLoaded', function(e)

    Ovviamente. Non dovresti assumere che qualsiasi elemento in particolare – nemmeno il tag – sia già disponibile così presto durante il caricamento della pagina. Dovrai aspettare che diventino disponibili.

    E l’evento DOMContentLoaded può semplicemente essere registrato sull’object del document . Non so perché lo avresti registrato su qualche elemento.

    (o evento impedisce qualsiasi tipo di visualizzazione della pagina prima che tutta la pagina sia stata caricata).

    Non lo vuoi davvero perché aumenterebbe i tempi di caricamento della pagina e quindi ridurrebbe la reattività del sito web.

     /* * contentScriptWhen: "start" * * "start": Load content scripts immediately after the document * element is inserted into the DOM, but before the DOM content * itself has been loaded */ /* * use an empty HTMLElement both as a place_holder * and a way to prevent the DOM content from loading */ document.replaceChild( document.createElement("html"), document.children[0]); var rqst = new XMLHttpRequest(); rqst.open("GET", document.URL); rqst.responseType = 'document'; rqst.onload = function(){ if(this.status == 200) { /* edit the document */ this.response.children[0].children[1].querySelector( "#content-load + div + script").remove(); /* replace the place_holder */ document.replaceChild( document.adoptNode( this.response.children[0]), document.children[0]); // use_the_new_world(); } }; rqst.send(); 

    Se vuoi approfondire l’argomento prima dell’esecuzione di qualsiasi script, qui ci sono gli osservatori di documenti: https://developer.mozilla.org/en-US/docs/Observer_Notifications#Documenti come content-document-global-created