apotomo-datatable 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2013 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,113 @@
1
+ # Apotomo-Datatable
2
+ Rails Gem for generating jQuery Datatables with extremely minimal configuration
3
+
4
+ Built on the Apotomo widget gem
5
+
6
+ Pacaged with jQuery Datatables version 1.9.4
7
+
8
+ Datatables may be rendered within a view (like a partial) or as javascipt for AJAX implementation
9
+
10
+ ## Usage
11
+
12
+ ### Gemfile
13
+ gem 'apotomo-datatable'
14
+ gem 'haml'
15
+
16
+ ### Simple use case for a given model/controller
17
+
18
+ #### items_controller.rb
19
+ has_widgets do |root|
20
+ root << datatable=widget('apotomo/datatable',:datatable)
21
+ end
22
+
23
+ #### Embedding with an HTML view
24
+ ##### view/items/index.html.haml
25
+ =render_widget :datatable,:display
26
+
27
+ #### AJAX rendering
28
+ ##### view/items/index.html.haml
29
+ %div#parentDiv
30
+ =link_to "Create table", items_path+'.js?template[parent]=parentDiv', :remote=>true, :title=>"Create table"
31
+ ##### view/items/index.js.haml
32
+ =render_widget :datatable,:display
33
+
34
+ ### Passing options from various points
35
+
36
+ #### items_controller.rb
37
+ root << datatable=widget('apotomo/datatable',:datatable,
38
+ :widget=>{}, #widget options (the model is derived from the controller name by default, but may be passed here as :model=>Model)
39
+ :template=>{:footer=>true}, #template options
40
+ :plugin=>{:sScrollY=>150} #plugin options, see: http://datatables.net/usage/options
41
+ )
42
+
43
+ def index
44
+ respond_to do |format|
45
+ format.html
46
+ format.js {render :script=>true}
47
+ end
48
+ end
49
+
50
+ # By defaultathe widget will query the model on its own
51
+ # If apotomo_datatable_datasource is defined, Apotomo::DatatableWidget.datasource will use this to populate
52
+ # The hash provided, which is expected to be standard search results from an ActiveRecord query, is encapsulated in a hash expected by jquery datatables
53
+
54
+ def apotomo_datatable_datasource(filter)
55
+ Item.find(:all,filter)
56
+ end
57
+
58
+ #### view/items/index.html.haml
59
+ %h1="Apotomo Datatable Example"
60
+
61
+ %h2="Rendered as HTML"
62
+ =render_widget :items_datatable,:display,:plugin=>{:sScrollY=>100,:bScrollCollapse=>true},:template=>{:id=>'html_datatable'}
63
+
64
+ %h2="Rendered via AJAX"
65
+
66
+ %div#parentDiv1
67
+ =link_to "Create table from options set in the URL", items_path+'.js?template[parent]=parentDiv1&plugin[sScrollY]=100', :remote=>true
68
+
69
+ :javascript
70
+ var plugin_options={sScrollY: 50, iDisplayStart: 20};
71
+
72
+
73
+ %div#parentDiv2
74
+ =link_to "Create table from options defined in javascript variable", items_path+'.js?template[plugin_options]=plugin_options&template[parent]=parentDiv2&template[id]=datatable_2', :remote=>true
75
+
76
+ #### index.js.haml
77
+ =render_widget :items_datatable,:display,:widget=>{},:template=>{:footer=>true},:plugin=>{:sScrollY=>150}
78
+
79
+
80
+ ## Options
81
+
82
+ The @options hash includes sub-hashes for the widget, templates and client-side plugin
83
+ @options={:widget=>{...}, :template=>{...}, :plugin=>{...}}
84
+
85
+ Default options are generated and merged with controller-provided options in Apotomo::DatatableWidget.set_options
86
+
87
+ Default options may be overridden from the controller, view, by URL parameters and by a client-side javascript hash, as seen in the example above, with the client-side javascript hash taking the highest precedence
88
+ client_side_options -> url_param_options -> view_options -> controller_options -> default_options
89
+
90
+ URL parameters may only define template and plugin options. Defining widget options from the URL would present a security hole
91
+
92
+ The client-side hash may only define plugin options. Since this hash is not passed to the server template and widget options would never be seen
93
+
94
+ $.extend(@options[:widget].to_json,client_side_options) constitutes the arguments passed to the datatable initialization function.
95
+ See http://datatables.net/usage/options for options. As such, any option specified in the jquery datatables API may be set in this sub hash
96
+ Note: Server-side processing is not yet supported
97
+
98
+ By default, :id, :created_at and :updated_at columns are excluded from display.
99
+ Pass the [:template][:excluded_columns] option to exclude more
100
+ Pass the [:template][:included_columns] option to include excluded columns
101
+
102
+ ## Current Status
103
+
104
+ The above examples will load a functional datatable, with sorting and global filtering working
105
+ Basic tests for loading and sorting are implemented. Sorting tests fail when plugin[bServerSide]=true since that is not implemented yet
106
+ Template for column-based filters started, but not yet complete or functional
107
+
108
+ ## TODO
109
+
110
+ Implement server-side sorting and filtering
111
+ Expand feature tests
112
+ Implementing the other base features
113
+ Move on to implementing plugins
data/Rakefile ADDED
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'ApotomoDatatable'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
24
+ load 'rails/tasks/engine.rake'
25
+
26
+ Bundler::GemHelper.install_tasks
27
+
28
+ Dir[File.join(File.dirname(__FILE__), 'tasks/**/*.rake')].each {|f| load f }
29
+ require 'rspec/core'
30
+ require 'rspec/core/rake_task'
31
+ desc "Run all specs in spec directory (excluding plugin specs)"
32
+ RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
33
+ task :default => :spec
34
+
35
+ =begin
36
+
37
+ Rake::TestTask.new(:test) do |t|
38
+ t.libs << 'test'
39
+ t.test_files = FileList['test/**/*_test.rb']
40
+ t.verbose = true
41
+ end
42
+
43
+
44
+
45
+ Bundler::GemHelper.install_tasks
46
+ =end
@@ -0,0 +1,11 @@
1
+ require 'apotomo/datatable_widget'
2
+ require 'apotomo-datatable/railtie'
3
+ module ApotomoDatatable
4
+ class Engine < Rails::Engine
5
+ # loads views from 'cell/views' and NOT from 'app/cells'
6
+ # config.paths.add 'app/cell_views', :with => 'cell/views'
7
+
8
+ # appends 'lib/my_cells_view_path' to this Railtie view path contribution
9
+ # config.paths['app/cell_views'] << 'lib/apotomo/datatable'
10
+ end
11
+ end
@@ -0,0 +1,24 @@
1
+ require "rails/railtie"
2
+
3
+ module ApotomoDatatable
4
+ class Railtie < ::Rails::Railtie
5
+ # rake_tasks do
6
+ # load "apotomo/apotomo.rake"
7
+ # end
8
+
9
+ # As we are a Railtie only, the routes won't be loaded automatically. Beside that, we want our
10
+ # route to be the very first (otherwise #resources might supersede it).
11
+ # initializer 'apotomo.prepend_routes', :after => :add_routing_paths do |app|
12
+ # app.routes_reloader.paths.unshift(File.dirname(__FILE__) + "/../../config/routes.rb")
13
+ # end
14
+
15
+ # Include a lazy loader via has_widgets.
16
+ # initializer 'apotomo.add_has_widgets' do |app|
17
+ # ActionController::Base.extend Apotomo::Rails::ControllerMethodsLoader
18
+ # end
19
+
20
+ initializer 'apotomo-datatable.setup_view_paths', :after => 'apotomo.setup_view_paths' do |app|
21
+ Apotomo::DatatableWidget.setup_view_paths!
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,3 @@
1
+ module ApotomoDatatable
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,25 @@
1
+ /default apotomo-datatable view
2
+ -if @merged_options[:widget][:model]
3
+ %table{:id=>@merged_options[:template][:id],:class=>"display dataTable"}<>
4
+ -if @merged_options[:template][:header]
5
+ %thead<>
6
+ =render({:state=>:head_foot},@merged_options,:header);
7
+ %tbody<>
8
+ -if !@merged_options[:plugin][:sAjaxSource] and !@merged_options[:plugin][:aaData]
9
+ -@merged_options[:widget][:datasource].call().each do |item|
10
+ %tr<>
11
+ -item.attributes.each do |key,value|
12
+ -if !@merged_options[:template][:excluded_columns].include?(key.to_sym) or @merged_options[:template][:included_columns].include?(key.to_sym)
13
+ %td<>=value
14
+ -if @merged_options[:template][:footer]
15
+ %tfoot<>
16
+ =render({:state=>:head_foot},@merged_options,:footer);
17
+ -if !@merged_options[:params][:format]
18
+ :javascript
19
+ postInit(function() {
20
+ #{@init_datatable_js}
21
+ });
22
+ -"#{@merged_options[:plugin].inspect}"
23
+ -else
24
+ ="No Model Defined"
25
+
@@ -0,0 +1,2 @@
1
+ $("##{@merged_options[:template][:parent]}").append("#{@html}");
2
+ != "#{@init_datatable_js}"
@@ -0,0 +1,22 @@
1
+ %tr<>
2
+ -merged_options[:widget][:model].columns_hash.each_pair do |name,column|
3
+ -if !@merged_options[:template][:excluded_columns].include?(name.to_sym) or @merged_options[:template][:included_columns].include?(name.to_sym)
4
+ %th<>
5
+ - if merged_options[:template][section].respond_to?(:each_pair)
6
+ - inputs=merged_options[:template][section][name]
7
+ - unless inputs
8
+ - inputs=merged_options[:template][section][:default]
9
+ - else
10
+ - inputs=merged_options[:template][section]
11
+ - unless inputs.respond_to?(:each)
12
+ - inputs=[inputs]
13
+ - inputs.each do |opt|
14
+ - case opt
15
+ - when :label
16
+ =name
17
+ - when :input
18
+ %br<>
19
+ %input{:onclick=>"event.stopPropagation();"}<>
20
+ - when :select
21
+ %br<>
22
+ %select{:onclick=>"event.stopPropagation();"}<>
@@ -0,0 +1,303 @@
1
+ require 'apotomo'
2
+ #include Rails.application.routes.url_helpers
3
+
4
+ =begin
5
+ Apotomo-Datatables
6
+
7
+ Basic usage with default options:
8
+
9
+ Gemfile
10
+ gem 'apotomo-datatables'
11
+
12
+ items_controller.rb
13
+ root << items_datatable=widget('apotomo/datatable',:items_datatable)
14
+
15
+ index.html.haml
16
+ #render as HTML like a partial
17
+ =render_widget :items_datatable,:display
18
+
19
+ #render via AJAX
20
+ %div#parentDiv
21
+ =link_to "Create table from options set in the URL", items_path+'.js?template[parent]=parentDiv, :remote=>true
22
+
23
+ index.js.haml #used to render via AJAX
24
+ =render_widget :items_datatable,:display
25
+
26
+ =end
27
+
28
+ class Apotomo::DatatableWidget < Apotomo::Widget
29
+ DEFAULT_VIEW_PATHS << File.expand_path('../../', __FILE__)
30
+
31
+ responds_to_event :data #Used by sAjaxSource plugin option
32
+ responds_to_event :display
33
+ responds_to_event :test_evt, :with => :test_evt, :passing => :root
34
+
35
+ after_initialize do
36
+ ## set default options and those based on options provided in the has_widgets call in the controller
37
+ set_options(options)
38
+ @test_val=0
39
+ end
40
+
41
+ def test_val
42
+ @test_val
43
+ end
44
+
45
+ def increment_test_val
46
+ @test_val=@test_val+1
47
+ end
48
+
49
+ def test_evt(event)
50
+ if @merged_options[:widget][:controller].respond_to?(:apotomo_datatable_event)
51
+ @evt_test=@merged_options[:widget][:controller].apotomo_datatable_event(event)
52
+ end
53
+ end
54
+
55
+ def merged_options
56
+ @merged_options
57
+ end
58
+
59
+ def display(view_options={})
60
+ if view_options && view_options.respond_to?('each_pair')
61
+ ## merge options provided by the render_widget method call in the view
62
+ @merged_options.deep_merge!(view_options)
63
+ end
64
+
65
+ ## merge options from the URL params
66
+ merge_url_param_options(params)
67
+ process_boolean_options
68
+
69
+ ##Build json string to pass plugin options to the client
70
+ ##and command to merge with client-side plugin_options if provided
71
+ datatable_options=@merged_options[:plugin].to_json
72
+ if @merged_options[:template][:plugin_options]
73
+ datatable_options="$.extend(#{datatable_options},#{@merged_options[:template][:plugin_options]})"
74
+ end
75
+
76
+ #make sure :header and :footer are arrays
77
+ if @merged_options[:template][:header] && ! @merged_options[:template][:header].respond_to?('each') then @merged_options[:template][:header]=[@merged_options[:template][:header]] end
78
+ if @merged_options[:template][:footer] && ! @merged_options[:template][:footer].respond_to?('each') then @merged_options[:template][:footer]=[@merged_options[:template][:footer]] end
79
+
80
+
81
+ @init_datatable_js= "$(\"##{@merged_options[:template][:id]}\").dataTable(#{datatable_options});"
82
+
83
+ #this is just a test firing an event
84
+ @evt_test='empty'
85
+ self.fire :test_evt
86
+ if @merged_options[:params][:format]=='js'
87
+ #TODO: search the app's widget path for this template before using the default version
88
+ @html=render_to_string :file => File.expand_path('../../apotomo/datatable/display_html', __FILE__)
89
+ #escape double quotes and new lines, then make string safe so it's rendered properly
90
+ @html=@html.gsub(/[\n\r]/,' ').gsub(/"/,'\\\\"').html_safe
91
+ render :view=>:display_js
92
+ # render (replace :view=>:display_html, :selector=>'div#parent')+@init_datatable_js
93
+ else
94
+ render :view=>:display_html
95
+ # render :view=>File.expand_path('./datatable/display_html', __FILE__)
96
+ # render :view=>'app/widgets/apotomo/datatable/display_html'
97
+ end
98
+ end
99
+
100
+
101
+ # def view_for_state(state)
102
+ # "app/widgets/apotomo/datatable/#{state}"
103
+ # end
104
+
105
+ def datatable_init_vars
106
+ end
107
+
108
+ def head_foot(merged_options,section)
109
+ render :locals=>{:merged_options=>merged_options,:section=>section}
110
+ end
111
+
112
+ def data
113
+ is_searching = (params[:sSearch] and params[:sSearch].length>0)
114
+ @records=datasource
115
+ @data={
116
+ :iTotalRecords=>@merged_options[:widget][:model].count,
117
+ :iTotalDisplayRecords=>is_searching ? @records.count : @merged_options[:widget][:model].count,
118
+ :aaData=>@records
119
+ }
120
+ render text: @data.to_json
121
+ end
122
+
123
+ def datasource
124
+ #datatable passes something like
125
+ #"sEcho"=>"1", "iColumns"=>"5", "sColumns"=>"", "iDisplayStart"=>"0", "iDisplayLength"=>"10", "mDataProp_0"=>"id", "mDataProp_1"=>"text", "mDataProp_2"=>"created_at", "mDataProp_3"=>"updated_at", "mDataProp_4"=>"like", "sSearch"=>"", "bRegex"=>"false", "sSearch_0"=>"", "bRegex_0"=>"false", "bSearchable_0"=>"true", "sSearch_1"=>"", "bRegex_1"=>"false", "bSearchable_1"=>"true", "sSearch_2"=>"", "bRegex_2"=>"false", "bSearchable_2"=>"true", "sSearch_3"=>"", "bRegex_3"=>"false", "bSearchable_3"=>"true", "sSearch_4"=>"", "bRegex_4"=>"false", "bSearchable_4"=>"true", "iSortCol_0"=>"0", "sSortDir_0"=>"asc", "iSortingCols"=>"1", "bSortable_0"=>"true", "bSortable_1"=>"true", "bSortable_2"=>"true", "bSortable_3"=>"true", "bSortable_4"=>"true"
126
+ filter={}
127
+ is_searching = (params[:sSearch] and params[:sSearch].length>0)
128
+ if is_searching
129
+ filter[:conditions]=[@merged_options[:widget][:model].column_names.join(' LIKE :sSearch OR ')+' LIKE :sSearch',{:sSearch=>"%#{params[:sSearch]}%"}]
130
+ end
131
+ if params[:iDisplayStart] and params[:iDisplayLength]
132
+ filter[:limit]=params[:iDisplayLength]
133
+ filter[:offset]=params[:iDisplayStart]
134
+ end
135
+ if @merged_options[:widget][:controller].respond_to?('apotomo_datatable_datasource')
136
+ @records=@merged_options[:widget][:controller].apotomo_datatable_datasource(filter)
137
+ else
138
+ @records=@merged_options[:widget][:model].find(:all,filter)
139
+ end
140
+ return @records
141
+ end
142
+
143
+ def create
144
+
145
+ end
146
+
147
+ def edit
148
+
149
+ end
150
+
151
+ def update
152
+
153
+ end
154
+
155
+ def destroy
156
+
157
+ end
158
+
159
+ def set_options(controller_options)
160
+ =begin
161
+ Options:
162
+
163
+ The @merged_options hash includes primary keys for the widget, templates and client-side plugin
164
+ @merged_options={:widget=>{...}, :template=>{...}, :plugin=>{...}}
165
+
166
+ Default options are generated in Apotomo::DatatableWidget.set_options
167
+
168
+ Default options may be overridden from the controller, view, by URL parameters and by a client-side javascript hash, as seen in the example above,
169
+ with the client-side javascript hash taking the highest precedence
170
+ client_side_options -> url_param_options -> view_options -> controller_options -> default_options
171
+
172
+ URL parameters may only define template and plugin options. Defining widget options from the URL would present a security hole
173
+ The client-side hash may only define plugin options. Since it is not passed to the server, template and widget options would be irrelevant
174
+
175
+ $.extend(@merged_options[:widget].to_json,client_side_options) constitutes the arguments passed to the datatable initialization function.
176
+ See http://datatables.net/usage/options for options. As such, any option specified in the jquery datatables API may be set in this sub hash
177
+
178
+
179
+ =end
180
+ #initialize @merged_options, which will contain the final merged hash of options
181
+ @merged_options={:widget=>{},:template=>{},:plugin=>{}}.with_indifferent_access
182
+
183
+ #make sure options (passed by controller in has_widgets) has the basic hash structure
184
+ controller_options=controller_options.respond_to?(:each_pair) ? controller_options : {}.with_indifferent_access
185
+ controller_options=@merged_options.deep_merge(controller_options)
186
+ controller=parent_controller
187
+ if match=/(\w+?)sController/.match(controller.class.name.to_s)
188
+ controller_model_name=match[1]
189
+ end
190
+
191
+ #get model first since it is used to build other default options
192
+ model=nil
193
+ if controller_options[:widget].has_key?(:model)
194
+ if controller_options[:widget][:model].respond_to?("columns_hash")
195
+ model=controller_options[:widget][:model]
196
+ end
197
+ elsif controller_model_name
198
+ #derive the model from the controller name
199
+ if defined?(controller_model_name) && eval(controller_model_name+'.respond_to?("columns_hash")')
200
+ model=eval(controller_model_name)
201
+ end
202
+ end
203
+ if model==nil then
204
+ raise "Cannot use apotomo-datatable without a model. Either pass a model in the has_widgets method call or make sure a model exists with a name corresponding to the controller from which has_widgets is called"
205
+ end
206
+
207
+ default_options={
208
+ :widget=>{
209
+ :name=>"#{model.name}DatatableWidget",
210
+ :model=>model,
211
+ :controller=>controller,
212
+ :datasource=>self.method(:datasource),
213
+ :test_option=>'default'
214
+ },
215
+ :template=>{
216
+ #The header and footer have the same set of options.
217
+ #Each may contain multiple rows. Each row may define an array of options for each cell
218
+ #:header=
219
+
220
+ #Each may be a single value, an array or a hash
221
+ #If a single value or array, all columns are rendered with the provided options in order
222
+ #If a hash, each key should match column field names. Each key-value is a value or array as above
223
+ #single value or array options are: nil: ommited, label: label, input: input column filter, select: select column filter
224
+ # :header=>{:default=>:label,:name=>[:label,:input],:value=>[:label,:input]},
225
+ :header=>{:default=>:label},
226
+ :footer=>nil,
227
+ :id=>"#{model.name}Datatable",
228
+ :excluded_columns=>[:id,:created_at,:updated_at], #set to a list of field names to exclude from display
229
+ :included_columns=>[], #set to a list of columns to include even if they are excluded in :excluded_columns
230
+ :test_option=>'default'
231
+ },
232
+ :plugin=>{
233
+ :iDisplayStart=>0,
234
+ :bProcessing=>true,
235
+ :bJQueryUI=>true,
236
+ :test_option=>'default'
237
+ }
238
+ }.with_indifferent_access
239
+ default_options[:plugin][:aoColumns]=[]
240
+ model.column_names.each do |name|
241
+ default_options[:plugin][:aoColumns].push({'mDataProp'=>name})
242
+ end
243
+
244
+ # merge default options with options provided by the controller
245
+ @merged_options=default_options.deep_merge(controller_options)
246
+ @merged_options[:params]=params
247
+ end
248
+
249
+ def merge_url_param_options(url_param_options)
250
+ #:widget options are not accepted from URL parameters - accepting them would be a security hole
251
+ if url_param_options.has_key?(:template) && url_param_options[:template].respond_to?('each_pair')
252
+ @merged_options[:template].deep_merge!(url_param_options[:template])
253
+ end
254
+ if url_param_options.has_key?(:plugin) && url_param_options[:plugin].respond_to?('each_pair')
255
+ @merged_options[:plugin].deep_merge!(url_param_options[:plugin])
256
+ end
257
+ end
258
+
259
+ def process_boolean_options
260
+ #some options accept boolean options to indicate the default value (true) or undefined (false or nil)
261
+ #these must be processed after options from all sources have been merged
262
+ #Some true values are converted to default parameters for the plugin
263
+ #Some false values are deleted from the hash to allow the plugin to apply its own default options
264
+
265
+ ## if options[:plugin][:sAjaxSource] is boolean or nil, derive default if true and delete option value from controller
266
+ if @merged_options[:plugin].has_key?(:sAjaxSource)
267
+ sAjaxSource_bool=make_bool(@merged_options[:plugin][:sAjaxSource])
268
+ if sAjaxSource_bool
269
+ @merged_options[:plugin][:sAjaxSource]=url_for_event(:data)
270
+ unless @merged_options[:plugin].has_key?(:bServerSide)
271
+ @merged_options[:plugin][:bServerSide]=true # User server-side processing: http://datatables.net/ref#bServerSide
272
+ end
273
+ else
274
+ @merged_options[:plugin].delete(:sAjaxSource) #delete false or nil value to prevent invalid option from passing to plugin
275
+ end
276
+ end
277
+ ## profide column mapping if using ajax or aaData
278
+ ## provide aaData if requested
279
+ if sAjaxSource_bool || @merged_options[:plugin][:aaData]==true
280
+ if @merged_options[:plugin][:aaData]==true
281
+ records=datasource
282
+ @merged_options[:plugin][:aaData]=records
283
+ end
284
+ else
285
+ @merged_options[:plugin].delete(:aoColumns)
286
+ end
287
+ @merged_options[:plugin][:sAjaxSourceBOOL]=sAjaxSource_bool
288
+ end
289
+
290
+ def make_bool(val)
291
+ if !!val==val
292
+ return val
293
+ else
294
+ if val.is_a?(String) && val.downcase=="true"
295
+ return true
296
+ else
297
+ return false
298
+ end
299
+ end
300
+ end
301
+ end
302
+
303
+