datatablesnet 1.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.
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ .bundle
2
+ db/*.sqlite3
3
+ log/*.log
4
+ tmp/
5
+ .DS_Store
6
+ *.log
7
+ nbproject
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source :rubygems
2
+
3
+ gem 'rake', '< 0.9'
4
+
5
+ gemspec
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "datatablesnet/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "datatablesnet"
7
+ s.version = Datatablesnet::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.summary = "Datatables.net component for rails"
10
+ s.email = "mfields106@gmail.com"
11
+ s.homepage = "https://github.com/IslandPort/datatablesnet"
12
+ s.description = "Component abstraction for datatables.net"
13
+ s.authors = ['Matt Fields']
14
+
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ end
@@ -0,0 +1,43 @@
1
+ -options = config[:options]
2
+
3
+ :javascript
4
+ $(document).ready(function(){
5
+ $('##{table_id}').dataTable(#{config[:table_options].to_json});
6
+ if(#{options[:toolbar].present? or options[:toolbar_external]}){
7
+ $('div.toolbar').html($('##{table_id}_toolbar').html());
8
+ }
9
+ if(#{options[:width].present?}){
10
+ $('##{table_id}_wrapper').css('width', '#{options[:width].to_s}');
11
+ }
12
+ });
13
+
14
+ -if options[:toolbar].present?
15
+ %div{:id => table_id + "_toolbar", :style => "display:none"}
16
+ - options[:toolbar].each do |toolbar_item|
17
+ .toolbarItem
18
+ -if toolbar_item[:url]
19
+ =link_to toolbar_item[:text], toolbar_item[:url] , :class=>"btn"
20
+ -else
21
+ =toolbar_item[:text]
22
+
23
+ %table.display{:id => table_id, :style => "#{options[:width].present? ? 'width:' + options[:width].to_s : 'width:100%!important'}"}
24
+ %thead
25
+ - columns.each do |column|
26
+ %th= column[:label]
27
+ - if options[:show_actions].to_b
28
+ %th Actions
29
+ - if options[:server_side].to_b
30
+ %th
31
+ %tbody
32
+ - unless options[:data_url].present?
33
+ - rows.each do |row|
34
+ %tr
35
+ - columns.each do |column|
36
+ %td
37
+ =datatable_get_column_data(row,column)
38
+ - if options[:show_actions] == 'true'
39
+ %td
40
+ .tableAction= link_to 'Show', row
41
+ .tableAction= link_to 'Edit', send("edit_#{row.class.to_s.demodulize.underscore}_path",row)
42
+ .tableAction= link_to 'Destroy', row, :confirm => 'Are you sure?', :method => :delete
43
+
@@ -0,0 +1,310 @@
1
+ require 'datatablesnet/types'
2
+
3
+ module Datatable
4
+
5
+ class UrlHelper
6
+ include Rails.application.routes.url_helpers
7
+ #default_url_options[:routing_type] = :path
8
+
9
+ def url_for(options = {})
10
+ options ||= {}
11
+ url = case options
12
+ when String
13
+ super
14
+ when Hash
15
+ super
16
+ when :back
17
+ super
18
+ else
19
+ polymorphic_path(options)
20
+ end
21
+
22
+ url
23
+ end
24
+ end
25
+
26
+ #Options
27
+ # :sort_by
28
+ # :additional_data
29
+ # :search
30
+ # :search_label
31
+ # :processing
32
+ # :persist_state
33
+ # :per_page
34
+ # :no_records_message
35
+ # :auto_width
36
+ # :row_callback
37
+ # :show_actions
38
+ #Column Options
39
+ # :name
40
+ # :label
41
+ # :render
42
+ # :format
43
+
44
+ module_function
45
+
46
+ def template_path
47
+ path = File.expand_path('..', __FILE__)
48
+ $:.unshift(path)
49
+ path
50
+ end
51
+
52
+ def datatable_tag id, columns = [], rows = nil, options = {}
53
+ options_map = {:sort_by => "aaSorting",
54
+ :search => "bFilter",
55
+ :search_label => "sSearch",
56
+ :processing => "bProcessing",
57
+ :persist_state => "bSaveState",
58
+ :per_page => "iDisplayLength",
59
+ :no_records_message => "sZeroRecords",
60
+ :auto_width => "bAutoWidth",
61
+ :dom => "sDom",
62
+ :data_url => "sAjaxSource",
63
+ :server_side => "bServerSide",
64
+ :auto_scroll => "bScrollInfinite",
65
+ :pagination_type => "sPaginationType",
66
+ :paginate => "bPaginate",
67
+ :save_state => "bStateSave"
68
+ }
69
+
70
+
71
+ options =
72
+ {
73
+ :show_actions => true,
74
+ :per_page => 25,
75
+ :toolbar_external => false
76
+ }.merge(options)
77
+
78
+ index = 0
79
+ columns.each do |column|
80
+ column[:label] = field_to_label(column[:field]) unless column[:label].present?
81
+ if options[:data_url].present?
82
+ options[:data_url] << "?" if column == columns.first
83
+ options[:data_url] << "column_field_#{index.to_s}=#{column[:field]}"
84
+ if column[:view_link].present?
85
+ options[:data_url] << "&column_view_link_#{index.to_s}=#{column[:view_link]}"
86
+ end
87
+ options[:data_url] << "&" unless column == columns.last
88
+ end
89
+ index += 1
90
+ end
91
+
92
+ if options[:toolbar].present? or options[:toolbar_external]
93
+ options[:dom]='<"toolbar">lfrtip'
94
+ end
95
+
96
+ table_options = {}
97
+ options_map.each do |k,v|
98
+ if options[k].present?
99
+ table_options[v] = options[k]
100
+ end
101
+ end
102
+
103
+ table_options["aoColumns"] = datatable_get_column_defs(options,columns)
104
+
105
+ config = {:options => options, :columns =>columns, :table_options => table_options}
106
+ config.to_json
107
+ render :file => template_path + "/_table", :locals => { :table_id => id, :columns => columns, :rows => rows, :config => config}
108
+ end
109
+
110
+ def datatable_get_column_defs options, columns
111
+ column_defs = []
112
+ column_options_map = {:width => "sWidth",
113
+ :sortable => "bSortable",
114
+ :searchable => "bSearchable",
115
+ :class => "sClass"}
116
+
117
+
118
+ column_index =0
119
+ columns.each do |column|
120
+ column_options = {}
121
+ column_options_map.each do |k,v|
122
+ if column[k].present?
123
+ column_options[v] = column[k]
124
+ end
125
+ end
126
+ column_options["fnRender"] = NoEscape.new(options[:render]) if column[:render].present?
127
+ column_options["fnRender"] = NoEscape.new("function (obj) {return #{column[:format]}(obj.aData[#{column_index}])}") if column[:format].present?
128
+ if column[:view_link].present? and options[:server_side]
129
+ column_options["fnRender"] = NoEscape.new("function (obj) {return '<a href = ' + obj.aData[#{columns.length}]['urls']['#{column[:field]}'] + '>' + obj.aData[#{column_index}] + '</a>'}")
130
+ end
131
+
132
+ unless column_options.empty?
133
+ column_defs << column_options
134
+ else
135
+ column_defs << nil
136
+ end
137
+ column_index+=1
138
+ end
139
+
140
+ if options[:show_actions]
141
+ column_defs << nil
142
+ end
143
+
144
+ if options[:server_side]
145
+ column_defs << {"bVisible" => false}
146
+ end
147
+
148
+ return column_defs
149
+ end
150
+
151
+ def get_field_data obj, field
152
+ attrs = field.split('.')
153
+ attrs.each do |attr|
154
+ if obj
155
+ obj = obj.send attr
156
+ else
157
+ return ""
158
+ end
159
+ end
160
+ return obj
161
+ end
162
+
163
+ def datatable_get_column_data row, column
164
+ obj = get_field_data(row, column[:field])
165
+
166
+ if column[:view_link].present?
167
+ if column[:view_link] == "."
168
+ return link_to(obj, row)
169
+ else
170
+ return link_to(obj, row.send(column[:view_link]))
171
+ end
172
+ else
173
+ return obj
174
+ end
175
+ end
176
+
177
+ def field_to_label(field)
178
+ label = field.gsub(/[_.]/, " ")
179
+ label.to_s.gsub(/\b\w/){$&.upcase}
180
+ end
181
+
182
+ def parse_params params
183
+ grid_options = {}
184
+ columns = []
185
+ order_by = {}
186
+ filter_by = {}
187
+ (0..params[:iColumns].to_i-2).each do |index|
188
+ column = {}
189
+ column[:field] = params["column_field_#{index}"]
190
+ column[:searchable] = params["bSearchable_#{index}"].to_b
191
+ column[:sortable] = params["bSortable_#{index}"].to_b
192
+ column[:index] = index
193
+ if params["column_view_link_#{index}"].present?
194
+ column[:view_link] = params["column_view_link_#{index}"]
195
+ end
196
+ columns << column
197
+ if params["iSortCol_#{index}"].present?
198
+ order_column_index = params["iSortCol_#{index}"]
199
+ order_column = params["column_field_#{order_column_index}"]
200
+ order_column_order = params["sSortDir_#{index}"] || "DESC"
201
+ order_by[order_column] = order_column_order
202
+ end
203
+ if params["sSearch_#{index}"].present?
204
+ filter_by[column[:field]] = params["sSearch_#{index}"]
205
+ end
206
+ end
207
+
208
+ grid_options[:columns] = columns
209
+ grid_options[:order_by] = order_by
210
+ grid_options[:filter_by] = filter_by
211
+ grid_options[:page] = (params[:iDisplayStart].to_i/params[:iDisplayLength].to_i rescue 0)+1
212
+ grid_options[:per_page] = params[:iDisplayLength]
213
+ if params["sSearch"].present?
214
+ grid_options[:search] = params["sSearch"]
215
+ end
216
+
217
+ grid_options
218
+ end
219
+
220
+
221
+ def find(klass, params={}, options = {})
222
+ field_filter_where = {}
223
+ all_filter_where = {}
224
+
225
+ grid_options = parse_params params
226
+
227
+
228
+ options[:page] = grid_options[:page]
229
+ options[:per_page] = grid_options[:per_page]
230
+
231
+ # Build order by
232
+ grid_options[:order_by].each do |column, order|
233
+ if options[:order].present?
234
+ options[:order] << ", "
235
+ else
236
+ options[:order] = ""
237
+ end
238
+ options[:order] << "#{column} #{order}"
239
+ end
240
+
241
+ # Build filter by
242
+ grid_options[:filter_by].each do |column, value|
243
+ field_filter_where[column] = value
244
+ end
245
+
246
+ # Search all searchable columns
247
+ if grid_options[:search].present?
248
+ grid_options[:columns].each do |column|
249
+ if column[:searchable].to_b
250
+ all_filter_where[column[:field]] = grid_options[:search]
251
+ end
252
+ end
253
+ end
254
+
255
+ if !field_filter_where.empty? or !all_filter_where.empty?
256
+ options[:conditions] = [field_filter_where.sql_like, all_filter_where.sql_or.sql_like].sql_and.sql_where
257
+ end
258
+
259
+ puts options[:conditions]
260
+
261
+ rows = klass.paginate options
262
+
263
+ objects = []
264
+ rows.each do |row|
265
+ object = []
266
+ grid_options[:columns].each do |column|
267
+ object << get_field_data(row, column[:field])
268
+ end
269
+
270
+ meta = build_row_meta row, grid_options
271
+ object << meta
272
+ objects << object
273
+ end
274
+
275
+ total_records = klass.count
276
+ if options[:conditions].present?
277
+ klass.count(:conditions => options[:conditions])
278
+ else
279
+ total_display_records = total_records
280
+ end
281
+ json_data = {:sEcho => params[:sEcho],
282
+ :iTotalRecords => total_records,
283
+ :iTotalDisplayRecords => total_display_records,
284
+ :aaData => objects
285
+ }
286
+ return json_data
287
+ end
288
+
289
+
290
+ def build_row_meta row, grid_options
291
+ url_helper = UrlHelper.new
292
+ meta={}
293
+ meta[:urls] = {}
294
+ grid_options[:columns].each do |column|
295
+ if column[:view_link].present?
296
+ view_link = column[:view_link]
297
+ if view_link == "."
298
+ url = url_helper.url_for(row)
299
+ else
300
+ url = url_helper.url_for(row.send(view_link))
301
+ end
302
+ meta[:urls][column[:field]] = url
303
+ end
304
+ end
305
+ return meta
306
+ end
307
+
308
+ end
309
+
310
+
@@ -0,0 +1,85 @@
1
+
2
+
3
+ module HashSql
4
+
5
+ def self.included(klass)
6
+ klass.send :include, InstanceMethods
7
+ end
8
+
9
+ module InstanceMethods
10
+
11
+ attr_accessor :sql_operator
12
+ attr_accessor :sql_comparator
13
+
14
+ def sql_where
15
+ if self.instance_of?(Hash)
16
+ build_where
17
+ else
18
+ combine_wheres
19
+ end
20
+ end
21
+
22
+ def sql_and
23
+ self.sql_operator = "and"
24
+ return self
25
+ end
26
+
27
+ def sql_or
28
+ self.sql_operator = "or"
29
+ return self
30
+ end
31
+
32
+ def sql_like
33
+ self.sql_comparator = "like"
34
+ return self
35
+ end
36
+
37
+
38
+ private
39
+
40
+ def build_where
41
+ values = []
42
+ where_string = ""
43
+ self.each do |name, value|
44
+ if where_string != ""
45
+ where_string << " #{sql_operator ? sql_operator : 'and'} "
46
+ end
47
+
48
+ if self.sql_comparator = "like"
49
+ where_string << "#{name} LIKE ?"
50
+ values << '%' + value + '%'
51
+ else
52
+ where_string << "#{name} = ?"
53
+ values << value
54
+ end
55
+ end
56
+ where = [where_string] + values
57
+ return where
58
+ end
59
+
60
+ def combine_wheres
61
+ values = []
62
+ where_string = ""
63
+ self.each do |where_hash|
64
+ unless where_hash.empty?
65
+ where = where_hash.sql_where
66
+ if where_string != ""
67
+ where_string << " and "
68
+ end
69
+
70
+ where_string << "(#{where[0]})"
71
+
72
+ values += where[1..-1]
73
+ end
74
+ end
75
+
76
+ [where_string] + values
77
+ end
78
+ end
79
+ end
80
+
81
+ [Array, Hash].each do |klass|
82
+ klass.class_eval do
83
+ include HashSql
84
+ end
85
+ end
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+
3
+ module Datatablesnet
4
+ # @private
5
+ class Railtie < Rails::Railtie
6
+ initializer 'datatablesnet.initialize' do
7
+ ActiveSupport.on_load(:action_view) do
8
+ include Datatable
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,34 @@
1
+
2
+ class NoEscape
3
+ def as_json(options = nil) self end #:nodoc:
4
+ def encode_json(encoder) to_s end #:nodoc:
5
+
6
+ def initialize text
7
+ @text = text
8
+ end
9
+
10
+ def to_s
11
+ @text
12
+ end
13
+ end
14
+
15
+
16
+ module ToBoolean
17
+ def self.included(klass)
18
+ klass.send :include, InstanceMethods
19
+ end
20
+
21
+
22
+ module InstanceMethods
23
+ def to_b
24
+ string = self
25
+ return true if string == true || string =~ (/(true|t|yes|y|1)$/i)
26
+ return false if string == false || string.nil? || string =~ (/(false|f|no|n|0)$/i)
27
+ raise ArgumentError.new("invalid value for Boolean: \"#{string}\"")
28
+ end
29
+ end
30
+ end
31
+
32
+ Object.class_eval do
33
+ include ToBoolean
34
+ end
@@ -0,0 +1,3 @@
1
+ module Datatablesnet
2
+ VERSION = "1.0"
3
+ end
@@ -0,0 +1,10 @@
1
+ require 'datatablesnet/railtie' if defined?(::Rails)
2
+
3
+ module Datatablesnet
4
+ extend ActiveSupport::Autoload
5
+
6
+ autoload :Datatable
7
+ autoload :HashSql
8
+ autoload :NoEscape
9
+
10
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: datatablesnet
3
+ version: !ruby/object:Gem::Version
4
+ hash: 15
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ version: "1.0"
10
+ platform: ruby
11
+ authors:
12
+ - Matt Fields
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-07-30 00:00:00 Z
18
+ dependencies: []
19
+
20
+ description: Component abstraction for datatables.net
21
+ email: mfields106@gmail.com
22
+ executables: []
23
+
24
+ extensions: []
25
+
26
+ extra_rdoc_files: []
27
+
28
+ files:
29
+ - .gitignore
30
+ - Gemfile
31
+ - datatablesnet.gemspec
32
+ - lib/datatablesnet.rb
33
+ - lib/datatablesnet/_table.html.haml
34
+ - lib/datatablesnet/datatable.rb
35
+ - lib/datatablesnet/hash_sql.rb
36
+ - lib/datatablesnet/railtie.rb
37
+ - lib/datatablesnet/types.rb
38
+ - lib/datatablesnet/version.rb
39
+ homepage: https://github.com/IslandPort/datatablesnet
40
+ licenses: []
41
+
42
+ post_install_message:
43
+ rdoc_options: []
44
+
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ hash: 3
53
+ segments:
54
+ - 0
55
+ version: "0"
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ requirements: []
66
+
67
+ rubyforge_project:
68
+ rubygems_version: 1.7.2
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: Datatables.net component for rails
72
+ test_files: []
73
+