tabulatr2 0.6.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/README.md +71 -27
  4. data/app/assets/javascripts/tabulatr/application.js +130 -133
  5. data/app/assets/stylesheets/tabulatr/application.css.scss +153 -0
  6. data/app/assets/stylesheets/tabulatr/bootstrap2_fixes.css.scss +24 -0
  7. data/app/views/tabulatr/_tabulatr_actual_table.html.slim +35 -0
  8. data/app/views/tabulatr/_tabulatr_batch_actions_menu.html.slim +34 -0
  9. data/app/views/tabulatr/_tabulatr_filter_dialog.html.slim +84 -0
  10. data/app/views/tabulatr/_tabulatr_filter_menu.html.slim +30 -0
  11. data/app/views/tabulatr/_tabulatr_fuzzy_search_field.html.slim +24 -0
  12. data/app/views/tabulatr/_tabulatr_info_string.html.slim +23 -0
  13. data/app/views/tabulatr/_tabulatr_paginator.html.slim +24 -0
  14. data/app/views/tabulatr/_tabulatr_static_table.html.slim +33 -0
  15. data/app/views/tabulatr/_tabulatr_table.html.slim +45 -0
  16. data/lib/tabulatr/data/column_name_builder.rb +86 -0
  17. data/lib/tabulatr/data/data.rb +135 -0
  18. data/lib/tabulatr/data/dsl.rb +61 -0
  19. data/lib/tabulatr/data/filtering.rb +101 -0
  20. data/lib/tabulatr/data/formatting.rb +65 -0
  21. data/lib/tabulatr/data/invoker.rb +37 -0
  22. data/lib/tabulatr/data/pagination.rb +48 -0
  23. data/lib/tabulatr/data/proxy.rb +41 -0
  24. data/lib/tabulatr/{tabulatr/batch_actions.rb → data/sorting.rb} +20 -23
  25. data/lib/tabulatr/engine.rb +24 -1
  26. data/lib/tabulatr/generators/railtie.rb +33 -0
  27. data/lib/tabulatr/generators/resource_override.rb +35 -0
  28. data/lib/{generators → tabulatr/generators}/tabulatr/install_generator.rb +21 -3
  29. data/lib/{generators → tabulatr/generators}/tabulatr/templates/tabulatr.yml +3 -1
  30. data/lib/tabulatr/generators/tabulatr/templates/tabulatr_data.rb +18 -0
  31. data/lib/tabulatr/json_builder.rb +94 -0
  32. data/lib/tabulatr/rails/action_controller.rb +36 -0
  33. data/lib/{initializers → tabulatr/rails}/action_view.rb +6 -3
  34. data/lib/{initializers → tabulatr/rails}/active_record.rb +11 -19
  35. data/lib/tabulatr/renderer/action.rb +32 -0
  36. data/lib/tabulatr/{tabulatr/formattr.rb → renderer/association.rb} +19 -30
  37. data/lib/tabulatr/renderer/checkbox.rb +36 -0
  38. data/lib/tabulatr/renderer/column.rb +113 -0
  39. data/lib/{initializers/mark_as_localizable.rb → tabulatr/renderer/columns.rb} +13 -15
  40. data/lib/tabulatr/renderer/columns_from_block.rb +56 -0
  41. data/lib/tabulatr/renderer/renderer.rb +96 -0
  42. data/lib/tabulatr/utility/utility.rb +46 -0
  43. data/lib/tabulatr/version.rb +25 -2
  44. data/lib/tabulatr.rb +45 -4
  45. data/lib/tabulatr2.rb +1 -0
  46. data/spec/dummy/app/assets/stylesheets/application.css.scss +2 -2
  47. data/spec/dummy/app/controllers/products_controller.rb +27 -3
  48. data/spec/dummy/app/models/vendor.rb +1 -0
  49. data/spec/dummy/app/tabulatr_data/product_tabulatr_data.rb +29 -0
  50. data/spec/dummy/app/views/products/implicit_columns.html.erb +1 -0
  51. data/spec/dummy/app/views/products/one_item_per_page.html.erb +1 -1
  52. data/spec/dummy/app/views/products/simple_index.html.erb +6 -4
  53. data/spec/dummy/app/views/products/stupid_array.html.erb +1 -1
  54. data/spec/dummy/app/views/products/with_batch_actions.html.erb +10 -0
  55. data/spec/dummy/config/locales/tabulatr.yml +22 -1
  56. data/spec/dummy/config/routes.rb +3 -1
  57. data/spec/features/tabulatrs_spec.rb +53 -11
  58. data/tabulatr.gemspec +1 -1
  59. metadata +50 -42
  60. data/app/assets/images/tabulatr/buttons_lite_background.png +0 -0
  61. data/app/assets/images/tabulatr/pager_arrow_left.gif +0 -0
  62. data/app/assets/images/tabulatr/pager_arrow_left_off.gif +0 -0
  63. data/app/assets/images/tabulatr/pager_arrow_right.gif +0 -0
  64. data/app/assets/images/tabulatr/pager_arrow_right_off.gif +0 -0
  65. data/app/assets/images/tabulatr/sort_arrow_down.gif +0 -0
  66. data/app/assets/images/tabulatr/sort_arrow_down_off.gif +0 -0
  67. data/app/assets/images/tabulatr/sort_arrow_up.gif +0 -0
  68. data/app/assets/images/tabulatr/sort_arrow_up_off.gif +0 -0
  69. data/app/assets/stylesheets/tabulatr/application.css +0 -40
  70. data/lib/initializers/action_controller.rb +0 -13
  71. data/lib/tabulatr/tabulatr/adapter/active_record.rb +0 -84
  72. data/lib/tabulatr/tabulatr/adapter.rb +0 -55
  73. data/lib/tabulatr/tabulatr/data_cell.rb +0 -132
  74. data/lib/tabulatr/tabulatr/dummy_record.rb +0 -40
  75. data/lib/tabulatr/tabulatr/empty_cell.rb +0 -44
  76. data/lib/tabulatr/tabulatr/filter_cell.rb +0 -145
  77. data/lib/tabulatr/tabulatr/filter_icon.rb +0 -6
  78. data/lib/tabulatr/tabulatr/finder/find_for_table.rb +0 -187
  79. data/lib/tabulatr/tabulatr/finder.rb +0 -64
  80. data/lib/tabulatr/tabulatr/header_cell.rb +0 -146
  81. data/lib/tabulatr/tabulatr/json_builder.rb +0 -57
  82. data/lib/tabulatr/tabulatr/paginator.rb +0 -76
  83. data/lib/tabulatr/tabulatr/row_builder.rb +0 -128
  84. data/lib/tabulatr/tabulatr/security.rb +0 -21
  85. data/lib/tabulatr/tabulatr/settings.rb +0 -158
  86. data/lib/tabulatr/tabulatr.rb +0 -343
  87. data/spec/lib/tabulatr/tabulatr/finder/find_for_table_spec.rb +0 -187
  88. /data/lib/{generators → tabulatr/generators}/tabulatr/templates/tabulatr.rb +0 -0
