2013-07-06 27 views
8

Mam następujący przykład:Phantomjs nie czyni stopek z niestandardowych stylów

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); 
     } 
    }); 
} 

W powyższym przykładzie używam footer_style klasę, która lubi wyglądać w moim pliku css o następującej treści:

.footer_style { 
    text-align:right; 
} 

Ale niestety to nie działa. Próbuję utworzyć plik pdf w następujący sposób:

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

Odpowiedz

3

Z moich wcześniejszych doświadczeń phantomjs nie obsługuje stylów w niestandardowym nagłówku/stopce.

Jedynym rozwiązaniem, które znalazłem jest zastosowanie stylu wbudowanego takiego:

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); 
    } 
}); 
} 

Uwaga: Przecinek brakuje w kodzie po margin: "1cm"

+0

Tak wiem to rozwiązanie, ale trzeba go uruchomić za pomocą klas cSS – Erik

9

Wiemy, że ćwiczenia nie działają ale inline style robią. Możemy tylko zastąpić klasę stylem obliczeniowym.

Oto funkcja, która zajmie kawałek html, utworzy tymczasowy element w ciele za pomocą html, obliczy styl dla każdego elementu za pomocą klasy, doda wbudowany styl do linii i zwróci nowy 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); 
} 

Następnie wystarczy wywołać tę funkcję w swojej stopce:

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

Trzeba będzie przenieść to wszystko wewnątrz page.open().

Przetestowałem to i stopka jest wyrównana w prawo.

+0

Wygląda to jak idealne rozwiązanie do renderowania nagłówków/stopek, ale w wersji 1.9.7 wydaje się to "opróżniać" document.body po appendChild. Prawdopodobnie błąd PhantomJS. Którą wersję przetestowałeś w tym? –

+2

Naprawiono ten problem^i kilka innych: http://stackoverflow.com/a/27296129/678265 –

4

Mam aktualizację mak's excellent answer dla PhantomJS 1.9.7.

Ta wersja poprawki:

  • obejścia błędów, które „puste to dokument nadrzędny (PhantomJS 1.9.7)
  • Style mixups gdy style zagnieżdżone (do głębokości pierwszego przechodzenie zamiast)
  • działa również gdy znaczniki nie mają zajęcia
/** 
* 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); 
}