Module: Vapir::HasRowsAndColumns
Instance Method Summary collapse
-
#[](index) ⇒ Object
Returns the TableRow at the given index.
-
#cell(first = nil, second = nil) ⇒ Object
returns a TableCell which is a cell of this of this Table or TBody (not in a nested table).
-
#cells ⇒ Object
returns all of the cells of this table.
-
#column_count(index = nil) ⇒ Object
returns the number of columns of the table, either on the row at the given index or (by default) on the first row.
-
#column_texts_at(column_index) ⇒ Object
Returns an array containing the text of the cell in the specified index in each row.
-
#each_row ⇒ Object
(also: #each)
iterates through the rows in the table.
-
#row(first = nil, second = nil) ⇒ Object
returns a TableRow which is a row of this of this Table or TBody (not in a nested table).
-
#row_count ⇒ Object
Returns the number of rows inside the table.
- #row_count_excluding_nested_tables ⇒ Object
-
#row_texts_at(row_index) ⇒ Object
Returns an array of the text of each cell in the row at the given index.
-
#to_a ⇒ Object
Returns a 2 dimensional array of text contents of each row and column of the table or tbody.
-
#to_hashes(options = {}) ⇒ Object
Returns an array of hashes representing this table.
Instance Method Details
#[](index) ⇒ Object
Returns the TableRow at the given index. indices start at 1.
701 702 703 |
# File 'lib/vapir-common/elements/elements.rb', line 701 def [](index) rows[index] end |
#cell(first = nil, second = nil) ⇒ Object
returns a TableCell which is a cell of this of this Table or TBody (not in a nested table). takes the usual arguments for specifying what you want - see github.com/vapir/vapir/wiki/Locators
609 610 611 612 613 614 615 616 |
# File 'lib/vapir-common/elements/elements.rb', line 609 def cell(first=nil, second=nil) element_by_howwhat(element_class_for(Vapir::TableCell), first, second, :extra => {:candidates => proc do |container| container_object=container.element_object object_collection_to_enumerable(container_object.rows).inject([]) do |candidates, row| candidates+object_collection_to_enumerable(row.cells).to_a end end}) end |
#cells ⇒ Object
returns all of the cells of this table. to get the cells including nested tables, use #table_cells, which is defined on all containers (including Table)
720 721 722 723 724 725 726 727 |
# File 'lib/vapir-common/elements/elements.rb', line 720 def cells ElementCollection.new(self, element_class_for(Vapir::TableCell), extra_for_contained.merge(:candidates => proc do |container| container_object=container.element_object object_collection_to_enumerable(container_object.rows).inject([]) do |candidates, row| candidates+object_collection_to_enumerable(row.cells).to_a end end)) end |
#column_count(index = nil) ⇒ Object
returns the number of columns of the table, either on the row at the given index or (by default) on the first row. takes into account any defined colSpans. returns nil if the table has no rows. (if you want the number of cells - not taking into account colspans - use #cell_count on the row in question)
735 736 737 738 739 740 741 742 743 |
# File 'lib/vapir-common/elements/elements.rb', line 735 def column_count(index=nil) if index rows[index].column_count elsif row=rows.first row.column_count else nil end end |
#column_texts_at(column_index) ⇒ Object
Returns an array containing the text of the cell in the specified index in each row.
758 759 760 761 762 763 |
# File 'lib/vapir-common/elements/elements.rb', line 758 def column_texts_at(column_index) # TODO: since this is named as 'column', not 'cell', shouldn't it return cell_at_column? rows.map do |row| row.cells[column_index].text end end |
#each_row ⇒ Object Also known as: each
iterates through the rows in the table. Yields a TableRow object
692 693 694 695 696 |
# File 'lib/vapir-common/elements/elements.rb', line 692 def each_row rows.each do |row| yield row end end |
#row(first = nil, second = nil) ⇒ Object
returns a TableRow which is a row of this of this Table or TBody (not in a nested table). takes the usual arguments for specifying what you want - see github.com/vapir/vapir/wiki/Locators
603 604 605 |
# File 'lib/vapir-common/elements/elements.rb', line 603 def row(first=nil, second=nil) element_by_howwhat(element_class_for(Vapir::TableRow), first, second, :extra => {:candidates => :rows}) end |
#row_count ⇒ Object
Returns the number of rows inside the table. does not recurse through nested tables. same as (object).rows.length
if you want the row count including nested tables (which this brokenly used to return) use (object).table_rows.length
710 711 712 |
# File 'lib/vapir-common/elements/elements.rb', line 710 def row_count element_object.rows.length end |
#row_count_excluding_nested_tables ⇒ Object
714 715 716 |
# File 'lib/vapir-common/elements/elements.rb', line 714 def row_count_excluding_nested_tables raise NotImplementedError, "the method \#row_count_excluding_nested_tables is gone. the \#row_count method now returns the number of rows in this #{self.class}. for the number of rows including nested tables, use [this object].table_rows.length" end |
#row_texts_at(row_index) ⇒ Object
Returns an array of the text of each cell in the row at the given index.
750 751 752 753 754 |
# File 'lib/vapir-common/elements/elements.rb', line 750 def row_texts_at(row_index) rows[row_index].cells.map do |cell| cell.text end end |
#to_a ⇒ Object
Returns a 2 dimensional array of text contents of each row and column of the table or tbody.
619 620 621 |
# File 'lib/vapir-common/elements/elements.rb', line 619 def to_a rows.map{|row| row.cells.map{|cell| cell.text.strip}} end |
#to_hashes(options = {}) ⇒ Object
Returns an array of hashes representing this table. This assumes that the table has one row with header information and any number of rows with data. Each element of the array is a hash whose keys are the header values (every hash has the same keys), and whose values correspond to the current row.
+--------------+---------------+
| First Header | Second Header |
| First Data 1 | Second Data 1 |
| First Data 2 | Second Data 2 |
+--------------+---------------+
Given the above table, #to_hashes will return
[{'First Header' => 'First Data 1', 'Second Header' => 'Second Data 1'}, {'First Header' => 'First Data 2', 'Second Header' => 'Second Data 2'}]
This method will correctly account for colSpans and return text from all cells underneath a given header on one row. However, this method makes no attempt to deal with any rowSpans and will probably not work with any table with rowSpans in either the header row or data rows.
options:
-
:header_count (default 1) - the number of rows before the table data start.
-
:header_index (default whatever :header_count is) - the index of the row that contains header data which will be the keys of the hashes returned. (1-indexed)
-
:footer_count (default 0) - the number of rows to discard from the end, being footer information and not table data.
-
:separator (default ‘ ’) - used to join cells when there is more than one cell underneath a header.
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 |
# File 'lib/vapir-common/elements/elements.rb', line 649 def to_hashes(={}) =(, {:header_count => 1, :footer_count => 0, :separator => ' '}, [:header_index]) [:header_index]||=[:header_count] col_headings=rows[[:header_index]].cells.map do |cell| {:colSpan => cell.colSpan || 1, :text => cell.text.strip} end body_range=([:header_count]+1 .. self.row_count-[:footer_count]) return body_range.map do |row_index| row=rows[row_index] # cells_by_heading will contain an array of arrays of table cells # underneath the col_heading corresponding to cells_by_heading's array index. # if cells do not line up underneath the column heading, exception is raised. cells_by_heading=[] curr_heading_index=0 cols_in_curr_heading=0 row.cells.each do |cell| curr_heading=col_headings[curr_heading_index] cells_by_heading[curr_heading_index] ||= [] cells_by_heading[curr_heading_index] << cell cols_in_curr_heading += cell.colSpan || 1 if cols_in_curr_heading == curr_heading[:colSpan] curr_heading_index+=1 cols_in_curr_heading=0 elsif cols_in_curr_heading > curr_heading[:colSpan] raise "Cells underneath heading #{curr_heading[:text].inspect} do not line up!" end # else, we haven't got all the cells under the current heading; keep going end if curr_heading_index > col_headings.length raise "Too many cells for the headings!" elsif curr_heading_index < col_headings.length raise "Too few cells for the headings!" end col_headings.zip(cells_by_heading).inject({}) do |row_hash, (heading, cells)| cell_texts=cells.map(&:text).join([:separator]).strip row_hash.merge(heading[:text] => cell_texts) end end end |