sorting_table_for 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,7 +13,8 @@ module SortingTableFor
13
13
  :default_boolean, :show_total_entries,
14
14
  :params_sort_table, :i18n_default_format_date,
15
15
  :html_sorting_class, :default_actions,
16
- :i18n_default_scope, :i18n_add_header_action_scope
16
+ :i18n_default_scope, :i18n_add_header_action_scope,
17
+ :i18n_add_footer_action_scope
17
18
 
18
19
  self.reserved_columns = [:id, :password, :salt]
19
20
  self.currency_columns = [:price, :total_price, :currency, :money]
@@ -25,11 +26,12 @@ module SortingTableFor
25
26
  self.default_actions = [:edit, :delete]
26
27
  self.i18n_default_scope = [:namespace, :controller, :action]
27
28
  self.i18n_add_header_action_scope = :header
29
+ self.i18n_add_footer_action_scope = :footer
28
30
 
29
31
  def initialize(collection, object_or_array, template, options, params)
30
32
  @collection, @@object_or_array, @@template, @@options, @@params = collection, object_or_array, template, options, params
31
- I18n.set_options(params, model_name(@collection.first), object_or_array.first)
32
33
  set_default_global_options
34
+ I18n.set_options(params, model_name(@collection.first), object_or_array.first, @@options[:i18n])
33
35
  @lines = []
34
36
  end
35
37
 
@@ -75,9 +77,10 @@ module SortingTableFor
75
77
  #
76
78
  # === Options
77
79
  #
78
- # All options are passed down to the fieldser HTML attribtues (id, class, title, ...) expect
79
- # for option sort.
80
- #
80
+ # * :sort - true of false to add or not sorting
81
+ # * :html - Hash options: class, id, ...
82
+ # * :caption - set caption on td
83
+ #
81
84
  # # Html option:
82
85
  # <% sorting_table_for @users do |table| do %>
83
86
  # <%= table.headers :username, :firstname, :html => { :class => 'my_class', :id => 'my_id' }
@@ -170,6 +173,7 @@ module SortingTableFor
170
173
  #
171
174
  # * :sort - true of false to add or not sorting
172
175
  # * :html - Hash options: class, id, ...
176
+ # * :caption - set caption on td
173
177
  #
174
178
  # === Values
175
179
  #
@@ -243,6 +247,7 @@ module SortingTableFor
243
247
  # * :actions - Set actions to render
244
248
  # * :only - Columns only to render
245
249
  # * :except - Columns to not render
250
+ # * :caption - set caption on td
246
251
  #
247
252
  # # Exemples:
248
253
  # <% sorting_table_for @users do |table| %>
@@ -318,7 +323,7 @@ module SortingTableFor
318
323
  #
319
324
  # the values given to columns can be anything. Only the symbols are the values of the collection.
320
325
  # If you give other types (string, image, ...) there won't be interpreted.
321
- #
326
+ #
322
327
  def columns(*args, &block)
323
328
  column_options, html_options = get_column_and_html_options( args.extract_options! )
324
329
  @collection.each do |object|
@@ -366,6 +371,7 @@ module SortingTableFor
366
371
  # * :as - Force to render a type (:date, :time, :currency)
367
372
  # * :format - Set the I18n localization format for :date or :time (:default, :short, ...)
368
373
  # * :action - Set an action
374
+ # * :caption - set caption on td
369
375
  #
370
376
  # # Exemple:
371
377
  # <% sorting_table_for @users do |table| %>
@@ -394,6 +400,170 @@ module SortingTableFor
394
400
  nil
395
401
  end
396
402
 
