views:

1098

answers:

3

Hello all, I have read through all relevant posts on Prawn but found no mentioning (even in Prawn's own documentation) of headers and footers.

However, I did see a demo on Prawnto's own website about headers and footers. I copied the entire source of that demo just to see if it works but an error of undefined method "header" is complained about. Am I to understand that Prawn took out header and footer recently in the gem or is there something else I need to do first to use header and footer?

The demo page: http://cracklabs.com/prawnto/code/prawn_demos/source/text/flowing_text_with_header_and_footer

the part of code of concern:

Prawn::Document.generate("flow_with_headers_and_footers.pdf") do

header margin_box.top_left do text "Here's My Fancy Header", :size => 25, :align => :center
end

text "hello world!" end

And by header, just in case, I mean the snippets of words that appear usually at a corner of every page of a document. Like your account number in your bills pages.

thanks!

A: 

The only way I've found to get a repeating item on a page is to use the Prawn::Document::LazyBoundingBox method. Basically this allows you to define a bounding box that is only rendered once you call it. So the usual pseudo-code steps are

1. Define lazy bounding box element assign to somevar
2. One each new page call the element.

The example from the source shows how

file = "lazy_bounding_boxes.pdf"
Prawn::Document.generate(file, :skip_page_creation => true) do
  point = [bounds.right-50, bounds.bottom + 25]
  page_counter = lazy_bounding_box(point, :width => 50) do
  text "Page: #{page_count}"
end 

10.times do
  start_new_page
  text "Some filler text for the page"  
  page_counter.draw
end

end

This gives you a Page-count text output on each new page. What would be ideal is if this could be applied in the setup of a page template that is reused without the manual call to render the element. The combined with text flow it would give the traditional solution of headers and footers.

Grant Sayer
+3  A: 

@GrantSayer thx for the example, but this will only let you show the current page number, not the total number of pages.

You can also use the number_pages function for the footer:

Prawn::Document.generate("page_with_numbering.pdf") do
  text "Hai"
  start_new_page
  text "bai"
  start_new_page
  text "-- Hai again"
  number_pages "<page> in a total of <total>", [bounds.right - 50, 0]
end

However, in my case I also need to format/style and right align the page numbers to match company style guides. I used go_to_page(k) to create my own header and footer functions, which add the header and footer to each page after all the pages are created. This gives me both styling options and the total number of pages:

Prawn::Document.generate("footer_example.pdf", :skip_page_creation => true) do
  10.times do
    start_new_page
    text "Some filler text for the page"
  end

  # footer
  page_count.times do |i|
    go_to_page(i+1)
    lazy_bounding_box([bounds.right-50, bounds.bottom + 25], :width => 50) {
      text "#{i+1} / #{page_count}"
    }.draw
  end
end
gawin
+3  A: 

The sample you are refering to, from the prawnto plugin, is using an older version of prawn.

Since i also needed header and footer i looked a bit more into this. It seems that that version of prawn had header and footer methods, which were implemented using lazy bounding box. (found by checking the code on github)

In the new prawn version you can do the same thing using repeaters.

Here is the full sample rewritten using the new version:

require "#{File.dirname(__FILE__)}/../example_helper.rb"

Prawn::Document.generate("test.pdf")  do

   repeat :all do
    # header
    bounding_box [bounds.left, bounds.top], :width  => bounds.width do
        font "Helvetica"
        text "Here's My Fancy Header", :align => :center, :size => 25
        stroke_horizontal_rule
    end

    # footer
    bounding_box [bounds.left, bounds.bottom + 25], :width  => bounds.width do
        font "Helvetica"
        stroke_horizontal_rule
        move_down(5)
        text "And here's a sexy footer", :size => 16
    end
  end

  bounding_box([bounds.left, bounds.top - 50], :width  => bounds.width, :height => bounds.height - 100) do                 
   text "this is some flowing text " * 200    

   move_down(20)

   font "#{Prawn::BASEDIR}/data/fonts/DejaVuSans.ttf"
   table [["ὕαλον ϕαγεῖν",    "baaar",             "1" ],
          ["This is","a sample",          "2" ],
          ["Table",  "dont\ncha\nknow?",  "3" ],
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules\nwith an iron fist", "x" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],   
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],  
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ]],     

     :font_size          => 24, 
     :horizontal_padding => 10,
     :vertical_padding   => 3,
     :border_width       => 2,
     :position           => :center,
     :headers            => ["Column A","Column B","#"]

  end
end

you can check the documentation page of repeat for other options which allow you to exactly specify where you want the repeaters.

memical