Skip to content

Commit

Permalink
Rewrite HtmlOutputter
Browse files Browse the repository at this point in the history
  • Loading branch information
toretore committed Jan 31, 2012
1 parent 0b9eb1b commit 268a077
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 75 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG
@@ -1,3 +1,11 @@
* master

* Rewrite HtmlOutputter. Not entirely backwards compatible with the previous version.

* 0.5.0

* Require requirement of barcode symbologies in the same way outputters must be required before being used

* 0.4.4

* Use Gemfile for dependency management [Ken Collins]
Expand Down
137 changes: 71 additions & 66 deletions lib/barby/outputter/html_outputter.rb
Expand Up @@ -2,87 +2,92 @@

module Barby

# Outputs an HTML representation of the barcode.
#
# Registers to_html
#
# Allowed options include.
# :width - Applied to parent element's style attribute. Default 100.
# :height - Applied to parent element's style attribute. Default 100.
# :css - Include Barby::HtmlOutputter.css in output's style tag. If you pass false
# you can include the output of Barby::HtmlOutputter.css in single place like
# your own stylesheet on once on the page. Default true.
# :parent_style - Include inline style for things like width and height on parent element.
# Useful if you want to style these attributes elsewhere globally. Default true.
# Outputs an HTML <table> containing cells for each module in the barcode.
#
# This does NOT include any styling, you're expected to add the relevant
# CSS yourself. The markup is simple: One <table> with class 'barby-barcode',
# one or more <tr class="barby-row"> inside a <tbody> each containing
# <td class="barby-cell"> for each module with the additional class "on" or "off".
#
# Example, let's say the barcode.encoding == ['101', '010'] :
#
# <table class="barby-barcode">
# <tbody>
# <tr class="barby-row">
# <td class="barby-cell on"></td>
# <td class="barby-cell off"></td>
# <td class="barby-cell on"></td>
# </tr>
# <tr class="barby-row">
# <td class="barby-cell off"></td>
# <td class="barby-cell on"></td>
# <td class="barby-cell off"></td>
# </tr>
# </tbody>
# </table>
#
# You could then style this with:
#
# table.barby-barcode { border-spacing: 0; }
# tr.barby-row {}
# td.barby-cell { width: 3px; height: 3px; }
# td.barby-cell.on { background: #000; }
#
# Options:
#
# :class_name - A class name that will be added to the <table> in addition to barby-barcode
class HtmlOutputter < Outputter

register :to_html

def self.css
<<-CSS
table.barby_code {
border: 0 none transparent !important;
border-collapse: collapse !important;
}
table.barby_code tr.barby_row {
border: 0 none transparent !important;
border-collapse: collapse !important;
margin: 0 !important;
padding: 0 !important;
}
table.barby_code tr.barby_row td { border: 0 none transparent !important; }
table.barby_code tr.barby_row td.barby_black { background-color: black !important; }
table.barby_code tr.barby_row td.barby_white { background-color: white !important; }
CSS

attr_accessor :class_name


def to_html(options = {})
with_options options do
start + rows.join + stop
end
end

def to_html(options={})
default_options = {:width => 100, :height => 100, :css => true, :parent_style => :true}
options = default_options.merge(options)
elements = if barcode.two_dimensional?
booleans.map do |bools|
line_to_elements_row(bools, options)
end.join("\n")
else
line_to_elements_row(booleans, options)
end
html = %|<#{parent_element} class="barby_code" #{parent_style_attribute(options)}>\n#{elements}\n</#{parent_element}>|
options[:css] ? "<style>#{self.class.css}</style>\n#{html}" : html


def rows
if barcode.two_dimensional?
rows_for(booleans)
else
rows_for([booleans])
end
end


private
def rows_for(boolean_groups)
boolean_groups.map{|g| row_for(cells_for(g)) }
end

def line_to_elements_row(bools, options)
elements = bools.map{ |b| b ? black_tag : white_tag }.join
Array(%|<#{row_element} class="barby_row">#{elements}</#{row_element}>|)
def cells_for(booleans)
booleans.map{|b| b ? on_cell : off_cell }
end
def black_tag
'<td class="barby_black"></td>'

def row_for(cells)
cells.map{|c| "<tr class=\"barby-row\">#{c}</tr>" }.join
end
def white_tag
'<td class="barby_white"></td>'

def on_cell
'<td class="barby-cell on"></td>'
end
def row_element
'tr'

def off_cell
'<td class="barby-cell off"></td>'
end
def parent_element
'table'

def start
'<table class="barby-barcode'+(class_name ? " #{class_name}" : '')+'"><tbody>'
end

def parent_style_attribute(options)
return unless options[:parent_style]
s = ''
s << "width: #{options[:width]}px; " if options[:width]
s << "height: #{options[:height]}px; " if options[:height]
s.strip!
s.empty? ? nil : %|style="#{s}"|

def stop
'</tbody></table>'
end


end

end
61 changes: 52 additions & 9 deletions test/outputter/html_outputter_test.rb
@@ -1,25 +1,68 @@
require 'test_helper'
require 'barby/barcode/code_128'
#require 'barby/outputter/html_outputter'

class HtmlOutputterTest < Barby::TestCase

class MockCode
attr_reader :encoding
def initialize(e)
@encoding = e
end
def two_dimensional?
encoding.is_a? Array
end
end

before do
load_outputter('html')
@barcode = Barby::Code128B.new('BARBY')
@outputter = HtmlOutputter.new(@barcode)
end

it "should register to_html" do
Barcode.outputters.must_include(:to_html)
end

it "should include css style tag by default with option to leave out" do
@barcode.to_html.must_include "<style>#{Barby::HtmlOutputter.css}</style>"
@barcode.to_html(:css => false).wont_include "<style>#{Barby::HtmlOutputter.css}</style>"

it 'should have the expected start HTML' do
assert_equal '<table class="barby-barcode"><tbody>', @outputter.start
end

it 'should be able to set additional class name' do
@outputter.class_name = 'humbaba'
assert_equal '<table class="barby-barcode humbaba"><tbody>', @outputter.start
end

it 'should have the expected stop HTML' do
assert_equal '</tbody></table>', @outputter.stop
end

it "should include inline parent style for width and height with option to disable" do
@barcode.to_html.must_include '<table class="barby_code" style="width: 100px; height: 100px;">'
@barcode.to_html(:parent_style => false).must_include '<table class="barby_code" >'

it 'should build the expected cells' do
assert_equal ['<td class="barby-cell on"></td>', '<td class="barby-cell off"></td>', '<td class="barby-cell off"></td>', '<td class="barby-cell on"></td>'],
@outputter.cells_for([true, false, false, true])
end

it 'should build the expected rows' do
assert_equal(
[
@outputter.cells_for([true, false]).map{|c| "<tr class=\"barby-row\">#{c}</tr>" }.join,
@outputter.cells_for([false, true]).map{|c| "<tr class=\"barby-row\">#{c}</tr>" }.join
],
@outputter.rows_for([[true, false],[false, true]])
)
end

it 'should have the expected rows' do
barcode = MockCode.new('101100')
outputter = HtmlOutputter.new(barcode)
assert_equal outputter.rows_for([[true, false, true, true, false, false]]), outputter.rows
barcode = MockCode.new(['101', '010'])
outputter = HtmlOutputter.new(barcode)
assert_equal outputter.rows_for([[true, false, true], [false, true, false]]), outputter.rows
end

it 'should have the expected html' do
assert_equal @outputter.start + @outputter.rows.join + @outputter.stop, @outputter.to_html
end

end

0 comments on commit 268a077

Please sign in to comment.