tabulatr2 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +4 -0
  5. data/Changelog.textile +124 -0
  6. data/Gemfile +21 -0
  7. data/LICENSE +23 -0
  8. data/README.md +242 -0
  9. data/Rakefile +11 -0
  10. data/app/assets/images/tabulatr/buttons_lite_background.png +0 -0
  11. data/app/assets/images/tabulatr/pager_arrow_left.gif +0 -0
  12. data/app/assets/images/tabulatr/pager_arrow_left_off.gif +0 -0
  13. data/app/assets/images/tabulatr/pager_arrow_right.gif +0 -0
  14. data/app/assets/images/tabulatr/pager_arrow_right_off.gif +0 -0
  15. data/app/assets/images/tabulatr/sort_arrow_down.gif +0 -0
  16. data/app/assets/images/tabulatr/sort_arrow_down_off.gif +0 -0
  17. data/app/assets/images/tabulatr/sort_arrow_up.gif +0 -0
  18. data/app/assets/images/tabulatr/sort_arrow_up_off.gif +0 -0
  19. data/app/assets/javascripts/tabulatr/application.js +452 -0
  20. data/app/assets/javascripts/tabulatr/jquery.inview.min.js +3 -0
  21. data/app/assets/javascripts/tabulatr.js +1 -0
  22. data/app/assets/stylesheets/tabulatr/application.css +40 -0
  23. data/app/assets/stylesheets/tabulatr.css +4 -0
  24. data/init.rb +1 -0
  25. data/lib/generators/tabulatr/install_generator.rb +44 -0
  26. data/lib/generators/tabulatr/templates/tabulatr.rb +5 -0
  27. data/lib/generators/tabulatr/templates/tabulatr.yml +14 -0
  28. data/lib/initializers/action_controller.rb +13 -0
  29. data/lib/initializers/action_view.rb +31 -0
  30. data/lib/initializers/active_record.rb +48 -0
  31. data/lib/initializers/mark_as_localizable.rb +43 -0
  32. data/lib/tabulatr/engine.rb +3 -0
  33. data/lib/tabulatr/tabulatr/adapter/active_record.rb +84 -0
  34. data/lib/tabulatr/tabulatr/adapter.rb +55 -0
  35. data/lib/tabulatr/tabulatr/batch_actions.rb +51 -0
  36. data/lib/tabulatr/tabulatr/data_cell.rb +132 -0
  37. data/lib/tabulatr/tabulatr/dummy_record.rb +40 -0
  38. data/lib/tabulatr/tabulatr/empty_cell.rb +44 -0
  39. data/lib/tabulatr/tabulatr/filter_cell.rb +145 -0
  40. data/lib/tabulatr/tabulatr/filter_icon.rb +6 -0
  41. data/lib/tabulatr/tabulatr/finder/find_for_table.rb +187 -0
  42. data/lib/tabulatr/tabulatr/finder.rb +64 -0
  43. data/lib/tabulatr/tabulatr/formattr.rb +55 -0
  44. data/lib/tabulatr/tabulatr/header_cell.rb +146 -0
  45. data/lib/tabulatr/tabulatr/json_builder.rb +57 -0
  46. data/lib/tabulatr/tabulatr/paginator.rb +76 -0
  47. data/lib/tabulatr/tabulatr/row_builder.rb +128 -0
  48. data/lib/tabulatr/tabulatr/security.rb +21 -0
  49. data/lib/tabulatr/tabulatr/settings.rb +158 -0
  50. data/lib/tabulatr/tabulatr.rb +343 -0
  51. data/lib/tabulatr/version.rb +3 -0
  52. data/lib/tabulatr.rb +34 -0
  53. data/spec/dummy/.gitignore +18 -0
  54. data/spec/dummy/README.rdoc +28 -0
  55. data/spec/dummy/Rakefile +6 -0
  56. data/spec/dummy/app/assets/images/.keep +0 -0
  57. data/spec/dummy/app/assets/javascripts/application.js +16 -0
  58. data/spec/dummy/app/assets/stylesheets/application.css.scss +15 -0
  59. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  60. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  61. data/spec/dummy/app/controllers/products_controller.rb +24 -0
  62. data/spec/dummy/app/controllers/tags_controller.rb +5 -0
  63. data/spec/dummy/app/controllers/vendors_controller.rb +5 -0
  64. data/spec/dummy/app/helpers/application_helper.rb +9 -0
  65. data/spec/dummy/app/mailers/.keep +0 -0
  66. data/spec/dummy/app/models/.keep +0 -0
  67. data/spec/dummy/app/models/concerns/.keep +0 -0
  68. data/spec/dummy/app/models/product.rb +5 -0
  69. data/spec/dummy/app/models/tag.rb +3 -0
  70. data/spec/dummy/app/models/vendor.rb +2 -0
  71. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  72. data/spec/dummy/app/views/products/count_tags.html.erb +9 -0
  73. data/spec/dummy/app/views/products/one_item_per_page.html.erb +9 -0
  74. data/spec/dummy/app/views/products/simple_index.html.erb +9 -0
  75. data/spec/dummy/app/views/products/stupid_array.html.erb +20 -0
  76. data/spec/dummy/bin/bundle +3 -0
  77. data/spec/dummy/bin/rails +4 -0
  78. data/spec/dummy/bin/rake +4 -0
  79. data/spec/dummy/config/application.rb +23 -0
  80. data/spec/dummy/config/boot.rb +5 -0
  81. data/spec/dummy/config/database.yml +25 -0
  82. data/spec/dummy/config/environment.rb +5 -0
  83. data/spec/dummy/config/environments/development.rb +29 -0
  84. data/spec/dummy/config/environments/production.rb +80 -0
  85. data/spec/dummy/config/environments/test.rb +36 -0
  86. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  87. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  88. data/spec/dummy/config/initializers/inflections.rb +16 -0
  89. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  90. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  91. data/spec/dummy/config/initializers/session_store.rb +3 -0
  92. data/spec/dummy/config/initializers/tabulatr.rb +5 -0
  93. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  94. data/spec/dummy/config/locales/en.yml +23 -0
  95. data/spec/dummy/config/locales/tabulatr.yml +14 -0
  96. data/spec/dummy/config/routes.rb +13 -0
  97. data/spec/dummy/config.ru +4 -0
  98. data/spec/dummy/db/migrate/20130730132101_create_vendors.rb +12 -0
  99. data/spec/dummy/db/migrate/20130730132321_create_products.rb +12 -0
  100. data/spec/dummy/db/migrate/20130730132348_create_tags.rb +14 -0
  101. data/spec/dummy/db/schema.rb +47 -0
  102. data/spec/dummy/lib/assets/.keep +0 -0
  103. data/spec/dummy/log/.keep +0 -0
  104. data/spec/dummy/public/404.html +58 -0
  105. data/spec/dummy/public/422.html +58 -0
  106. data/spec/dummy/public/500.html +57 -0
  107. data/spec/dummy/public/favicon.ico +0 -0
  108. data/spec/features/tabulatrs_spec.rb +227 -0
  109. data/spec/lib/tabulatr/tabulatr/finder/find_for_table_spec.rb +187 -0
  110. data/spec/spec_helper.rb +45 -0
  111. data/tabulatr.gemspec +29 -0
  112. metadata +258 -0
