gridify 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +3 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +26 -0
- data/README.rdoc +264 -0
- data/Rakefile +47 -0
- data/VERSION +1 -0
- data/autotest/discover.rb +5 -0
- data/init.rb +1 -0
- data/lib/gridify.rb +44 -0
- data/lib/gridify/assertions.rb +37 -0
- data/lib/gridify/grid.rb +149 -0
- data/lib/gridify/grid_column.rb +121 -0
- data/lib/gridify/grid_finder.rb +197 -0
- data/lib/gridify/grid_options.rb +261 -0
- data/lib/gridify/grid_view.rb +346 -0
- data/spec/db/database.yml +3 -0
- data/spec/db/gridify.sqlite3.db +0 -0
- data/spec/db/schema.rb +7 -0
- data/spec/grid_column_spec.rb +72 -0
- data/spec/grid_finder_spec.rb +192 -0
- data/spec/grid_spec.rb +38 -0
- data/spec/grid_view_spec.rb +423 -0
- data/spec/gridify_spec.rb +34 -0
- data/spec/spec_helper.rb +20 -0
- data/tasks/gridify_tasks.rake +4 -0
- metadata +137 -0
@@ -0,0 +1,261 @@
|
|
1
|
+
module Gridify
|
2
|
+
class Grid
|
3
|
+
# non persistent options:
|
4
|
+
# :build_model
|
5
|
+
# :only
|
6
|
+
# :except
|
7
|
+
|
8
|
+
attr_accessor :name, # name of the table (required)
|
9
|
+
:resource, # based on AR model class (assume tableized, plural, string)
|
10
|
+
# used as basis for all RESTful requests and data format
|
11
|
+
|
12
|
+
# model
|
13
|
+
:columns, # incoming: hash of presets (native jqGrid); internally: array of GridColumn objects
|
14
|
+
# { :body => { "title" => {"width" => 98} }}
|
15
|
+
|
16
|
+
#:widths, # hash of column width (key = data type)
|
17
|
+
:searchable, # default: true (used in generating columns, changing has no effect on existing cols)
|
18
|
+
:sortable, # default: true (used in generating columns, changing has no effect on existing cols)
|
19
|
+
:editable, # default: false (used in generating columns, changing has no effect on existing cols)
|
20
|
+
|
21
|
+
# grid
|
22
|
+
:dom_id, # defaults to #{resource}_#{name} eg "notes_grid"
|
23
|
+
|
24
|
+
:jqgrid_options, # hash of additional jqGrid options that override any other settings
|
25
|
+
|
26
|
+
|
27
|
+
# grid layout options
|
28
|
+
:width, # in pixels, or nil (nil means calculated based on overflow setting)
|
29
|
+
:width_fit, # :fluid, :scroll, or :visible
|
30
|
+
# :fluid will always fit container (presently ignores width option)
|
31
|
+
# :scroll uses horizontal scrollbars
|
32
|
+
# :fitted scales columns to fit in width, not fluid
|
33
|
+
|
34
|
+
:height, # in pixels, '100%', or :auto (150)
|
35
|
+
# :auto means makes it as tall as needed per number of rows
|
36
|
+
|
37
|
+
:resizable, # allow gride resize with mouse, (true) (or {}) for default options;
|
38
|
+
# nil or false for disabled; or hash of jqUI options
|
39
|
+
# see http://jqueryui.com/demos/resizable/
|
40
|
+
# defaults (differ from jqUI ones) "minWidth" => 150, "minHeight" => 80
|
41
|
+
# when overflow is fluid, "handles" => 's', otherwise 'e, s, se'
|
42
|
+
|
43
|
+
:arranger, # :sortable, :hide_show, :chooser, or nil for none (nil) ,
|
44
|
+
# can combine with array of options
|
45
|
+
# or can be a hash with options
|
46
|
+
# see http://www.trirand.com/jqgridwiki/doku.php?id=wiki:show_hide_columns
|
47
|
+
|
48
|
+
# rows
|
49
|
+
:alt_rows, # true for odd/even row classes, or odd row style name string (nil)
|
50
|
+
|
51
|
+
:row_numbers, # true to display row numbers in left column; or numeric width in pixels (nil)
|
52
|
+
|
53
|
+
:select_rows, # true for rows are selectable (eg for pager buttons); or js function when row is selected, false disables hover (true if pager buttons else false)
|
54
|
+
|
55
|
+
# header layer
|
56
|
+
:title, # title string (aka caption), or true for resource.titleize, nil for no title (nil)
|
57
|
+
|
58
|
+
:collapsible, # when true generates collapse icon (false)
|
59
|
+
:collapsed, # when true initial state is collapsed (false)
|
60
|
+
|
61
|
+
# pager layer
|
62
|
+
:pager, # id of the pager, or true => dom_id+"_pager", false or nil for no pager (nil)
|
63
|
+
:paging_controls, # false to disable all (true); or hash with native jqGrid options
|
64
|
+
:paging_choices, # array of rows_per_page choices ([10,25,50,100])
|
65
|
+
|
66
|
+
# nav buttons
|
67
|
+
:view_button, # true, or hash of native jqGrid parameters and events for the action
|
68
|
+
:add_button,
|
69
|
+
:edit_button,
|
70
|
+
:delete_button,
|
71
|
+
|
72
|
+
:search_button, # enable search button and dialog
|
73
|
+
:search_advanced, # instead of search_button
|
74
|
+
:search_toolbar, # toggleable search bar, true or :visible, :hidden (other options?) (nil)
|
75
|
+
|
76
|
+
:refresh_button,
|
77
|
+
:jqgrid_nav_options, # native jqGrid button options (added to 2nd arg in navGrid method)
|
78
|
+
|
79
|
+
|
80
|
+
# data
|
81
|
+
:restful, # use restful url and mtype (true) for all actions
|
82
|
+
:finder, # default: :find
|
83
|
+
:url, # request url (required unless table_to_grid or derived from resource)
|
84
|
+
# if nil, uses "/#{resource}" eg "/notes"
|
85
|
+
# note, to force "editurl" use jqgrid_options
|
86
|
+
|
87
|
+
:data_type, # :xml, :json, and other defined in jqGrid options doc (xml)
|
88
|
+
:data_format, # (defaults to rails conventin based on resource) <chickens><chicken><title><body> format
|
89
|
+
# set false for jqGrid default <rows><records><row><cell> format
|
90
|
+
|
91
|
+
:sort_by, # name of sort column of next request
|
92
|
+
:sort_order, # sort direction of next request, 'asc' or 'desc' ('asc')
|
93
|
+
:case_sensitive, # sort and search are case sensitive (false)
|
94
|
+
|
95
|
+
:current_page, # current page requested
|
96
|
+
:rows_per_page, # number of items to be requested in the next request (paging_choices.first or -1 if pager false)
|
97
|
+
|
98
|
+
:table_to_grid, # when true generates tableToGrid (false) from html table, then use as local data
|
99
|
+
# note, we assume table rows are not selectable.
|
100
|
+
# (tableToGrid sets multiselect when first col has checkboxes or radio buttons,
|
101
|
+
# we dont know to preserve this so you also need to set in options)
|
102
|
+
|
103
|
+
:load_once, # true to use local data after first load (false)
|
104
|
+
:error_handler, # javacript: method for crud error handling (default to "after_submit")
|
105
|
+
:error_container, # selector for posting error/flash messages (.errorExplanation)
|
106
|
+
|
107
|
+
|
108
|
+
:z
|
109
|
+
|
110
|
+
# ----------------------
|
111
|
+
# attribute defaults and special value handling
|
112
|
+
# (sure it'd be easier to initialize defaults using a hash but we want nil to mean the jqGrid default - might be true - and not pass a value at all)
|
113
|
+
|
114
|
+
def restful
|
115
|
+
@restful==false ? false : true
|
116
|
+
end
|
117
|
+
|
118
|
+
def finder
|
119
|
+
@finder || :find
|
120
|
+
end
|
121
|
+
|
122
|
+
def searchable
|
123
|
+
@searchable==false ? false : true
|
124
|
+
end
|
125
|
+
|
126
|
+
def sortable
|
127
|
+
@sortable==false ? false : true
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
def dom_id
|
132
|
+
@dom_id || "#{resource}_#{name}"
|
133
|
+
end
|
134
|
+
|
135
|
+
def jqgrid_options
|
136
|
+
@jqgrid_options || {}
|
137
|
+
end
|
138
|
+
|
139
|
+
def width_fit
|
140
|
+
@width_fit || :fluid
|
141
|
+
end
|
142
|
+
|
143
|
+
def resizable
|
144
|
+
return false if @resizable == false
|
145
|
+
rs = { "minWidth" => 150, "minHeight" => 80 }
|
146
|
+
rs.merge!({ "handles" => 's' }) if width_fit == :fluid
|
147
|
+
rs.merge!( @resizable ) if @resizable.is_a?(Hash)
|
148
|
+
rs
|
149
|
+
end
|
150
|
+
|
151
|
+
def arranger_type #read-only
|
152
|
+
if arranger.is_a?(Hash)
|
153
|
+
arranger.keys
|
154
|
+
else
|
155
|
+
Array(arranger)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def arranger_options(type) #read-only
|
160
|
+
(arranger[type] if arranger.is_a?(Hash)) || {}
|
161
|
+
end
|
162
|
+
|
163
|
+
def select_rows
|
164
|
+
if @select_rows
|
165
|
+
@select_rows
|
166
|
+
else
|
167
|
+
pager && (view_button || edit_button || delete_button)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# header layer
|
172
|
+
def title
|
173
|
+
case @title
|
174
|
+
when String: @title
|
175
|
+
when true: resource.titleize
|
176
|
+
else
|
177
|
+
(' ' if collapsible || collapsed) #show header with blank title
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def collapsible
|
182
|
+
@collapsible || @collapsed
|
183
|
+
end
|
184
|
+
|
185
|
+
# pager layer
|
186
|
+
def pager
|
187
|
+
case @pager
|
188
|
+
when String: @pager
|
189
|
+
when true: dom_id+'_pager'
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def paging_controls
|
194
|
+
@paging_controls.nil? ? true : @paging_controls
|
195
|
+
end
|
196
|
+
|
197
|
+
def paging_choices
|
198
|
+
@paging_choices || [10,25,50,100]
|
199
|
+
end
|
200
|
+
|
201
|
+
# data
|
202
|
+
def url
|
203
|
+
@url || "/#{resource}"
|
204
|
+
end
|
205
|
+
|
206
|
+
def rows_per_page
|
207
|
+
#debugger
|
208
|
+
# all rows when pager controls or rows per page are off
|
209
|
+
if !pager || paging_controls==false || @rows_per_page==false || @rows_per_page==-1
|
210
|
+
-1
|
211
|
+
elsif @rows_per_page.nil?
|
212
|
+
paging_choices.first
|
213
|
+
else
|
214
|
+
@rows_per_page
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def data_type
|
219
|
+
@data_type || :xml
|
220
|
+
end
|
221
|
+
|
222
|
+
def data_format
|
223
|
+
if @data_format || @data_format==false #explicit false for no param
|
224
|
+
@data_format
|
225
|
+
elsif resource && data_type == :xml
|
226
|
+
{
|
227
|
+
:root => resource,
|
228
|
+
:page => resource+'>page',
|
229
|
+
:total => resource+'>total_pages',
|
230
|
+
:records => resource+'>total_records',
|
231
|
+
:row => resource.singularize,
|
232
|
+
:repeatitems => false,
|
233
|
+
:id => :id
|
234
|
+
}
|
235
|
+
elsif resource && data_type == :json
|
236
|
+
{
|
237
|
+
:root => resource,
|
238
|
+
:page => 'page',
|
239
|
+
:total => 'total_pages',
|
240
|
+
:records => 'total_records',
|
241
|
+
:row => resource.singularize,
|
242
|
+
:repeatitems => false,
|
243
|
+
:id => :id
|
244
|
+
}
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
def error_handler
|
249
|
+
@error_handler || 'gridify_action_error_handler'
|
250
|
+
end
|
251
|
+
|
252
|
+
def error_handler_return_value
|
253
|
+
error_handler ? error_handler : 'true;'
|
254
|
+
end
|
255
|
+
|
256
|
+
def error_container
|
257
|
+
@error_container || '.errorExplanation'
|
258
|
+
end
|
259
|
+
|
260
|
+
end
|
261
|
+
end
|
@@ -0,0 +1,346 @@
|
|
1
|
+
# reference: http://github.com/ahe/2dc_jqgrid
|
2
|
+
|
3
|
+
module Gridify
|
4
|
+
class Grid
|
5
|
+
|
6
|
+
# ----------------------
|
7
|
+
# generate the grid javascript for a view
|
8
|
+
# options:
|
9
|
+
# :script => true generates <script> tag (true)
|
10
|
+
# :ready => true generates jquery ready function (true)
|
11
|
+
def to_javascript( options={} )
|
12
|
+
options = { :script => true, :ready => true }.merge(options)
|
13
|
+
|
14
|
+
s = ''
|
15
|
+
if options[:script]
|
16
|
+
s << %Q^<script type="text/javascript">^
|
17
|
+
end
|
18
|
+
|
19
|
+
s << js_helpers
|
20
|
+
|
21
|
+
if options[:ready]
|
22
|
+
s << %Q^jQuery(document).ready(function(){^
|
23
|
+
end
|
24
|
+
|
25
|
+
s << jqgrid_javascript(options)
|
26
|
+
|
27
|
+
if options[:ready]
|
28
|
+
s << %Q^});^
|
29
|
+
end
|
30
|
+
if options[:script]
|
31
|
+
s << %Q^</script>^
|
32
|
+
end
|
33
|
+
s
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
def to_json
|
38
|
+
jqgrid_properties.to_json_with_js
|
39
|
+
end
|
40
|
+
|
41
|
+
# alias :to_s, :to_javascript
|
42
|
+
def to_s( options={} )
|
43
|
+
to_javascript( options )
|
44
|
+
end
|
45
|
+
|
46
|
+
# ------------------
|
47
|
+
protected
|
48
|
+
# ------------------
|
49
|
+
|
50
|
+
# //{ url: '/notes/{id}', mtype: 'PUT', reloadAfterSubmit: false, closeAfterEdit: true }, // edit settings
|
51
|
+
# //{ url: '/notes', mtype: 'POST', reloadAfterSubmit: false, closeAfterEdit: true }, // add settings
|
52
|
+
# //{ url: '/notes/{id}', mtype: 'DELETE', reloadAfterSubmit: false }, // delete settings
|
53
|
+
|
54
|
+
# get the button options
|
55
|
+
def edit_button_options
|
56
|
+
# 'url' => '/notes/{id}', 'mtype' => 'PUT'
|
57
|
+
# {afterSubmit:function(r,data){return #{options[:error_handler_return_value]}(r,data,'edit');}},
|
58
|
+
|
59
|
+
# note, closeAfterEdit will not close if response returns a non-empty string (even if "success" message)
|
60
|
+
merge_options_defaults( edit_button,
|
61
|
+
'reloadAfterSubmit' => false,
|
62
|
+
'closeAfterEdit' => true,
|
63
|
+
'afterSubmit' => "javascript: function(r,data){return #{error_handler_return_value}(r,data,'edit');}"
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
def add_button_options
|
68
|
+
# 'url' => '/notes', 'mtype' => 'POST'
|
69
|
+
merge_options_defaults( add_button,
|
70
|
+
'reloadAfterSubmit' => false,
|
71
|
+
'closeAfterEdit' => true,
|
72
|
+
'afterSubmit' => "javascript: function(r,data){return #{error_handler_return_value}(r,data,'add');}"
|
73
|
+
)
|
74
|
+
end
|
75
|
+
|
76
|
+
def delete_button_options
|
77
|
+
# 'url' => '/notes/{id}', 'mtype' => 'DELETE'
|
78
|
+
merge_options_defaults( delete_button,
|
79
|
+
'reloadAfterSubmit' => false,
|
80
|
+
'afterSubmit' => "javascript: function(r,data){return #{error_handler_return_value}(r,data,'delete');}"
|
81
|
+
)
|
82
|
+
end
|
83
|
+
|
84
|
+
def search_button_options
|
85
|
+
if search_advanced
|
86
|
+
merge_options_defaults( search_advanced, 'multipleSearch' => true)
|
87
|
+
else
|
88
|
+
merge_options_defaults( search_button)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def view_button_options
|
93
|
+
merge_options_defaults( view_button)
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
# generate the jqGrid initial values in json
|
98
|
+
# maps our attributes to jqGrid options; omit values when same as jqGrid defaults
|
99
|
+
def jqgrid_properties
|
100
|
+
vals = {}
|
101
|
+
|
102
|
+
# data and request options
|
103
|
+
vals['url'] = url if url
|
104
|
+
vals['restful'] = true if restful
|
105
|
+
vals['postData'] = { :grid => name } #identify which grid making the request
|
106
|
+
# vals['colNames'] = column_names if columns.present?
|
107
|
+
vals['colModel'] = column_model if columns.present?
|
108
|
+
vals['datatype'] = data_type if data_type
|
109
|
+
if data_format.present?
|
110
|
+
if data_type == :xml
|
111
|
+
vals['xmlReader'] = data_format
|
112
|
+
elsif data_type == :json
|
113
|
+
vals['jsonReader'] = data_format
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
vals['loadonce'] = load_once if load_once
|
118
|
+
|
119
|
+
vals['sortname'] = sort_by if sort_by
|
120
|
+
vals['sortorder'] = sort_order if sort_order && sort_by
|
121
|
+
vals['rowNum'] = rows_per_page if rows_per_page
|
122
|
+
vals['page'] = current_page if current_page
|
123
|
+
|
124
|
+
# grid options
|
125
|
+
vals['height'] = height if height
|
126
|
+
vals['gridview'] = true # faster views, NOTE theres cases when this needs to be disabled
|
127
|
+
|
128
|
+
case width_fit
|
129
|
+
when :fitted
|
130
|
+
#vals[:autowidth] = false #default
|
131
|
+
#vals[:shrinkToFit] = true #default
|
132
|
+
vals['forceFit'] = true
|
133
|
+
vals['width'] = width if width
|
134
|
+
|
135
|
+
when :scroll
|
136
|
+
#vals[:autowidth] = false #default
|
137
|
+
vals['shrinkToFit'] = false
|
138
|
+
#vals['forceFit'] = #ignored by jqGrid
|
139
|
+
vals['width'] = width if width
|
140
|
+
|
141
|
+
else #when :fluid
|
142
|
+
vals['autowidth'] = true
|
143
|
+
#vals['shrinkToFit'] = true #default
|
144
|
+
vals['forceFit'] = true
|
145
|
+
#vals['width'] = is ignored
|
146
|
+
vals['resizeStop'] = 'javascript: gridify_fluid_recalc_width'
|
147
|
+
end
|
148
|
+
|
149
|
+
vals['sortable'] = true if arranger_type.include?(:sortable)
|
150
|
+
|
151
|
+
# header layer
|
152
|
+
vals['caption'] = title if title
|
153
|
+
vals['hidegrid'] = false unless collapsible
|
154
|
+
vals['hiddengrid'] = true if collapsed
|
155
|
+
|
156
|
+
# row formatting
|
157
|
+
vals['altrows'] = true if alt_rows
|
158
|
+
vals['altclass'] = alt_rows if alt_rows.is_a?(String)
|
159
|
+
|
160
|
+
vals['rowNumbers'] = true if row_numbers
|
161
|
+
vals['rownumWidth'] = row_numbers if row_numbers.is_a?(Numeric)
|
162
|
+
|
163
|
+
if select_rows.present?
|
164
|
+
vals['scrollrows'] = true
|
165
|
+
#handler...
|
166
|
+
else
|
167
|
+
vals['hoverrows'] = false
|
168
|
+
vals['beforeSelectRow'] = "javascript: function(){ false; }"
|
169
|
+
end
|
170
|
+
|
171
|
+
# pager layer
|
172
|
+
if pager
|
173
|
+
vals['pager'] = "##{pager}"
|
174
|
+
vals['viewrecords'] = true # display total records in the query (eg "1 - 10 of 25")
|
175
|
+
vals['rowList'] = paging_choices
|
176
|
+
if paging_controls.is_a?(Hash)
|
177
|
+
# allow override of jqGrid pager options
|
178
|
+
vals.merge!(paging_controls)
|
179
|
+
elsif !paging_controls
|
180
|
+
vals['rowList'] = []
|
181
|
+
vals['pgbuttons'] = false
|
182
|
+
vals['pginput'] = false
|
183
|
+
vals['recordtext'] = "{2} records"
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# allow override of native jqGrid options
|
188
|
+
vals.merge(jqgrid_options)
|
189
|
+
end
|
190
|
+
|
191
|
+
# -----------------
|
192
|
+
def jqgrid_javascript( options={} )
|
193
|
+
s = ''
|
194
|
+
|
195
|
+
if table_to_grid
|
196
|
+
s << %Q^ tableToGrid("##{dom_id}", #{to_json});^
|
197
|
+
s << %Q^ grid = jQuery("##{dom_id}") ^
|
198
|
+
else
|
199
|
+
s << %Q^ grid = jQuery("##{dom_id}").jqGrid(#{to_json})^
|
200
|
+
end
|
201
|
+
|
202
|
+
# tag the grid as fluid so we can find it on resize events
|
203
|
+
if width_fit == :fluid
|
204
|
+
s << %Q^ .addClass("fluid")^
|
205
|
+
end
|
206
|
+
|
207
|
+
# override tableToGrid colmodel options as needed (sortable)
|
208
|
+
#s << %Q^ .jqGrid('setColProp','Title',{sortable: false})^
|
209
|
+
|
210
|
+
# resize method
|
211
|
+
if resizable
|
212
|
+
s << %Q^ .jqGrid('gridResize', #{resizable.to_json})^
|
213
|
+
end
|
214
|
+
|
215
|
+
# pager buttons (navGrid)
|
216
|
+
if pager
|
217
|
+
nav_params = {
|
218
|
+
'edit' => edit_button.present?,
|
219
|
+
'add' => add_button.present?,
|
220
|
+
'del' => delete_button.present?,
|
221
|
+
'search' => search_button.present? || search_advanced.present?,
|
222
|
+
'view' => view_button.present?,
|
223
|
+
'refresh' => refresh_button.present?
|
224
|
+
}.merge(jqgrid_nav_options||{})
|
225
|
+
|
226
|
+
s << %Q^ .navGrid('##{pager}',
|
227
|
+
#{nav_params.to_json},
|
228
|
+
#{edit_button_options.to_json_with_js},
|
229
|
+
#{add_button_options.to_json_with_js},
|
230
|
+
#{delete_button_options.to_json_with_js},
|
231
|
+
#{search_button_options.to_json_with_js},
|
232
|
+
#{view_button_options.to_json_with_js}
|
233
|
+
)^
|
234
|
+
end
|
235
|
+
|
236
|
+
if arranger_type.include?(:hide_show)
|
237
|
+
s << %Q^ .jqGrid('navButtonAdd','##{pager}',{
|
238
|
+
caption: "Columns",
|
239
|
+
title: "Hide/Show Columns",
|
240
|
+
onClickButton : function (){ jQuery("##{dom_id}").jqGrid('setColumns',
|
241
|
+
#{arranger_options(:hide_show).to_json_with_js} );
|
242
|
+
}
|
243
|
+
})^
|
244
|
+
end
|
245
|
+
if arranger_type.include?(:chooser)
|
246
|
+
# hackey way to build the string but gets it done
|
247
|
+
chooser_code = %Q^ function (){ jQuery('##{dom_id}').jqGrid('columnChooser', {
|
248
|
+
done : function (perm) {
|
249
|
+
if (perm) {
|
250
|
+
this.jqGrid('remapColumns', perm, true);
|
251
|
+
var gwdth = this.jqGrid('getGridParam','width');
|
252
|
+
this.jqGrid('setGridWidth',gwdth);
|
253
|
+
}
|
254
|
+
} })}^
|
255
|
+
chooser_opts = {
|
256
|
+
'caption' => 'Columns',
|
257
|
+
'title' => 'Arrange Columns',
|
258
|
+
'onClickButton' => 'chooser_code'
|
259
|
+
}.merge(arranger_options(:chooser))
|
260
|
+
s << %Q^ .jqGrid('navButtonAdd','##{pager}', #{chooser_opts.to_json.gsub('"chooser_code"', chooser_code)} )^
|
261
|
+
end
|
262
|
+
|
263
|
+
if search_toolbar
|
264
|
+
# I wish we could put this in the header rather than the pager
|
265
|
+
s << %Q^ .jqGrid('navButtonAdd',"##{pager}", { caption:"Toggle", title:"Toggle Search Toolbar", buttonicon: 'ui-icon-pin-s', onClickButton: function(){ grid[0].toggleToolbar() } })
|
266
|
+
.jqGrid('navButtonAdd',"##{pager}", { caption:"Clear", title:"Clear Search", buttonicon: 'ui-icon-refresh', onClickButton: function(){ grid[0].clearToolbar() } })
|
267
|
+
.jqGrid('filterToolbar')^
|
268
|
+
end
|
269
|
+
|
270
|
+
# TODO: built in event handlers, eg
|
271
|
+
# loadError
|
272
|
+
# onSelectRow, onDblClickRow, onRightClickRow etc
|
273
|
+
|
274
|
+
s << '; '
|
275
|
+
|
276
|
+
unless search_toolbar == :visible
|
277
|
+
s << %Q^ grid[0].toggleToolbar(); ^
|
278
|
+
end
|
279
|
+
|
280
|
+
# # keep page controls centered (jqgrid bug) [eg appears when :width_fit => :scroll]
|
281
|
+
# s << %Q^ $("##{pager}_left").css("width", "auto"); ^
|
282
|
+
|
283
|
+
s
|
284
|
+
end
|
285
|
+
|
286
|
+
# ------------------
|
287
|
+
def js_helpers
|
288
|
+
# just move this into appliaction.js?
|
289
|
+
|
290
|
+
# gridify_fluid_recalc_width: allow grid resize on window resize events
|
291
|
+
# recalculate width of grid based on parent container; handles multiple grids
|
292
|
+
# ref: http://www.trirand.com/blog/?page_id=393/feature-request/Resizable%20grid/
|
293
|
+
|
294
|
+
# afterSubmit: display error message in response
|
295
|
+
|
296
|
+
%Q^ function gridify_fluid_recalc_width(){
|
297
|
+
if (grids = jQuery('.fluid.ui-jqgrid-btable:visible')) {
|
298
|
+
grids.each(function(index) {
|
299
|
+
gridId = jQuery(this).attr('id');
|
300
|
+
gridParentWidth = jQuery('#gbox_' + gridId).parent().width();
|
301
|
+
jQuery('#' + gridId).setGridWidth(gridParentWidth);
|
302
|
+
});
|
303
|
+
}
|
304
|
+
};
|
305
|
+
|
306
|
+
jQuery(window).bind('resize', gridify_fluid_recalc_width);
|
307
|
+
|
308
|
+
function gridify_action_error_handler(r, data, action){
|
309
|
+
if (r.responseText != '') {
|
310
|
+
return [false, r.responseText];
|
311
|
+
} else {
|
312
|
+
return true;
|
313
|
+
}
|
314
|
+
}
|
315
|
+
^
|
316
|
+
end
|
317
|
+
|
318
|
+
|
319
|
+
# if(r.responseText != "") {
|
320
|
+
# $('#{error_container}').html(r.responseText);
|
321
|
+
# $('#{error_container}').slideDown();
|
322
|
+
# //window.setTimeout(function() { // Hide error div after 6 seconds
|
323
|
+
# // $('#{error_container}').slideUp();
|
324
|
+
# //}, 6000);
|
325
|
+
# return false;
|
326
|
+
# }
|
327
|
+
# return true;
|
328
|
+
|
329
|
+
# lets options be true or a hash, merges into defaults and returns a hash
|
330
|
+
def merge_options_defaults( options, defaults={} )
|
331
|
+
if options
|
332
|
+
defaults.merge( options==true ? {} : options)
|
333
|
+
else
|
334
|
+
{}
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
class Hash
|
342
|
+
# replace embedded '"javascript: foo"' with 'foo'
|
343
|
+
def to_json_with_js
|
344
|
+
self.to_json.gsub(/\"javascript: ([^"]*)\"/) {|string| string[1..-2].gsub('javascript:','') }
|
345
|
+
end
|
346
|
+
end
|