datatablesnet 1.0

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