sorting_table_for 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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