@@ -1,128 +0,0 @@
1
- #--
2
- # Copyright (c) 2010-2011 Peter Horn, Provideal GmbH
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining
5
- # a copy of this software and associated documentation files (the
6
- # "Software"), to deal in the Software without restriction, including
7
- # without limitation the rights to use, copy, modify, merge, publish,
8
- # distribute, sublicense, and/or sell copies of the Software, and to
9
- # permit persons to whom the Software is furnished to do so, subject to
10
- # the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be
13
- # included in all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
- #++
23
-
24
- # These are extensions for use as a row builder
25
- # In a seperate class call only for clearity
26
-
27
- class Tabulatr
28
-
29
- # called inside the build_table block, branches into data, header,
30
- # or filter building methods depending on the current mode
31
- def column(name, opts={}, &block)
32
- #puts "column: '#{name}'"
33
- case @row_mode
34
- when :data then data_column(name, opts, &block)
35
- when :header then
36
- @attributes << name.to_s
37
- header_column(name, opts, &block)
38
- when :filter then filter_column(name, opts, &block)
39
- when :empty then empty_column(name, opts, &block)
40
- else raise "Wrong row mode '#{@row_mode}'"
41
- end # case
42
- end
43
-
44
- # called inside the build_table block, branches into data, header,
45
- # or filter building methods depending on the current mode
46
- def association(relation, name, opts={}, &block)
47
- #puts "assoc: '#{relation}.#{name}'"
48
- case @row_mode
49
- when :data then data_association(relation, name, opts, &block)
50
- when :header then
51
- @attributes << "#{relation}:#{name}"
52
- header_association(relation, name, opts, &block)
53
- when :filter then filter_association(relation, name, opts, &block)
54
- when :empty then empty_column(name, opts, &block)
55
- else raise "Wrong row mode '#{@row_mode}'"
56
- end # case
57
- end
58
-
59
- # called inside the build_table block, branches into data, header,
60
- # or filter building methods depending on the current mode
61
- def checkbox(opts={}, &block)
62
- #puts "column: '#{name}'"
63
- case @row_mode
64
- when :data then data_checkbox(opts, &block)
65
- when :header then header_checkbox(opts, &block)
66
- when :filter then filter_checkbox(opts, &block)
67
- when :empty then nil
68
- else raise "Wrong row mode '#{@row_mode}'"
69
- end # case
70
- end
71
-
72
- def action(opts={}, &block)
73
- #puts "column: '#{name}'"
74
- case @row_mode
75
- when :data then data_action(opts, &block)
76
- when :header then header_action(opts, &block)
77
- when :filter then filter_action(opts, &block)
78
- when :empty then nil
79
- else raise "Wrong row mode '#{@row_mode}'"
80
- end # case
81
- end
82
-
83
- private
84
-
85
- # returns self, sets record to nil and row_mode as required for a
86
- # header row
87
- def header_row_builder
88
- @record = nil
89
- @row_mode = :header
90
- self
91
- end
92
-
93
- def filter_form_builder
94
- @record = nil
95
- @row_mode = :filter
96
- self
97
- end
98
-
99
- def empty_row_builder
100
- @record = nil
101
- @row_mode = :empty
102
- self
103
- end
104
-
105
- def data_row_builder(record)
106
- @record = record
107
- @row_mode = :data
108
- self
109
- end
110
-
111
-
112
- # some preprocessing of the options
113
- def normalize_column_options(name, opts)
114
- preset = column_preset_for(opts[:preset] || name)
115
- opts = Tabulatr::COLUMN_OPTIONS.merge(preset).merge(opts)
116
- {:width => 'width', :align => 'text-align', :valign => 'vertical-align'}.each do |key,css|
117
- if opts[key]
118
- [:th_html, :filter_html].each do |set|
119
- opts[set] ||= {}
120
- opts[set][:style] = (opts[set][:style] ? opts[set][:style] << "; " : "") << "#{css}: #{opts[key]}"
121
- end # each
122
- end # if
123
- end # each
124
- # more to come!
125
- opts
126
- end
127
- end
128
-
@@ -1,21 +0,0 @@
1
- require 'securerandom'
2
-
3
- class Tabulatr
4
- class Security
5
- def self.sign(arglist, salt=nil)
6
- salt ||= SecureRandom.base64
7
- str = "#{Tabulatr.secret_tokens.first}-#{salt}-#{arglist}-#{Rails.application.config.secret_token}-#{Tabulatr.secret_tokens.last}"
8
- hash = Digest::SHA1.hexdigest(str)
9
- "#{arglist}-#{salt}-#{hash[5..40]}"
10
- end
11
-
12
- def self.validate(str)
13
- arglist, salt, hash = str.split('-')
14
- str == sign(arglist, salt)
15
- end
16
-
17
- def self.validate!(str)
18
- validate(str) or raise "SECURITY!"
19
- end
20
- end
21
- end
@@ -1,158 +0,0 @@
1
- #--
2
- # Copyright (c) 2010-2011 Peter Horn, Provideal GmbH
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining
5
- # a copy of this software and associated documentation files (the
6
- # "Software"), to deal in the Software without restriction, including
7
- # without limitation the rights to use, copy, modify, merge, publish,
8
- # distribute, sublicense, and/or sell copies of the Software, and to
9
- # permit persons to whom the Software is furnished to do so, subject to
10
- # the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be
13
- # included in all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
- #++
23
-
24
- require 'whiny_hash'
25
-
26
- class Tabulatr
27
-
28
- # Hash keeping the defaults for the table options, may be overriden in the
29
- # table_for call
30
- TABLE_OPTIONS = WhinyHash.new({ # WhinyHash.new({
31
- :table_class => 'tabulatr_table', # class for the actual data table
32
- :control_div_class_before => 'table-controls', # class of the upper div containing the paging and batch action controls
33
- :control_div_class_after => 'table-controls', # class of the lower div containing the paging and batch action controls
34
- :paginator_div_class => 'pagination', # class of the div containing the paging controls
35
-
36
- # which controls to be rendered above and below the tabel and in which order
37
- :before_table_controls => [:filter, :paginator],
38
- :after_table_controls => [],
39
-
40
- :table_html => false, # a hash with html attributes for the table
41
- :row_html => false, # a hash with html attributes for the normal trs
42
- :header_html => false, # a hash with html attributes for the header trs
43
- :filter_html => false, # a hash with html attributes for the filter trs
44
- :filter => true, # false for no filter row at all
45
- :paginate => false, # true to show paginator
46
- :default_pagesize => 10, # default pagesize
47
- :sortable => true, # true to allow sorting (can be specified for every sortable column)
48
- :batch_actions => false, # :name => value hash of batch action stuff
49
- :footer_content => false, # if given, add a <%= content_for <footer_content> %> before the </table>
50
- :path => '#' # where to send the AJAX-requests to
51
- })
52
-
53
- # these settings are considered constant for the whole application, can not be overridden
54
- # on a per-table basis.
55
- # That's necessary to allow find_for_table to work properly
56
- TABLE_FORM_OPTIONS = WhinyHash.new({
57
- :filter_postfix => '_filter', # postfix for name of the filter in the params :hash => xxx_filter
58
- :sort_postfix => '_sort', # postfix for name of the filter in the params :hash => xxx_filter
59
- :associations_filter => '__association', # name of the associations in the filter hash
60
- :batch_postfix => '_batch', # postfix for name of the batch action select
61
- :checked_separator => ',' # symbol to separate the checked ids
62
- })
63
-
64
- # these settings are considered constant for the whole application, can not be overridden
65
- # on a per-table basis.
66
- # That's necessary to allow find_for_table to work properly
67
- PAGINATE_OPTIONS = ActiveSupport::HashWithIndifferentAccess.new({
68
- :page => 1,
69
- :pagesize => 10,
70
- :pagesizes => [10, 20, 50]
71
- })
72
-
73
- # Hash keeping the defaults for the column options
74
- COLUMN_OPTIONS = ActiveSupport::HashWithIndifferentAccess.new({
75
- :header => false, # a string to write into the header cell
76
- :width => false, # the width of the cell
77
- :align => false, # horizontal alignment
78
- :valign => false, # vertical alignment
79
- :wrap => true, # wraps
80
- :type => :string, # :integer, :date
81
- :th_html => false, # a hash with html attributes for the header cell
82
- :filter_html => false, # a hash with html attributes for the filter cell
83
- :filter => true, # false for no filter field,
84
- # container for options_for_select
85
- # String from options_from_collection_for_select or the like
86
- # :range for range spec
87
- # :checkbox for a 0/1 valued checkbox
88
- :checkbox_value => '1', # value if checkbox is checked
89
- :checkbox_label => '', # text behind the checkbox
90
- :filter_width => '97%', # width of the filter <input>
91
- :range_filter_symbol => '&ndash;', # put between the <inputs> of the range filter
92
- :sortable => true, # if set, sorting-stuff is added to the header cell
93
- :format_methods => [] # javascript methods to execute on this column
94
- })
95
-
96
- # defaults for the find_for_table
97
- FINDER_OPTIONS = WhinyHash.new({
98
- :default_order => false,
99
- :precondition => false,
100
- :store_data => false,
101
- :name_mapping => nil,
102
- :action => nil
103
- })
104
-
105
- # Stupid hack
106
- SQL_OPTIONS = WhinyHash.new({
107
- :like => nil
108
- })
109
-
110
- def self.finder_options(n=nil)
111
- FINDER_OPTIONS.merge!(n) if n
112
- FINDER_OPTIONS
113
- end
114
-
115
- def self.column_options(n=nil)
116
- COLUMN_OPTIONS.merge!(n) if n
117
- COLUMN_OPTIONS
118
- end
119
-
120
- def self.table_options(n=nil)
121
- TABLE_OPTIONS.merge!(n) if n
122
- TABLE_OPTIONS
123
- end
124
-
125
- def self.paginate_options(n=nil)
126
- PAGINATE_OPTIONS.merge!(n) if n
127
- PAGINATE_OPTIONS
128
- end
129
-
130
- def self.table_form_options(n=nil)
131
- TABLE_FORM_OPTIONS.merge!(n) if n
132
- TABLE_FORM_OPTIONS
133
- end
134
-
135
- def self.table_design_options(n=nil)
136
- raise("table_design_options stopped existing. Use table_options instead.")
137
- end
138
- def table_design_options(n=nil) self.class.table_design_options(n) end
139
-
140
- def self.sql_options(n=nil)
141
- SQL_OPTIONS.merge!(n) if n
142
- SQL_OPTIONS
143
- end
144
- def sql_options(n=nil) self.class.sql_options(n) end
145
-
146
- COLUMN_PRESETS = {}
147
- def self.column_presets(n=nil)
148
- COLUMN_PRESETS.merge!(n) if n
149
- COLUMN_PRESETS
150
- end
151
- def column_presets(n=nil) self.class.column_presets(n) end
152
- def column_preset_for(name)
153
- h = COLUMN_PRESETS[name.to_sym]
154
- return {} unless h
155
- return h if h.is_a? Hash
156
- COLUMN_PRESETS[h] || {}
157
- end
158
- end
@@ -1,343 +0,0 @@
1
- #--
2
- # Copyright (c) 2010-2011 Peter Horn, Provideal GmbH
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining
5
- # a copy of this software and associated documentation files (the
6
- # "Software"), to deal in the Software without restriction, including
7
- # without limitation the rights to use, copy, modify, merge, publish,
8
- # distribute, sublicense, and/or sell copies of the Software, and to
9
- # permit persons to whom the Software is furnished to do so, subject to
10
- # the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be
13
- # included in all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
- #++
23
-
24
- # Tabulatr is a class to allow easy creation of data tables as you
25
- # frequently find them on 'index' pages in rails. The 'table convention'
26
- # here is that we consider every table to consist of three parts:
27
- # * a header containing the names of the attribute of the column
28
- # * a filter which is an input element to allow for searching the
29
- # particular attribute
30
- # * the rows with the actual data.
31
- #
32
- # Additionally, we expect that people want to 'select' rows and perform
33
- # batch actions on these rows.
34
- #
35
- # Author:: Peter Horn, (mailto:peter.horn@provideal.net)
36
- # Copyright:: Copyright (c) 2010-2011 by Provideal GmbH (http://www.provideal.net)
37
- # License:: MIT Licence
38
- class Tabulatr
39
-
40
- include ActionView::Helpers::TagHelper
41
- include ActionView::Helpers::FormTagHelper
42
- include ActionView::Helpers::FormOptionsHelper
43
- include ActionView::Helpers::TranslationHelper
44
- include ActionView::Helpers::RecordTagHelper
45
- # include ActionView::Helpers::AssetTagHelper
46
- # include Rails::Application::Configurable
47
-
48
- # Constructor of Tabulatr
49
- #
50
- # Parameters:
51
- # <tt>klass</tt>:: the klass of the data for the table
52
- # <tt>view</tt>:: the current instance of ActionView
53
- # <tt>opts</tt>:: a hash of options specific for this table
54
- def initialize(klass_or_record, view=nil, toptions={})
55
- if klass_or_record.is_a?(Class) && klass_or_record < ActiveRecord::Base
56
- @klass = klass_or_record
57
- @records = nil
58
- elsif klass_or_record.respond_to?(:each)
59
- @records = klass_or_record
60
- @klass = @records.first.try(:class)
61
- toptions = toptions.merge! \
62
- :filter => false,
63
- :paginate => false,
64
- :sortable => false
65
- else
66
- raise "Give a model-class or an collection to `table_for'"
67
- end
68
- @view = view
69
- @table_options = TABLE_OPTIONS.merge(toptions)
70
- @table_form_options = TABLE_FORM_OPTIONS
71
- @val = []
72
- @record = nil
73
- @row_mode = false
74
- @classname = @klass.to_s.downcase.gsub("/","_")
75
- @attributes = []
76
- end
77
-
78
- cattr_accessor :bootstrap_paginator, instance_accessor: false do
79
- 'create_ul_paginator'
80
- end
81
-
82
- def self.config &block
83
- yield self
84
- end
85
-
86
- def self.secret_tokens=(secret_tokens)
87
- @@secret_tokens = secret_tokens
88
- end
89
-
90
- def self.secret_tokens
91
- @@secret_tokens ||= []
92
- end
93
-
94
- # the actual table definition method. It takes an Array of records, a hash of
95
- # options and a block with the actual <tt>column</tt> calls.
96
- #
97
- # The following options are evaluated here:
98
- # <tt>:table_html</tt>:: a hash with html-attributes added to the <table> created
99
- # <tt>:header_html</tt>:: a hash with html-attributes added to the <tr> created
100
- # for the header row
101
- # <tt>:filter_html</tt>:: a hash with html-attributes added to the <tr> created
102
- # for the filter row
103
- # <tt>:row_html</tt>:: a hash with html-attributes added to the <tr>s created
104
- # for the data rows
105
- # <tt>:filter</tt>:: if set to false, no filter row is output
106
- def build_table(&block)
107
- return nil if @records && @records.blank?
108
- @val = []
109
- # TODO: make_tag(:input, :type => 'submit', :style => 'display:inline; width:1px; height:1px', :value => '__submit')
110
- unless @records
111
- render_table_controls(:control_div_class_before, :before_table_controls)
112
- end
113
-
114
- render_element(:table, &block)
115
-
116
- unless @records
117
- render_table_controls(:control_div_class_after, :after_table_controls)
118
- make_tag(:div, class: "tabulatr_count",
119
- :'data-table' => "#{@klass.to_s.downcase}_table",
120
- :'data-format-string' => I18n.t('tabulatr.count')){}
121
-
122
- render_filter_dialog &block
123
- sec_hash = Tabulatr::Security.sign(@attributes.join(','))
124
- make_tag(:span, :id => "tabulatr_security_#{@klass.to_s.downcase}",
125
- :'data-salt' => sec_hash.split('-')[1],
126
- :'data-hash' => sec_hash.split('-')[2]){}
127
- end
128
- @val.join("").html_safe
129
- end
130
-
131
- def render_element(element, &block)
132
- case element
133
- when :filter then render_filter_icon
134
- when :paginator then render_paginator
135
- when :table then render_table &block
136
- else
137
- if element.is_a?(String)
138
- concat(element)
139
- else
140
- raise "unknown element '#{element}'"
141
- end
142
- end
143
- end
144
-
145
-
146
- def render_table(&block)
147
- to = @table_options[:table_html]
148
- to = (to || {}).merge(:class => "#{@table_options[:table_class]} table",
149
- :'data-path' => @table_options[:path], :id => "#{@klass.to_s.downcase}_table")
150
- make_tag(:table, to) do
151
- make_tag(:thead) do
152
- render_table_header(&block)
153
- end # </thead>
154
- if @records
155
- make_tag(:tbody) do
156
- render_table_rows(&block)
157
- end # </tbody>
158
- else
159
- make_tag(:tbody) do
160
- render_empty_start_row(&block)
161
- end # </tbody>
162
- end
163
- content_for(@table_options[:footer_content]) if @table_options[:footer_content]
164
- end # </table>
165
- end
166
-
167
- private
168
-
169
- def readable_name_for(name, relation=nil)
170
- if relation
171
- "#{@klass.human_attribute_name(relation).titlecase}
172
- #{@klass.reflect_on_association(relation).klass.
173
- human_attribute_name(name).titlecase}"
174
- else
175
- @klass.human_attribute_name(name).titlecase
176
- end
177
- end
178
-
179
- # either append to the internal string buffer or use
180
- # ActionView#concat to output if an instance is available.
181
- def concat(s, html_escape=false)
182
- #@view.concat(s) if (Rails.version.to_f < 3.0 && @view)
183
- #puts "\##{Rails.version.to_f} '#{s}'"
184
- if s.present? then @val << (html_escape ? h(s) : s) end
185
- end
186
-
187
- def h(s)
188
- ERB::Util.h(s)
189
- end
190
-
191
- def t(s)
192
- return '' unless s.present?
193
- begin
194
- if s.respond_to?(:should_localize?) and s.should_localize?
195
- translate(s)
196
- else
197
- case @should_translate
198
- when :translate then translate(s)
199
- when true then translate(s)
200
- when :localize then localize(s)
201
- else
202
- if !@should_translate
203
- s
204
- elsif @should_translate.respond_to?(:call)
205
- @should_translate.call(s)
206
- else
207
- raise "Wrong value '#{@should_translate}' for table option ':translate', should be false, true, :translate, :localize or a proc."
208
- end
209
- end
210
- end
211
- rescue
212
- raise "Translating '#{s}' failed!"
213
- end
214
- end
215
-
216
- # render the header row
217
- def render_table_header(&block)
218
- make_tag(:tr, @table_options[:header_html]) do
219
- yield(header_row_builder)
220
- end # </tr>"
221
- end
222
-
223
-
224
- def render_filter_options(&block)
225
- yield(filter_form_builder)
226
- make_tag(:input, :type => 'hidden', :name => 'sort_by')
227
- make_tag(:input, :type => 'hidden', :name => 'orientation')
228
- end
229
-
230
- def render_empty_start_row(&block)
231
- row_html = @table_options[:row_html] || {}
232
- row_html[:class] = 'empty_row'
233
- make_tag(:tr, row_html) do
234
- yield empty_row_builder
235
- end
236
- end
237
-
238
- def render_table_controls div_class, before_or_after
239
- make_tag(:div, :class => @table_options[div_class]) do
240
- @table_options[before_or_after].each do |element|
241
- render_element(element)
242
- end
243
- end if @table_options[before_or_after].present? # </div>
244
- end
245
-
246
- def render_filter_dialog &block
247
- make_tag(:div, class: 'modal fade', id: "tabulatr_filter_dialog_#{@klass.to_s.downcase}", style: "display:none ;") do
248
- make_tag(:div, class: 'modal-dialog') do
249
- make_tag(:div, class: 'modal-content') do
250
- make_tag(:div, class: 'modal-header') do
251
- make_tag(:button, class: :close, :'data-dismiss' => :modal,
252
- :'aria-hidden' => true) do
253
- concat "&times"
254
- end
255
- make_tag(:h3, class: 'modal-title') do
256
- concat I18n.t('tabulatr.filter')
257
- end
258
- end
259
- make_tag(:form, :'data-table' => "#{@klass.to_s.downcase}_table",
260
- class: 'form-horizontal tabulatr_filter_form', :'data-remote' => true) do
261
- make_tag(:div, class: 'modal-body') do
262
- render_filter_options &block
263
- end
264
- make_tag(:div, class: 'modal-footer') do
265
- make_tag(:input, :type => 'submit',
266
- :class => 'submit-table btn btn-primary',
267
- :value => I18n.t('tabulatr.apply_filters'))
268
- end
269
- end
270
- end # modal-content
271
- end # modal-dialog
272
- end # modal fade
273
- end
274
-
275
- # render the table rows, only used if records are passed
276
- def render_table_rows(&block)
277
- # row_classes = @table_options[:row_classes] || []
278
- # row_html = @table_options[:row_html] || {}
279
- # row_class = row_html[:class] || ""
280
- @records.each_with_index do |record, i|
281
- #concat("<!-- Row #{i} -->")
282
- # if row_classes.present?
283
- # rc = row_class.present? ? row_class + " " : ''
284
- # rc += row_classes[i % row_classes.length]
285
- # else
286
- # rc = nil
287
- # end
288
- rc = nil
289
- make_tag(:tr, :class => rc, :id => dom_id(record)) do
290
- yield(data_row_builder(record))
291
- end # </tr>
292
- end
293
- end
294
-
295
- def render_table_row(&block)
296
- row_html = @table_options[:row_html] || {}
297
- row_html[:class] = 'empty_row'
298
- make_tag(:tr, row_html) do
299
- yield empty_row_builder
300
- end
301
- end
302
-
303
-
304
- # stringly produce a tag w/ some options
305
- def make_tag(name, hash={}, &block)
306
- attrs = hash ? tag_options(hash) : ''
307
- if block_given?
308
- if name
309
- concat("<#{name}#{attrs}>")
310
- yield
311
- concat("</#{name}>")
312
- else
313
- yield
314
- end
315
- else
316
- concat("<#{name}#{attrs} />")
317
- end
318
- nil
319
- end
320
-
321
- def make_image_button(options)
322
- inactive = options.delete(:inactive)
323
- if(options['data-sort'] == 'desc')
324
- icon_class = 'icon-arrow-down'
325
- else
326
- icon_class = 'icon-arrow-up'
327
- end
328
- if !inactive
329
- make_tag(:i,
330
- options.merge(
331
- :class => "tabulatr-sort #{icon_class}"
332
- )
333
- )
334
- else
335
- make_tag(:i, :class => "tabulatr-sort #{icon_class}")
336
- end
337
- end
338
-
339
- end
340
-
341
- Dir[File.join(File.dirname(__FILE__), "tabulatr", "*.rb")].each do |file|
342
- require file
343
- end