403
+ # Create a footer around tfoot and tr.
404
+ # It can be called with or without a block.
405
+ # These two exemples are equivalent:
406
+ #
407
+ # # With a list:
408
+ # <% sorting_table_for @users do |table| %>
409
+ # <%= table.footers :username, :firstname %>
410
+ # <% end %>
411
+ #
412
+ # # With a block:
413
+ # <% sorting_table_for @users do |table| %>
414
+ # <%= table.footers do %>
415
+ # <%= table.footer :username %>
416
+ # <%= table.footer :firstname %>
417
+ # <% end %>
418
+ # <% end %>
419
+ #
420
+ # # Output:
421
+ # <table class='sorting_table_for'>
422
+ # <tfoot>
423
+ # <tr>
424
+ # <td>...</td>
425
+ # <td>...</td>
426
+ # </tr>
427
+ # </tfoot>
428
+ # </table>
429
+ #
430
+ # === Options
431
+ #
432
+ # * :html - Hash options: class, id, ...
433
+ # * :caption - set caption on td
434
+ #
435
+ # # Exemples:
436
+ # <% sorting_table_for @users do |table| %>
437
+ # <%= table.columns :username, :cation => 5 %>
438
+ # <% end %>
439
+ #
440
+ # === I18n
441
+ #
442
+ # Add a value on scope for footer. Only with symbol.
443
+ #
444
+ # # Exemple of i18n_add_header_action_scope:
445
+ # SortingTableFor::TableBuilder.i18n_add_footer_action_scope = :footer
446
+ #
447
+ # # Ouput:
448
+ # I18n.t(:edit, :scope => [:current_controller, :current_action]) => en.current_controller.current_action.footer.edit
449
+ #
450
+ def footers(*args, &block)
451
+ column_options, html_options = get_column_and_html_options( args.extract_options! )
452
+ if block_given?
453
+ @footer_line = FormatLine.new(args, column_options, html_options, nil, :tfoot)
454
+ @@template.capture(&block)
455
+ else
456
+ @footer_line = FormatLine.new(args, column_options, html_options, @collection.first, :tfoot) if !args.empty?
457
+ end
458
+ render_tfoot
459
+ end
460
+
461
+ # Create a cell of footer, to have more control.
462
+ # It can be called with or without a block.
463
+ # The three exemples are equivalent:
464
+ #
465
+ # # With a block:
466
+ # <% sorting_table_for @users do |table| %>
467
+ # <%= table.footers do %>
468
+ # <%= table.footer :username %>
469
+ # <%= table.footer :firstname %>
470
+ # <% end %>
471
+ # <% end %>
472
+ #
473
+ # # With a block:
474
+ # <% sorting_table_for @users do |table| %>
475
+ # <%= table.footers do %>
476
+ # <%= table.footer do %>
477
+ # <%= :username %>
478
+ # <% end %>
479
+ # <%= table.footer do %>
480
+ # <%= :firstname %>
481
+ # <% end %>
482
+ # <% end %>
483
+ # <% end %>
484
+ #
485
+ # === Options
486
+ #
487
+ # * :html - Hash options: class, id, ...
488
+ # * :caption - set caption on td
489
+ #
490
+ # # Exemples:
491
+ # <% sorting_table_for @users do |table| %>
492
+ # <%= table.columns :username, :cation => 5 %>
493
+ # <% end %>
494
+ #
495
+ # === I18n
496
+ #
497
+ # Add a value on scope for footer. Only with symbol.
498
+ #
499
+ # # Exemple of i18n_add_header_action_scope:
500
+ # SortingTableFor::TableBuilder.i18n_add_footer_action_scope = :footer
501
+ #
502
+ # # Ouput:
503
+ # I18n.t(:edit, :scope => [:current_controller, :current_action]) => en.current_controller.current_action.footer.edit
504
+ #
505
+ # With block the value won't be interpreted.
506
+ #
507
+ def footer(*args, &block)
508
+ if block_given?
509
+ block = @@template.capture(&block)
510
+ @footer_line.add_cell(@collection.first, args, nil, block)
511
+ else
512
+ @footer_line.add_cell(@collection.first, args)
513
+ end
514
+ nil
515
+ end
516
+
517
+ # Create a tag caption to set a title to the table
518
+ # It can be called with or without a block.
519
+ # The two exemples are equivalent:
520
+ #
521
+ # # Without block
522
+ # <% sorting_table_for @users do |table| %>
523
+ # <%= table.caption 'hello' %>
524
+ # <% end %>
525
+ #
526
+ # # With block
527
+ # <% sorting_table_for @users do |table| %>
528
+ # <%= table.caption do %>
529
+ # 'hello'
530
+ # <% end %>
531
+ # <% end %>
532
+ #
533
+ # # Output:
534
+ # <table class='sorting_table_for'>
535
+ # <caption>hello</caption>
536
+ # </table>
537
+ #
538
+ # === Quick
539
+ #
540
+ # When called without a block or a value, caption is set with I18n translation.
541
+ #
542
+ # # Exemple of i18n_default_scope:
543
+ # SortingTableFor::TableBuilder.i18n_default_scope = [:controller, :action]
544
+ #
545
+ # # Ouput:
546
+ # I18n.t(:table_caption, :scope => [:current_controller, :current_action]) => en.current_controller.current_action.table_caption
547
+ #
548
+ # === Options
549
+ #
550
+ # * :position - To set the position of the caption: :top, :bottom, :left, :right (default: :top)
551
+ # * :html - Hash options: class, id, ...
552
+ #
553
+ # === Values
554
+ #
555
+ # All the values won't be interpreted.
556
+ #
557
+ def caption(*args, &block)
558
+ @caption[:option], @caption[:html] = get_column_and_html_options( args.extract_options! )
559
+ if block_given?
560
+ @caption[:value] = @@template.capture(&block)
561
+ else
562
+ @caption[:value] = (args.empty?) ? I18n.t(:table_caption) : args.first;
563
+ end
564
+ render_caption
565
+ end
566
+
397
567
  protected
