2013-07-06 13 views
8

ho il seguente esempio:Phantomjs non rende piè di pagina con stili personalizzati

var page = require('webpage').create(), 
    system = require('system'); 

if (system.args.length < 3) { 
    console.log('Usage: printheaderfooter.js URL filename'); 
    phantom.exit(1); 
} else { 
    var address = system.args[1]; 
    var output = system.args[2]; 
    page.viewportSize = { width: 600, height: 600 }; 
    page.paperSize = { 
     format: 'A4', 
     margin: "1cm" 
     footer: { 
      height: "1cm", 
      contents: phantom.callback(function(pageNum, numPages) { 
       if (pageNum == numPages) { 
        return ""; 
       } 
       return "<h1 class='footer_style'>Footer" + pageNum + "/" + numPages + "</h1>"; 
      }) 
     } 
    }; 
    page.open(address, function (status) { 
     if (status !== 'success') { 
      console.log('Unable to load the address!'); 
     } else {     
      window.setTimeout(function() { 
       page.render(output); 
       phantom.exit(); 
      }, 200); 
     } 
    }); 
} 

Nell'esempio di cui sopra che uso classe footer_style che piace guardare nel mio file css il seguente:

.footer_style { 
    text-align:right; 
} 

Ma sfortunatamente questo non funziona. Sto cercando di creare file PDF come segue:

./phantomjs rasterize.js index.html test.pdf 

risposta

3

Dalla mia esperienza passata, phantomjs non supporta gli stili nell'intestazione/piè di pagina personalizzata.

L'unica soluzione che ho trovato è quello di applicare uno stile in linea come questa:

var page = require('webpage').create(), 
    system = require('system'); 

if (system.args.length < 3) { 
    console.log('Usage: printheaderfooter.js URL filename'); 
    phantom.exit(1); 
} else { 
    var address = system.args[1]; 
    var output = system.args[2]; 
    page.viewportSize = { width: 600, height: 600 }; 
    page.paperSize = { 
     format: 'A4', 
     margin: "1cm", 
     footer: { 
     height: "1cm", 
     contents: phantom.callback(function(pageNum, numPages) { 
      return "<h1 style='text-align:right'>Footer" + pageNum + "/" + numPages + "</h1>"; 
     }) 
     } 
}; 
page.open(address, function (status) { 
    if (status !== 'success') { 
     console.log('Unable to load the address!'); 
    } else {     
     window.setTimeout(function() { 
      page.render(output); 
      phantom.exit(); 
     }, 200); 
    } 
}); 
} 

Nota: Una virgola mancante nel codice dopo margin: "1cm"

+0

Sì, lo so questa soluzione, ma ho bisogno di farlo funzionare utilizzando le classi CSS – Erik

9

Sappiamo che le classi non funzionano, ma in linea gli stili fanno Quello che possiamo fare è sostituire la classe con lo stile calcolato.

Ecco una funzione che prenderà un pezzo di html, creerà un elemento temporaneo nel corpo con l'html, calcola lo stile per ogni elemento con una classe, aggiunge lo stile calcolato in linea e restituisce il nuovo html.

function replaceClassWithStyle(html) { 
    return page.evaluate(function(html) { 
     var host = document.createElement('div'); 
     host.innerHTML = html; 
     document.body.appendChild(host); // if not appended, values will be blank 
     var elements = host.getElementsByTagName('*'); 
     for (var i in elements) { 
      if (elements[i].className) { 
       elements[i].setAttribute('style', window.getComputedStyle(elements[i], null).cssText); 
      } 
     } 
     document.body.removeChild(host); 
     return host.innerHTML; 
    }, html); 
} 

Poi semplicemente chiamare questa funzione nel vostro piè di pagina:

page.paperSize = { 
    footer: { 
     contents: phantom.callback(function(pageNum, numPages) { 
      if (pageNum == numPages) { 
       return ""; 
      } 
      return replaceClassWithStyle("<h1 class='footer_style'>Footer" + pageNum + "/" + numPages + "</h1>"); 
     }) 
    } 
}; 

Sarà necessario spostare tutto questo all'interno page.open().

L'ho provato e il piè di pagina è allineato a destra.

+0

Sembra la soluzione ideale per il rendering di intestazioni/piè di pagina, ma in v1.9.7 sembra "svuotare" il documento. Corpo dopo appendChild. Probabilmente un bug di PhantomJS. In quale versione hai provato questo? –

+2

risolto il problema^e alcuni altri: http://stackoverflow.com/a/27296129/678265 –

4

Ho un aggiornamento a mak's excellent answer per PhantomJS 1.9.7.

Questa versione corregge:

  • aggirare bug che 'vuoto' il documento principale (PhantomJS 1.9.7)
  • mixups stile quando gli stili sono annidate (fare attraversamento in profondità invece)
  • funziona anche quando i tag non hanno classi
/** 
* Place HTML in the parent document, convert CSS styles to fixed computed style declarations, and return HTML. 
* (required for headers/footers, which exist outside of the HTML document, and have trouble getting styling otherwise) 
*/ 
function replaceCssWithComputedStyle(html) { 
    return page.evaluate(function(html) { 
    var host = document.createElement('div'); 
    host.setAttribute('style', 'display:none;'); // Silly hack, or PhantomJS will 'blank' the main document for some reason 
    host.innerHTML = html; 

    // Append to get styling of parent page 
    document.body.appendChild(host); 

    var elements = host.getElementsByTagName('*'); 
    // Iterate in reverse order (depth first) so that styles do not impact eachother 
    for (var i = elements.length - 1; i >= 0; i--) { 
     elements[i].setAttribute('style', window.getComputedStyle(elements[i], null).cssText); 
    } 

    // Remove from parent page again, so we're clean 
    document.body.removeChild(host); 
    return host.innerHTML; 
    }, html); 
}