@@ -0,0 +1,43 @@
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
+ # This is probably a REALLY bad idea...
25
+ module MarkAsLocalizable
26
+ def l
27
+ @should_localize = true
28
+ self
29
+ end
30
+
31
+ def should_localize?
32
+ @should_localize == true
33
+ end
34
+ end
35
+
36
+ class String
37
+ include MarkAsLocalizable
38
+ end
39
+
40
+ class Symbol
41
+ include MarkAsLocalizable
42
+ end
43
+
@@ -0,0 +1,3 @@
1
+ class Tabulatr::Engine < Rails::Engine
2
+
3
+ end
@@ -0,0 +1,84 @@
1
+ class Tabulatr::Adapter::ActiveRecordAdapter < Tabulatr::Adapter
2
+
3
+ def initialize(klaz)
4
+ set_like_statement unless Tabulatr::SQL_OPTIONS[:like]
5
+
6
+ super klaz
7
+ end
8
+
9
+ def primary_key
10
+ @relation.primary_key.to_sym
11
+ end
12
+
13
+ def key_type
14
+ @relation.columns_hash[primary_key.to_s].type
15
+ end
16
+
17
+ def selected_ids(opts)
18
+ preconditions_scope(opts).select(:id)
19
+ end
20
+
21
+ def table_name
22
+ @relation.table_name
23
+ end
24
+
25
+ def table_name_for_association(assoc)
26
+ @base.reflect_on_association(assoc).table_name
27
+ end
28
+
29
+ def order_for_query(sortparam, default)
30
+ context = order(sortparam, default)
31
+ "#{context[:by]} #{context[:direction]}" if context
32
+ end
33
+
34
+ def order_for_query_new(sort_by, orientation)
35
+ "#{sort_by} #{orientation}"
36
+ end
37
+
38
+ def includes(inc)
39
+ @relation.includes(inc)
40
+ end
41
+
42
+ def outer_joins(*args)
43
+ @relation.outer_joins(*args)
44
+ end
45
+
46
+ def select(s)
47
+ @relation.select(s)
48
+ end
49
+
50
+ def includes!(inc)
51
+ @relation = includes(includes)
52
+ end
53
+
54
+ def add_conditions_from(n,v)
55
+ like ||= Tabulatr.sql_options[:like]
56
+ if v.is_a?(String)
57
+ @relation = @relation.where("#{n} = ?", v) unless v.blank?
58
+ elsif v.is_a?(Hash)
59
+ if v[:like].present?
60
+ @relation = @relation.where("#{n} #{like} ?", "%#{v[:like]}%")
61
+ else
62
+ @relation = @relation.where("#{n} >= ?", "#{v[:from]}") if v[:from].present?
63
+ @relation = @relation.where("#{n} <= ?", "#{v[:to]}") if v[:to].present?
64
+ end
65
+ else
66
+ raise "Wrong filter type: #{v.class}"
67
+ end
68
+ end
69
+
70
+ private
71
+ def set_like_statement
72
+ case ActiveRecord::Base.connection.class.to_s
73
+ when "ActiveRecord::ConnectionAdapters::MysqlAdapter" then Tabulatr.sql_options(:like => 'LIKE')
74
+ when "ActiveRecord::ConnectionAdapters::Mysql2Adapter" then Tabulatr.sql_options(:like => 'LIKE')
75
+ when "ActiveRecord::ConnectionAdapters::PostgreSQLAdapter" then Tabulatr.sql_options(:like => 'ILIKE')
76
+ when "ActiveRecord::ConnectionAdapters::SQLiteAdapter" then Tabulatr.sql_options(:like => 'LIKE')
77
+ when "ActiveRecord::ConnectionAdapters::SQLite3Adapter" then Tabulatr.sql_options(:like => 'LIKE')
78
+ else
79
+ warn("Tabulatr Warning: Don't know which LIKE operator to use for the ConnectionAdapter '#{ActiveRecord::Base.connection.class}'.\n" +
80
+ "Please specify by `Tabulatr.sql_options(:like => '<likeoperator>')`")
81
+ Tabulatr.sql_options(:like => 'LIKE')
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,55 @@
1
+ class Tabulatr::Adapter
2
+ def initialize(klaz)
3
+ @base = klaz
4
+ @relation = klaz
5
+ end
6
+
7
+ delegate :all, :dup, :count, :limit, :to => :@relation
8
+
9
+ def to_sql
10
+ @relation.to_sql if @relation.respond_to? :to_sql
11
+ end
12
+
13
+ def class_to_param
14
+ @relation.to_s.downcase.gsub("/","_")
15
+ end
16
+
17
+ def preconditions_scope(opts)
18
+ opts[:precondition].present? ? @base.where(opts[:precondition]) : @base
19
+ end
20
+
21
+ def order(sortparam, default)
22
+ order_by, order_direction = sort_params(sortparam, default)
23
+ order_by ? { :by => order_by, :direction => order_direction } : nil
24
+ end
25
+
26
+ def sort_params(sortparam, default)
27
+ if sortparam
28
+ if sortparam[:_resort]
29
+ order_by = sortparam[:_resort].first.first
30
+ order_direction = sortparam[:_resort].first.last.first.first
31
+ else
32
+ order_by = sortparam.first.first
33
+ order_direction = sortparam.first.last.first.first
34
+ end
35
+ raise "SECURITY violation, sort field name is '#{n}'" unless /^[\w]+$/.match order_direction
36
+ raise "SECURITY violation, sort field name is '#{n}'" unless /^[\d\w]+$/.match order_by
37
+ else
38
+ if default
39
+ l = default.split(" ")
40
+ raise(":default_order parameter should be of the form 'id asc' or 'name desc'.") if l.length == 0 or l.length > 2
41
+
42
+ order_by = l[0]
43
+ order_direction = l[1] || 'asc'
44
+ else
45
+ order_by = order_direction = nil
46
+ end
47
+ end
48
+
49
+ return order_by, order_direction
50
+ end
51
+ end
52
+
53
+ Dir[File.join(File.dirname(__FILE__), "adapter", "*.rb")].each do |file|
54
+ require file
55
+ end
@@ -0,0 +1,51 @@
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
+ class Tabulatr
25
+
26
+ # render the select tag or the buttons for batch actions
27
+ def render_batch_actions
28
+ iname = "#{@classname}#{TABLE_FORM_OPTIONS[:batch_postfix]}"
29
+ make_tag(:span, :class => 'dropdown') do
30
+ make_tag(:button,
31
+ :class => 'disabled btn btn-small tabulatr-wrench',
32
+ :'data-toggle' => "dropdown") do
33
+ concat("<i class='icon-wrench'></i>#{I18n.t('tabulatr.batch_actions')}
34
+ <span class='caret'></span>")
35
+ end
36
+ make_tag(:ul, class: 'dropdown-menu', role: 'menu',
37
+ :'aria-labelledby' => 'dLabel') do
38
+ @table_options[:batch_actions].each do |n,v|
39
+ make_tag(:li) do
40
+ make_tag(:a, :value => v,
41
+ :name => "#{iname}[#{n}]",
42
+ :class => "btn batch-action-inputs") do
43
+ concat(v)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ end
@@ -0,0 +1,132 @@
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
+ class Tabulatr
25
+
26
+ # the method used to actually define the data cells of the columns,
27
+ # taking the name of the attribute and a hash of options.
28
+ #
29
+ # The following options are evaluated here:
30
+ # <tt>:td_html</tt>:: a hash with html-attributes added to the <ts>s created
31
+ # <tt>:method</tt>:: the actual method invoked on the record to retrieve the
32
+ # value for the column, or false if name is to be used.
33
+ # <tt>:fromat</tt>:: either a String by which the value is <tt>sprinf</tt>ed,
34
+ # a proc/lambda to which the value is passed or false if
35
+ # no specific formatting is desired.
36
+ def data_column(name, opts={}, &block)
37
+ raise "Not in data mode!" if @row_mode != :data
38
+ opts = normalize_column_options(name, opts)
39
+ make_tag(:td, opts[:td_html]) do
40
+ href = if opts[:link].class == Symbol || opts[:link].class == String
41
+ @view.send(opts[:link], @record)
42
+ elsif opts[:link].respond_to?(:call)
43
+ opts[:link].call(@record)
44
+ else
45
+ nil
46
+ end
47
+ make_tag((href ? :a : nil), :href => href) do
48
+ if block_given?
49
+ concat(@view.instance_exec(@record, &block))
50
+ else
51
+ val = @record.send(opts[:method] || name)
52
+ format = opts[:format]
53
+ concat(
54
+ if format.is_a?(Proc) then @view.instance_exec(val, &format)
55
+ elsif format.is_a?(String) then h(format % val)
56
+ elsif format.is_a?(Symbol) then @view.send(format, val)
57
+ else h(val.to_s)
58
+ end)
59
+ end # block_given?
60
+ end # </a>
61
+ end # </td>
62
+ end
63
+
64
+ # the method used to actually define the data cells of the columns,
65
+ # taking the name of the attribute and a hash of options.
66
+ #
67
+ # The following options are evaluated here:
68
+ # <tt>:td_html</tt>:: a hash with html-attributes added to the <ts>s created
69
+ # <tt>:method</tt>:: the actual method invoked on the record to retrieve the
70
+ # value for the column, or false if name is to be used.
71
+ # <tt>:format</tt>:: either a String by which the value is <tt>sprinf</tt>ed,
72
+ # a proc/lambda to which the value is passed or false if
73
+ # no specific formatting is desired.
74
+ def data_association(relation, name, opts={}, &block)
75
+ raise "Not in data mode!" if @row_mode != :data
76
+ opts = normalize_column_options(name, opts)
77
+ if block_given?
78
+ return @view.instance_exec(@record, &block)
79
+ end
80
+ assoc = @record.class.reflect_on_association(relation)
81
+ make_tag(:td, opts[:td_html]) do
82
+ format = opts[:format]
83
+ ass = @record.send(relation.to_sym)
84
+ if opts[:sort_by]
85
+ # TODO: SORTING specified by opts[:sort_by]
86
+ end
87
+ concat(if (ass.is_a?(Array) || ass.respond_to?(:to_ary)) && (opts[:map] != false)
88
+ ass.map do |r|
89
+ val = h(r.send(opts[:method] || name))
90
+ if format.is_a?(Proc) then format.call(val)
91
+ elsif format.is_a?(String) then h(format % val)
92
+ elsif format.is_a?(Symbol) then @view.send(format, val)
93
+ else h(val.to_s)
94
+ end
95
+ end.join(opts[:join_symbol] || ', ')
96
+ else
97
+ return '' unless ass
98
+ #puts ass.to_s
99
+ val = h(ass.send(opts[:method] || name))
100
+ val = if format.is_a?(Proc) then @view.instance_exec(val, &format)
101
+ elsif format.is_a?(String) then h(format % val)
102
+ elsif format.is_a?(Symbol) then @view.send(format, val)
103
+ else h(val.to_s)
104
+ end
105
+ end)
106
+ end # </td>
107
+ end
108
+
109
+ def data_checkbox(opts={}, &block)
110
+ raise "Whatever that's for!" if block_given?
111
+ iname = "#{@classname}#{@table_form_options[:checked_postfix]}[current_page][]"
112
+ make_tag(:td, opts[:td_html]) do
113
+ checked = @checked[:selected].member?(@record.send(@id)) ? :checked : nil
114
+ make_tag(:input, :type => 'checkbox', :name => iname,
115
+ :id => "#{@classname}#{@table_form_options[:checked_postfix]}_#{@record.send(@id).to_s}",
116
+ :value => @record.send(@id), :checked => checked)
117
+ end
118
+ end
119
+
120
+ def data_action(opts={}, &block)
121
+ raise "Not in data mode!" if @row_mode != :data
122
+ opts = normalize_column_options(:action_column, opts)
123
+ make_tag(:td, opts[:td_html]) do
124
+ if block_given?
125
+ concat(yield(@record))
126
+ else
127
+ raise "Always give a block ino action columns"
128
+ end # block_given?
129
+ end # </td>
130
+ end
131
+
132
+ end
@@ -0,0 +1,40 @@
1
+ class Tabulatr::DummyRecord
2
+
3
+ def self.for(klaz)
4
+ c = Class.new(self)
5
+ c.instance_variable_set("@model_name", klaz.model_name)
6
+ c.new
7
+ end
8
+
9
+ def to_s
10
+ @methods ||= []
11
+ if @methods.any?
12
+ m = @methods.join(':')
13
+ @method_names ||= []
14
+ @method_names << m
15
+ @methods.clear
16
+ "{{#{m}}}"
17
+ else
18
+ "{{id}}"
19
+ end
20
+ end
21
+
22
+ def method_missing(sym, *args)
23
+ @methods ||= []
24
+ @methods << sym.to_s
25
+ self
26
+ end
27
+
28
+ def to_key
29
+ ["{{id}}"]
30
+ end
31
+
32
+ def requested_methods
33
+ Array(@method_names).try(:uniq)
34
+ end
35
+
36
+ def self.model_name
37
+ @model_name
38
+ end
39
+
40
+ end
@@ -0,0 +1,44 @@
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
+ class Tabulatr
25
+
26
+ # the method used to actually define the filters of the columns,
27
+ # taking the name of the attribute and a hash of options.
28
+ #
29
+ # The following options are evaluated here:
30
+ # <tt>:filter_html</tt>:: a hash with html-attributes added to the <ts>s created
31
+ # <tt>:filter</tt>:: may take different values:
32
+ # <tt>false</tt>:: no filter is output for this column
33
+ # a container:: the keys of the hash are used to define a <tt>select</tt>
34
+ # where the values are the <tt>value</tt> of the <tt>options</tt>.
35
+ # an Array:: the elements of that array are used to define a
36
+ # <tt>select</tt>
37
+ # a String:: a <tt>select</tt> is created with that String as options
38
+ # you can use ActionView#collection_select and the like
39
+ def empty_column(name, opts={}, &block)
40
+ raise "Not in empty mode!" if @row_mode != :empty
41
+ opts = normalize_column_options(name, opts)
42
+ make_tag(:td, opts[:filter_html])
43
+ end
44
+ end
@@ -0,0 +1,145 @@
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
+ class Tabulatr
25
+
26
+ # the method used to actually define the filters of the columns,
27
+ # taking the name of the attribute and a hash of options.
28
+ #
29
+ # The following options are evaluated here:
30
+ # <tt>:filter_html</tt>:: a hash with html-attributes added to the <ts>s created
31
+ # <tt>:filter</tt>:: may take different values:
32
+ # <tt>false</tt>:: no filter is output for this column
33
+ # a container:: the keys of the hash are used to define a <tt>select</tt>
34
+ # where the values are the <tt>value</tt> of the <tt>options</tt>.
35
+ # an Array:: the elements of that array are used to define a
36
+ # <tt>select</tt>
37
+ # a String:: a <tt>select</tt> is created with that String as options
38
+ # you can use ActionView#collection_select and the like
39
+ def filter_column(name, opts={}, &block)
40
+ raise "Not in filter mode!" if @row_mode != :filter
41
+ opts = normalize_column_options(name, opts)
42
+ of = opts[:filter]
43
+ iname = "#{@classname}#{@table_form_options[:filter_postfix]}[#{name}]"
44
+ filter_name = "tabulatr_form_#{name}"
45
+ build_filter(of, filter_name, name, iname, opts) if filterable?(of, name.to_s)
46
+ end
47
+
48
+ # the method used to actually define the filters of the columns,
49
+ # taking the name of the attribute and a hash of options.
50
+ #
51
+ # The following options are evaluated here:
52
+ # <tt>:filter_html</tt>:: a hash with html-attributes added to the <ts>s created
53
+ # <tt>:filter</tt>:: may take different values:
54
+ # <tt>false</tt>:: no filter is output for this column
55
+ # a Hash:: the keys of the hash are used to define a <tt>select</tt>
56
+ # where the values are the <tt>value</tt> of the <tt>options</tt>.
57
+ # an Array:: the elements of that array are used to define a
58
+ # <tt>select</tt>
59
+ # a subclass of <tt>ActiveRecord::Base</tt>:: a <tt>select</tt> is created
60
+ # with all instances
61
+ def filter_association(relation, name, opts={}, &block)
62
+ raise "Not in filter mode!" if @row_mode != :filter
63
+ opts = normalize_column_options(name, opts)
64
+
65
+ of = opts[:filter]
66
+ iname = "#{@classname}#{@table_form_options[:filter_postfix]}[#{@table_form_options[:associations_filter]}][#{relation}.#{name}]"
67
+ filter_name = "tabulatr_form_#{relation}_#{name}"
68
+ build_filter(of, filter_name, name, iname, opts, relation) if filterable?(of, name.to_s, relation)
69
+ end
70
+
71
+ def filter_checkbox(opts={}, &block)
72
+ raise "Whatever that's for!" if block_given?
73
+ make_tag(:td, opts[:filter_html]) {}
74
+ end
75
+
76
+ def filter_action(opts={}, &block)
77
+ raise "Not in filter mode!" if @row_mode != :filter
78
+ opts = normalize_column_options(:action_column, opts)
79
+ make_tag(:td, opts[:filter_html]) do
80
+ concat(t(opts[:filter])) unless [true, false, nil].member?(opts[:filter])
81
+ end # </td>
82
+ end
83
+
84
+ private
85
+
86
+ def filter_tag(of, name, iname, attr_name, opts)
87
+ if !of
88
+ ""
89
+ elsif of.is_a?(Hash) or of.is_a?(Array) or of.is_a?(String)
90
+ make_tag(:select, :style => "width:#{opts[:filter_width]}",
91
+ :id => name, name: iname) do
92
+ if of.class.is_a?(String)
93
+ concat(of)
94
+ else
95
+ concat("<option></option>")
96
+ t = options_for_select(of)
97
+ concat(t.sub("value=\"\"", "value=\"\" selected=\"selected\""))
98
+ end
99
+ end # </select>
100
+ elsif opts[:filter] == :range
101
+ filter_text_tag(opts[:filter_width], "#{name}_from", iname, attr_name, 'from')
102
+ concat(t(opts[:range_filter_symbol]))
103
+ filter_text_tag(opts[:filter_width], "#{name}_to", iname, attr_name, 'to')
104
+ elsif opts[:filter] == :checkbox
105
+ checkbox_value = opts[:checkbox_value]
106
+ checkbox_label = opts[:checkbox_label]
107
+ concat(check_box_tag(iname, checkbox_value, false, {}))
108
+ concat(checkbox_label)
109
+ elsif opts[:filter] == :exact
110
+ filter_text_tag(opts[:filter_width], name, iname, attr_name, 'normal')
111
+ else
112
+ filter_text_tag(opts[:filter_width], name, iname, attr_name, 'like')
113
+ end # if
114
+ end
115
+
116
+ def filter_text_tag width, name, iname, attr_name, type=nil
117
+ name_attribute = iname
118
+ name_attribute += "[#{type}]" if type && type != 'normal'
119
+ make_tag(:input, :type => :text, :id => name,
120
+ :style => "width:#{width}",
121
+ :value => '',
122
+ :'data-type' => type,
123
+ :'data-tabulatr-attribute' => attr_name,
124
+ :class => 'tabulatr_filter',
125
+ :name => name_attribute)
126
+ end
127
+
128
+ def build_filter(of, filter_name, name, iname, opts, relation=nil)
129
+ if of
130
+ make_tag(:div, class: 'control-group') do
131
+ make_tag(:label, class: 'control-label', for: filter_name) do
132
+ concat(t(opts[:header] || readable_name_for(name, relation)), :escape_html)
133
+ end
134
+ make_tag(:div, class: 'controls') do
135
+ filter_tag(of, filter_name, iname, name, opts)
136
+ end
137
+ end
138
+ end
139
+ end
140
+
141
+ def filterable?(of, name, relation=nil)
142
+ of && (!(relation && name.to_sym == :count))
143
+ end
144
+
145
+ end
@@ -0,0 +1,6 @@
1
+ class Tabulatr
2
+ def render_filter_icon
3
+ make_tag(:a, class: 'btn btn-info', href: "#tabulatr_filter_dialog_#{@klass.to_s.downcase}",
4
+ :'data-toggle' => 'modal'){ concat('<i class="icon-filter"></i>Filter') }
5
+ end
6
+ end