398
568
 
399
569
  # Return the name of the model
@@ -403,6 +573,16 @@ module SortingTableFor
403
573
 
404
574
  private
405
575
 
576
+ def render_caption
577
+ if @caption
578
+ if @caption.has_key? :option and @caption[:option].has_key? :position
579
+ @caption[:html].merge!(:align => @caption[:option][:position])
580
+ end
581
+ return Tools::html_safe(content_tag(:caption, @caption[:value], @caption[:html]))
582
+ end
583
+ ''
584
+ end
585
+
406
586
  # Return the balise thead and its content
407
587
  def render_thead
408
588
  if @header_line
@@ -419,10 +599,22 @@ module SortingTableFor
419
599
  ''
420
600
  end
421
601
 
602
+ # Return the balise tfoot and its content
603
+ def render_tfoot
604
+ if @footer_line
605
+ return Tools::html_safe(content_tag(:tfoot, @footer_line.render_line))
606
+ end
607
+ ''
608
+ end
609
+
422
610
  # Set default global options
611
+ # init caption to a new hash
423
612
  # Set sort to true if the value isn't defined in options
613
+ # Set i18n to true if the value isn't defined in options
424
614
  def set_default_global_options
615
+ @caption = {}
425
616
  @@options[:sort] = true if !defined?(@@options[:sort]) or !@@options.has_key? :sort
617
+ @@options[:i18n] = true if !defined?(@@options[:i18n]) or !@@options.has_key? :i18n
426
618
  end
427
619
 
428
620
  # Calculate the total entries
@@ -430,7 +622,9 @@ module SortingTableFor
430
622
  def render_total_entries
431
623
  if self.show_total_entries
432
624
  total_entries = @collection.total_entries rescue @collection.size
433
- return Tools::html_safe(content_tag(:tr, content_tag(:td, I18n.t(:total_entries, :scope => :sorting_table_for, :value => total_entries), {:colspan => @lines.first.total_cells}), { :class => 'total-entries' }))
625
+ header_total_cells = @header_line ? @header_line.total_cells : 0
626
+ max_cells = (@lines.first.total_cells > header_total_cells) ? @lines.first.total_cells : header_total_cells
627
+ return Tools::html_safe(content_tag(:tr, content_tag(:td, I18n.t(:total_entries, :scope => :sorting_table_for, :value => total_entries), {:colspan => max_cells}), { :class => 'total-entries' }))
434
628
  end
435
629
  ''
436
630
  end
@@ -459,18 +653,20 @@ module SortingTableFor
459
653
  @cells << FormatCell.new(object, args, type, block)
460
654
  end
461
655
 
