gridify 0.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/.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
|