462
- # Return a tr line based on the type (:thead or :tbody)
656
+ # Return a tr line based on the type (:thead, :tbody or :tfoot)
463
657
  def render_line
464
658
  if @type == :thead
465
- header = content_tag(:tr, Tools::html_safe(@cells.collect { |cell| cell.render_cell_thead }.join), @html_options)
659
+ return content_tag(:tr, Tools::html_safe(@cells.collect { |cell| cell.render_cell_thead }.join), @html_options)
660
+ elsif @type == :tfoot
661
+ return content_tag(:tr, Tools::html_safe(@cells.collect { |cell| cell.render_cell_tfoot }.join), @html_options)
466
662
  else
467
663
  content_tag(:tr, Tools::html_safe(@cells.collect { |cell| cell.render_cell_tbody }.join), @html_options.merge(:class => "#{@html_options[:class]} #{@@template.cycle(:odd, :even)}".strip))
468
664
  end
469
665
  end
470
666
 
471
- # Return a string with the total of cells
667
+ # Return the number of cells in line
472
668
  def total_cells
473
- @cells.size.to_s
669
+ @cells.size
474
670
  end
475
671
 
476
672
  protected
@@ -492,14 +688,34 @@ module SortingTableFor
492
688
  def can_sort_column?(column)
493
689
  model_have_column?(column)
494
690
  end
495
-
691
+
692
+ # Options only for cells
693
+ def only_cell_option?(key)
694
+ [:colspan].include? key
695
+ end
696
+
697
+ # Format ask to send options to cell
698
+ def format_options_to_cell(ask, options = @column_options)
699
+ options.each do |key, value|
700
+ if only_cell_option?(key)
701
+ if ask.is_a? Hash
702
+ ask.merge!(key => value)
703
+ else
704
+ ask = [ask] unless ask.is_a? Array
705
+ (ask.last.is_a? Hash and ask.last.has_key? :html) ? ask.last[:html].merge!(key => value) : ask << { :html => { key => value }}
706
+ end
707
+ end
708
+ end
709
+ ask
710
+ end
711
+
496
712
  private
497
713
 
498
714
  # Call after headers or columns with no attributes (table.headers)
499
715
  # Create all the cells based on each column in the model's database table
500
716
  # Create cell's actions based on option default_actions or on actions given (:actions => [:edit])
501
717
  def create_cells
502
- @attributes.each { |ask| add_cell(@object, ask) }
718
+ @attributes.each { |ask| add_cell(@object, format_options_to_cell(ask)) }
503
719
  if @args.empty?
504
720
  TableBuilder.default_actions.each { |action| add_cell(@object, action, :action) }
505
721
  else
@@ -568,7 +784,7 @@ module SortingTableFor
568
784
  # Return a td with the formated value or action for headers
569
785
  def render_cell_thead
570
786
  if @ask
571
- cell_value = (@ask.is_a?(Symbol)) ? I18n.t(@ask, {}, true) : @ask
787
+ cell_value = (@ask.is_a?(Symbol)) ? I18n.t(@ask, {}, :header) : @ask
572
788
  else
573
789
  cell_value = @block
574
790
  end
@@ -580,6 +796,16 @@ module SortingTableFor
580
796
  end
581
797
  end
582
798
 
799
+ def render_cell_tfoot
800
+ if @ask
801
+ cell_value = (@ask.is_a?(Symbol)) ? I18n.t(@ask, {}, :footer) : @ask
802
+ else
803
+ cell_value = @block
804
+ end
805
+ cell_value = action_link_to(@options[:action], cell_value) if @type != :action and @options.has_key?(:action)
806
+ content_tag(:td, cell_value, @html_options)
807
+ end
808
+
583
809
  private
584
810
 
585
811
  # Return options and html options for a cell
@@ -594,6 +820,7 @@ module SortingTableFor
594
820
  def set_default_options
595
821
  @html_options = {} unless defined? @html_options
596
822
  @options = {} unless defined? @options
823
+ @html_options = format_options_to_cell(@html_options, @options)
597
824
  @options[:sort] = @@options[:sort] if !@options.has_key? :sort
598
825
  end
599
826
 
@@ -704,4 +931,4 @@ module SortingTableFor
704
931
  end
705
932
 
706
933
  end
707
- end
934
+ end
@@ -42,6 +42,50 @@ describe SortingTableFor, :type => :helper do
42
42
  end
43
43
  end
44
44
 
45
+ it "should no use i18n by default" do
46
+ helper.sorting_table_for(@users) do |table|
47
+ html = table.headers(:username)
48
+ html.should have_comp_tag("th:nth-child(1)", :text => 'Usernames')
49
+ end
50
+ end
51
+
52
+ it "should not use i18n" do
53
+ helper.sorting_table_for(@users, :i18n => false) do |table|
54
+ html = table.headers(:username)
55
+ html.should have_comp_tag("th:nth-child(1)", :text => 'username')
56
+ end
57
+ end
58
+
45
59
  end
60
+
61
+ describe " #All" do
46
62
 
63
+ it "should works with by default" do
64
+ helper.sorting_table_for(@users) do |table|
65
+ html = table.caption
66
+ html += table.headers
67
+ html += table.columns
68
+ html += table.footers :username
69
+ html.should have_comp_tag("caption", :count => 1)
70
+ html.should have_comp_tag("thead", :count => 1)
71
+ html.should have_comp_tag("tbody", :count => 1)
72
+ html.should have_comp_tag("tfoot", :count => 1)
73
+ end
74
+ end
75
+
76
+ it "should works with by default" do
77
+ helper.sorting_table_for(@users) do |table|
78
+ html = table.caption 'hello'
79
+ html += table.headers :username
80
+ html += table.columns :username
81
+ html += table.footers :username
82
+ html.should have_comp_tag("thead tr th", :count => 1)
83
+ html.should have_comp_tag("tbody tr td", :count => @users.count + 1)
84
+ html.should have_comp_tag("tbody tr[class=total-entries] td", :count => 1)
85
+ html.should have_comp_tag("tfoot tr td", :count => 1)
86
+ end
87
+ end
88
+
89
+ end
90
+
47
91
  end
@@ -0,0 +1,162 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require File.expand_path(File.dirname(__FILE__) + '/../fixtures/user')
5
+
6
+ include SortingTableForSpecHelper
7
+
8
+ describe SortingTableFor, :type => :helper do
9
+
10
+ before :each do
11
+ @users = User.all
12
+ helper.stub!(:url_for).and_return('fake_link')
13
+ helper.stub!(:params).and_return({ :controller => 'fakes', :action => 'index' })
14
+ helper.output_buffer = ''
15
+ end
16
+
17
+ describe ' #Caption' do
18
+
19
+ describe ' #Without block' do
20
+
21
+ it "should set caption tag" do
22
+ helper.sorting_table_for(@users) do |table|
23
+ html = table.caption
24
+ html.should have_comp_tag("caption", :count => 1)
25
+ end
26
+ end
27
+
28
+ it "should set caption tag with arguments" do
29
+ helper.sorting_table_for(@users) do |table|
30
+ html = table.caption 'hello'
31
+ html.should have_comp_tag("caption", :text => 'hello')
32
+ end
33
+ end
34
+
35
+ it "should set caption tag with arguments and option position left" do
36
+ helper.sorting_table_for(@users) do |table|
37
+ html = table.caption 'hello', :position => :left
38
+ html.should have_comp_tag("caption[align=left]")
39
+ end
40
+ end
41
+
42
+ it "should set caption tag with arguments and option position bottom" do
43
+ helper.sorting_table_for(@users) do |table|
44
+ html = table.caption 'hello', :position => :bottom
45
+ html.should have_comp_tag("caption[align=bottom]")
46
+ end
47
+ end
48
+
49
+ it "should works with html options" do
50
+ helper.sorting_table_for(@users) do |table|
51
+ html = table.caption 'hello', :html => {:class => 'my_class', :id => 'my_id', :title => 'my_title'}
52
+ html.should have_comp_tag("caption[class=my_class][id=my_id][title=my_title]")
53
+ end
54
+ end
55
+
56
+ it "should works with html options and position option" do
57
+ helper.sorting_table_for(@users) do |table|
58
+ html = table.caption 'hello', :position => :right, :html => {:class => 'my_class', :id => 'my_id', :title => 'my_title'}
59
+ html.should have_comp_tag("caption[class=my_class][id=my_id][title=my_title][align=right]")
60
+ end
61
+ end
62
+
63
+ end
64
+
65
+ describe ' #With block' do
66
+
67
+ it "should set caption tag" do
68
+ helper.sorting_table_for(@users) do |table|
69
+ html = table.caption {}
70
+ html.should have_comp_tag("caption", :count => 1)
71
+ end
72
+ end
73
+
74
+ it "should set caption tag with arguments" do
75
+ helper.sorting_table_for(@users) do |table|
76
+ html = table.caption do
77
+ 'hello'
78
+ end
79
+ html.should have_comp_tag("caption", :text => 'hello')
80
+ end
81
+ end
82
+
83
+ it "should set caption tag with arguments and option position left" do
84
+ helper.sorting_table_for(@users) do |table|
85
+ html = table.caption :position => :left do
86
+ 'hello'
87
+ end
88
+ html.should have_comp_tag("caption[align=left]")
89
+ end
90
+ end
91
+
92
+ it "should set caption tag with arguments and option position bottom" do
93
+ helper.sorting_table_for(@users) do |table|
94
+ html = table.caption :position => :bottom do
95
+ 'hello'
96
+ end
97
+ html.should have_comp_tag("caption[align=bottom]")
98
+ end
99
+ end
100
+
101
+ it "should works with html options" do
102
+ helper.sorting_table_for(@users) do |table|
103
+ html = table.caption :html => {:class => 'my_class', :id => 'my_id', :title => 'my_title'} do
104
+ 'hello'
105
+ end
106
+ html.should have_comp_tag("caption[class=my_class][id=my_id][title=my_title]")
107
+ end
108
+ end
109
+
110
+ it "should works with html options and position option" do
111
+ helper.sorting_table_for(@users) do |table|
112
+ html = table.caption :position => :right, :html => {:class => 'my_class', :id => 'my_id', :title => 'my_title'} do
113
+ 'hello'
114
+ end
115
+ html.should have_comp_tag("caption[class=my_class][id=my_id][title=my_title][align=right]")
116
+ end
117
+ end
118
+
119
+ end
120
+ end
121
+
122
+ describe " #Quick" do
123
+
124
+ it "should set caption tag with i18n translation" do
125
+ helper.sorting_table_for(@users) do |table|
126
+ html = table.caption
127
+ html.should have_comp_tag("caption", :count => 1)
128
+ html.should have_comp_tag("caption", :text => 'Quick Caption')
129
+ end
130
+ end
131
+
132
+ it "should set caption tag with arguments and option position left" do
133
+ helper.sorting_table_for(@users) do |table|
134
+ html = table.caption :position => :left
135
+ html.should have_comp_tag("caption[align=left]")
136
+ end
137
+ end
138
+
139
+ it "should set caption tag with arguments and option position bottom" do
140
+ helper.sorting_table_for(@users) do |table|
141
+ html = table.caption :position => :bottom
142
+ html.should have_comp_tag("caption[align=bottom]")
143
+ end
144
+ end
145
+
146
+ it "should works with html options" do
147
+ helper.sorting_table_for(@users) do |table|
148
+ html = table.caption :html => {:class => 'my_class', :id => 'my_id', :title => 'my_title'}
149
+ html.should have_comp_tag("caption[class=my_class][id=my_id][title=my_title]")
150
+ end
151
+ end
152
+
153
+ it "should works with html options and position option" do
154
+ helper.sorting_table_for(@users) do |table|
155
+ html = table.caption :position => :right, :html => {:class => 'my_class', :id => 'my_id', :title => 'my_title'}
156
+ html.should have_comp_tag("caption[class=my_class][id=my_id][title=my_title][align=right]")
157
+ end
158
+ end
159
+
160
+ end
161
+
162
+ end