widget_list 1.3.4 → 1.3.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/.gitignore +35 -35
  2. data/Gemfile +3 -3
  3. data/LICENSE.txt +21 -21
  4. data/README.md +736 -728
  5. data/Rakefile +1 -1
  6. data/app/views/widget_list/_condition_fields.html.erb +0 -0
  7. data/app/views/widget_list/_ransack_fields.html.erb +0 -0
  8. data/app/views/widget_list/_ransack_widget_list_advanced_search.html.erb +0 -0
  9. data/app/views/widget_list/administration/_button_row.html.erb +13 -13
  10. data/app/views/widget_list/administration/_checkbox_row.html.erb +18 -18
  11. data/app/views/widget_list/administration/_field_row.html.erb +11 -11
  12. data/app/views/widget_list/administration/_output.html.erb +1100 -1100
  13. data/app/views/widget_list/administration/_output_save.html.erb +1 -1
  14. data/app/views/widget_list/list_partials/_col.html.erb +0 -0
  15. data/app/views/widget_list/list_partials/_list_description.html.erb +2 -2
  16. data/app/views/widget_list/list_partials/_no_sort_column.html.erb +0 -0
  17. data/app/views/widget_list/list_partials/_outer_shell.html.erb +0 -0
  18. data/app/views/widget_list/list_partials/_pagination_jump_active.html.erb +0 -0
  19. data/app/views/widget_list/list_partials/_pagination_jump_unactive.html.erb +0 -0
  20. data/app/views/widget_list/list_partials/_pagination_next_active.html.erb +0 -0
  21. data/app/views/widget_list/list_partials/_pagination_next_disabled.html.erb +0 -0
  22. data/app/views/widget_list/list_partials/_pagination_previous_active.html.erb +0 -0
  23. data/app/views/widget_list/list_partials/_pagination_previous_disabled.html.erb +0 -0
  24. data/app/views/widget_list/list_partials/_pagination_wrapper.html.erb +0 -0
  25. data/app/views/widget_list/list_partials/_row.html.erb +0 -0
  26. data/app/views/widget_list/list_partials/_sequence.html.erb +0 -0
  27. data/app/views/widget_list/list_partials/_sort_column.html.erb +0 -0
  28. data/checkin_gem.sh +0 -0
  29. data/lib/extensions/action_controller_base.rb +33 -33
  30. data/lib/widget_list.rb +4685 -4389
  31. data/lib/widget_list/engine.rb +8 -8
  32. data/lib/widget_list/hash.rb +113 -113
  33. data/lib/widget_list/md5.rb +18 -18
  34. data/lib/widget_list/railtie.rb +42 -42
  35. data/lib/widget_list/sequel.rb +287 -218
  36. data/lib/widget_list/string.rb +41 -41
  37. data/lib/widget_list/tpl.rb +185 -185
  38. data/lib/widget_list/utils.rb +92 -92
  39. data/lib/widget_list/version.rb +3 -3
  40. data/lib/widget_list/widgets.rb +756 -756
  41. data/publish_gem.sh +37 -37
  42. data/vendor/assets/images/gobblecons/README.rtf +127 -127
  43. data/vendor/assets/javascripts/widget_list.js +795 -795
  44. data/vendor/assets/stylesheets/widget_list.css +813 -813
  45. data/vendor/assets/stylesheets/widgets.css +116 -116
  46. data/widget_list.gemspec +38 -38
  47. metadata +63 -54
data/.gitignore CHANGED
@@ -1,35 +1,35 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
18
-
19
- .idea/widget_list.iml
20
-
21
- .idea/widget_list.iml
22
-
23
- .idea/workspace.xml
24
-
25
- .DS_Store
26
-
27
- lib/widget_list (Autosaved).txt
28
-
29
- .idea/.rakeTasks
30
-
31
- .idea/misc.xml
32
-
33
- .idea/modules.xml
34
-
35
- .idea/modules.xml
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+
19
+ .idea/widget_list.iml
20
+
21
+ .idea/widget_list.iml
22
+
23
+ .idea/workspace.xml
24
+
25
+ .DS_Store
26
+
27
+ lib/widget_list (Autosaved).txt
28
+
29
+ .idea/.rakeTasks
30
+
31
+ .idea/misc.xml
32
+
33
+ .idea/modules.xml
34
+
35
+ .idea/modules.xml
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in widget_list.gemspec
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in widget_list.gemspec
4
4
  gemspec
@@ -1,22 +1,22 @@
1
- Copyright (c) 2012 TODO: Write your name
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
1
+ Copyright (c) 2012 TODO: Write your name
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
22
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,729 +1,737 @@
1
- # WidgetList
2
- ====================
3
-
4
- ****
5
-
6
- ## Introduction
7
-
8
- ****
9
-
10
- This is my first gem ever! It is an exciting gem because it is being used in production by a fortune 500 company. Please use and give me feedback/issues/pull requests.
11
-
12
- ****
13
-
14
- ## Summary
15
-
16
- ****
17
-
18
- I feel like there are not very good lists in ruby/rails and/or dont care to find any because nothing will compare to widget_list's implementation.
19
-
20
- In rails you have will_paginate and other ones like it using the ActiveRecord approach, but widget_list adds some awesome treats to standard boring pagers:
21
-
22
- * A sleek ajaxified list
23
- * Full Blown configuration administration tool
24
- * Supports *ALL Databases (Haven't tested everything yet though, I am sure there are tweaks for each DB). mysql, postgres, oracle and sqllite tested (basic example)
25
- * Full sorting ASC/DESC and paging/limits of list via ajax
26
- * Easily add row level buttons for each row
27
- * Custom tags to pass to be replaced by actual data from each column/value
28
- * Automatic wildcard search support as well as CSV numeric parsing of when to perform a LIKE search or an IN statement on the primary keys
29
- * Column mappings and names
30
- * Drill down link helper functions to allow user to click and filter the list by the particular record value
31
- * Checkboxes for each row for custom selection and mass actions
32
- * Session rememberance for each list/view of what was last sorted, which page the person was on, the limit and search filters
33
- * Ability to set a custom HTML arrow which draws a hidden DIV intended for someone to put custom widgets inside of to pass new filters to the list before it executes
34
- * Buttons for each row and areas on the bottom of the grid where you can add "Action buttons"
35
- * Export visible data as CSV
36
- * Grouping/Predefined report filter feature
37
- * Either use a custom advanced searching form you build, or use the ransack dependency to build out a powerful filtering mechanism on the DOWN ARROW form users click. (See screenshots below)
38
- * Granular control over site-wide list parameter defaults using [A WidgetList Helper][1] or by simply copying the desired partial from the gem's app/views/widget_list/list_partials into your app/views/widget_list/list_partials and modifying the template for your "site-wide template" and outer list shells
39
- ** Support for theme plugins such as [The Blue Sky Basin Theme][2]
40
-
41
- ****
42
-
43
- ## Screenshots
44
-
45
- ****
46
-
47
- ### Main Example Loaded:
48
-
49
- ![](http://davidrenne.com/github/widget_list/main.png)
50
-
51
- ###Filter Drop Downs:
52
-
53
- ![](http://davidrenne.com/github/widget_list/filtered.png)
54
-
55
- ###Searching a row (with wild card search):
56
-
57
- ![](http://davidrenne.com/github/widget_list/search.png)
58
-
59
- ###Searching "name=asdf_18" (With ActiveRecord and Ransack hook):
60
-
61
- ![](http://davidrenne.com/github/widget_list/ransack1.png)
62
-
63
- ###Searching "name=asdf_18" and "sku<9000"(With ActiveRecord and Ransack hook):
64
-
65
- ![](http://davidrenne.com/github/widget_list/ransack2.png)
66
-
67
- ###Searching "name=asdf_18" and "sku < 9000" and "price > 67" (With ActiveRecord and Ransack hook):
68
-
69
- ![](http://davidrenne.com/github/widget_list/ransack3.png)
70
-
71
- ###Theme plugins/gem support ([The Blue Sky Basin Theme][2]):
72
-
73
- ![](http://davidrenne.com/github/widget_list/theme_blue_sky_basin.png)
74
-
75
- ****
76
-
77
- ## Administration Tool
78
-
79
- ****
80
-
81
- In order to use this tool please paste your @output into your view
82
-
83
- ```ruby
84
- <div style="margin:50px;">
85
- <%=raw @output%>
86
- </div>
87
- ```
88
-
89
- And then add this to a clean controller. If you have code below, please return below the ajax
90
-
91
- ```ruby
92
- @output = WidgetList.go!()
93
- return render :inline => @output if params.key?('ajax')
94
- ```
95
-
96
- Next you will see this interface which will build some starter code for you:
97
-
98
- ![](http://davidrenne.com/github/widget_list/admin1.jpg)
99
-
100
- ![](http://davidrenne.com/github/widget_list/admin2.jpg)
101
-
102
- ![](http://davidrenne.com/github/widget_list/admin3.jpg)
103
-
104
- ![](http://davidrenne.com/github/widget_list/admin4.jpg)
105
-
106
- ###As you can see below, there is a preview iframe of what you are configuring:
107
-
108
- ![](http://davidrenne.com/github/widget_list/admin5.png)
109
-
110
- ###And finally, the code is output to get you started
111
-
112
- ![](http://davidrenne.com/github/widget_list/admin6.png)
113
-
114
- ****
115
-
116
- ## Installation
117
-
118
- ****
119
-
120
- Add this line to your application's Gemfile:
121
-
122
- ```ruby
123
- gem 'widget_list'
124
- ```
125
- And then execute:
126
- ```ruby
127
- $ bundle
128
- ```
129
- Or install it yourself as:
130
- ```ruby
131
- $ gem install widget_list
132
- ```
133
-
134
- ****
135
-
136
- ## Usage/Examples
137
-
138
- ****
139
-
140
- You can either follow the below instructions or take a look at the changes here https://github.com/davidrenne/widget_list_example/commit/e4e8ab54edcf8bc4538b1850ee762c13bc6f5316
141
-
142
- I recommend if you use widget_list in production that you use config.consider_all_requests_local = true as errors will be handled but the base lists will still draw.
143
-
144
-
145
- ****
146
-
147
- ## Feature Configurations
148
-
149
- ****
150
-
151
- widget_list features and configurations primarily work by a single large hash passed to the constructor with the features you need for the given request which changes how the list is displayed or filtered.
152
-
153
- `name` - The unique name/id's of all the pieces that make up your widget list `default=([*('A'..'Z'),*('0'..'9')]-%w(0 1 I O)).sample(16).join`
154
-
155
- `database` - You can pass which DB connection you would like to use for each list. Only two values/db connections are supported ('primary' or 'secondary') `default='primary'`
156
-
157
- `title` - This adds an H1 title and horizontal rule on top of your list `default=''`
158
-
159
- `listDescription` - This adds a grey header box. It is useful for describing the main query `default=''`
160
-
161
- `pageId` - Base path for requests (typically you never need to change this) `default=$_SERVER['PATH_INFO']`
162
-
163
- `view` - A sub-select query to your database (ALWAYS ALIASED) `default=''`
164
-
165
- `data` - A "sequel" formatted resultset like would be returned from _select() method. Instead of running a SQL query, you can pass an array to populate the list `default={}`
166
-
167
- `colClass` - Your custom td class for all td's `default=''`
168
-
169
- `colAlign` - td align attribute for all td's `default=''`
170
-
171
- `fields` - The visible fields shown in the current list. KEY=column name VALUE= displayed column header `default={}`
172
-
173
- `fieldsHidden` - The non-visible fields in the current list. Typically used when you wish to search on this column, but the main column is a drilldown or some HTML value that isnt easily searchable. VALUE=column name `default=[]`
174
-
175
- `bindVars` - bindVars that are passed to _select() sequel extension I wrote. Which will replace "?" in your query with the associated bindVar `default=[]`
176
-
177
- `bindVarsLegacy` - A Hash whose KEYS ARE CAPITALIZED and whose value is the replacement string. Inside the "view" you would use :MY_KEY as the template to be replaced `default={}`
178
-
179
- `links` - Turn text based record value into a link. KEY=column name VALUE=hash of link Config. Links should most likely pass ['tags']['field_name'] = 'get_var_name' (would yeild get_var_name=1234 for that field value 1234). You can pass ['tags']['onclick'] if you dont want to call ButtonLinkPost which will redirect to the URL built. If you pass ['onclick']['tags'], each field passed will be passed as a parameter for the function you designate `default={}`
180
-
181
- `buttons` - Buttons to generate for each row. KEY=column name VALUE=Hash of widget_button attributes `default={}`
182
-
183
- `inputs` - widget_check is the only one supported so far. (See examples) `default={}`
184
-
185
- `filter` - << "xxx = 123" would be the syntax to add a new filter array. (See examples) `default=[]`
186
-
187
- `groupBy` - The column name or CSV of names to group by. (See examples) `default=[]`
188
-
189
- `rowStart` - Which page the list should start at `default=0`
190
-
191
- `rowLimit` - How many rows per page? `default=10`
192
-
193
- `orderBy` - Default order by "column_name DIRECTION" `default=''`
194
-
195
- `allowHTML` - Strip HTML from view or not `default=true`
196
-
197
- `strlength` - Strip HTML from view or not `default=true`
198
-
199
- `searchClear` - Clear the list's search session `default=false`
200
-
201
- `searchClearAll` - Clear all search session for all lists `default=false`
202
-
203
- `showPagination` - Show pagination HTML `default=true`
204
-
205
- `searchSession` - Remember and restore the last search performed `default=true`
206
-
207
- `carryOverRequests` - will allow you to post custom things from request to all sort/paging URLS for each ajax. Takes an array of GETVARS which will be passed to each request `default=['switch_grouping']`
208
-
209
- `customFooter` - Add buttons or HTML at bottom area of list inside the grey box `default=''`
210
-
211
- `customHeader` - Add buttons or HTML at top area of list above all headers (such as TABS to delineate Summary/Details) `default=''`
212
-
213
- `ajaxFunctionAll` - Custom javascript called asychronously during each click of each event someone interacts with on the list `default=''`
214
-
215
- `ajaxFunction` - Mostly an internal setting `default='ListJumpMin'`
216
-
217
- `showSearch` - Show top search bar `default=true`
218
-
219
- `searchOnkeyup` - Search on key up event `default=''`
220
-
221
- `searchOnclick` - Search on click event `default=''`
222
-
223
- `searchIdCol` - By default `id` column is here because typically if you call your PK's id and are auto-increment and numeric. This can also take in an array of numeric fields so that users can search CSV's of numbers and get back matches `default='id'`
224
-
225
- `searchTitle` - Set a title for the search input `default= 'Search by Id or a list of Ids and more'`
226
-
227
- `searchFieldsIn` - White list of fields to include in a alpha-numeric based like '%%' search `default={}`
228
-
229
- `searchFieldsOut` - Black list of fields to exclude in a alpha-numeric based search `default={'id'=>true}`
230
-
231
- `showExport` - Allow users to export current list view as CSV `default=true`
232
-
233
- `exportButtonTitle` - Title of button `default='Export CSV'`
234
-
235
- `groupByItems` - Custom drop down's created by passing an array of modes. Best suited to group by the data `default=[]`
236
-
237
- `groupBySelected` - Initially selected grouping - defaults to first in list if not. Please pass the string value of the "groupByItem" `default=false`
238
-
239
- `groupByLabel` - Label describing select box `default='Group By'`
240
-
241
- `groupByClick` - Function to call as a custom function for each click on an item `default=''`
242
-
243
- `groupByClickDefault` - Default group by handler inside widget_list.js `default="ListChangeGrouping('<!--NAME-->', this);"`
244
-
245
- `listSearchForm` - Allows you to pass a custom form for the ARROW drop down for advanced searching `default=''`
246
-
247
- `ransackSearch` - If you pass ModelName.search(params[:q]) ransack will show up in your advanced search `default=false`
248
-
249
- `cornerRadius` - Either int number of pixels for radius corners. Or '14px' or whatever you want. `default=15`
250
-
251
- `columnStyle` - Column styles. KEY=column name VALUE= the inline style applied `default={}`
252
-
253
- `columnClass` - Column class. KEY=column name VALUE= the class name `default={}`
254
-
255
- `columnPopupTitle` - Column title as you hover over. KEY=column name VALUE=Popup text `default={}`
256
-
257
- `columnWidth` - Column widths. KEY=column name VALUE= '100px' `default={}`
258
-
259
- `columnNoSort` - Dont allow sorting on these columns (By default all visible columns have a sort link built). KEY=column name VALUE=column name `default={}`
260
-
261
- `borderedColumns` - Add a right border to each column. `default=false`
262
-
263
- `borderedRows` - Style the border of each row. `default=false`
264
-
265
- `borderRowStyle` - Border style of each row. `default='1px solid #CCCCCC'`
266
-
267
- `borderHeadFoot` - Style the border of header (bottom) and footer (top). `default=false`
268
-
269
- `headFootBorderStyle` - Border style of header (bottom) and footer (top). `default='1px solid #CCCCCC'`
270
-
271
- `borderColumnStyle` - Style of row if you use this above feature. `default='1px solid #CCCCCC'`
272
-
273
- `bordersEverywhere?` - If true, use borderEverywhere for all four borders you can pass separately `default=false`
274
-
275
- `borderEverywhere` - The catch all style of borders for headers, rows, outer table border and columns. `default='1px solid #CCCCCC'`
276
-
277
- `defaultButtonClass` - As you have seen in many screenshots, there are several buttons. This controls the innerClass of those drawn from the list. See lib/widget_list/widgets.rb `default='info'`
278
-
279
- `useBoxShadow` - Show shadow or not on list `default=true`
280
-
281
- `shadowInset` - Number or string with '11Px' for an 11PX Inset `default=10`
282
-
283
- `shadowSpread` - Number or string with '11Px' for an 11PX spread `default=20`
284
-
285
- `shadowColor` - Color of bottom right shadow `default='shadowColor'`
286
-
287
- `rowClass` - Class added to all rows `default=''`
288
-
289
- `rowFontColor` - Font color of all data rows that dont have a rowStylesByStatus color: passed to it `default='black'`
290
-
291
- `rowColorByStatus` - {'rowColorByStatus' =>
292
- {'active'=>
293
- {'No' => '#EBEBEB' }
294
- }
295
- }
296
- Color a row based on the value of the column.
297
- `default={}`
298
-
299
- `rowStylesByStatus` - {'rowStylesByStatus' =>
300
- {'active'=>
301
- {'No' => 'font-style:italic;color:red;' }
302
- }
303
- }
304
- Style a row based on the value of the column.
305
- `default={}`
306
-
307
- `rowOffsets` - Color for each row and offset `default=['FFFFFF','FFFFFF']`
308
-
309
- `noDataMessage` - Message to show when no data is found `default='Currently no data.'`
310
-
311
- `useSort` - Allow sorting on list `default=true`
312
-
313
- `headerClass` - Class of each individual header column `default={}`
314
-
315
- `fieldFunction` - A way to wrap or inject columns or SQL formatting in place of your columns `default={}`
316
-
317
- `template` - Pass in a custom template for outer shell `default=''`
318
-
319
- `templateFilter` - Instead of widget list building your search box. Pass your own HTML `default=''`
320
-
321
- `storeSessionChecks` - See http://stackoverflow.com/questions/1928204/marshal-data-too-short for configuring larger session storage which checkboxes would eat up if you had this set to true `default=false`
322
-
323
- `totalRow` - Add in your numeric or dollar amount fields you want to sum or average for the bottom record list_parms['totalRow']['my_field'] = true `default={}`
324
-
325
- `totalRowFirstCol` - A string to display what the row is showing `default='<strong>Total:</strong>'`
326
-
327
- `totalRowMethod` - Allows you to pass 'average' to define which columns should average the sum list_parms['totalRowPrefix']['my_field'] = 'average'. There is only support for average right now `default={}`
328
-
329
- `totalRowPrefix` - The prefix will be automatically generated based off the value such as $ for a dollar amount would be injected without this configuration. But this allows you to pass whatever you want displayed for the bottom summary row list_parms['totalRowPrefix']['my_field'] = true `default={}`
330
-
331
- `totalRowSuffix` - The suffix will be automatically generated based off the value at the end of the last row. But this allows you to pass whatever you want displayed for the bottom summary row list_parms['totalRowSuffix']['my_field'] = true `default={}`
332
-
333
- `totalRowSeparator` - Your decimal for the formatted number (if any is shown) `default='.'`
334
-
335
- `totalRowDelimiter` - Your "comma" for the formatted number (if any is shown) `default=','`
336
-
337
- `totalRowDefault` - For any columns such as strings which cannot be summed or added into a summary this value will be the place holder for that TD. `default='N/A'`
338
-
339
- `columnHooks` - Todo `default={}`
340
-
341
- `rowHooks` - Todo `default={}`
342
-
343
-
344
- ### #1 - Add widget_list CSS and JS to your application css and js
345
-
346
- Change application.css to:
347
- ```ruby
348
- *= require widget_list
349
- *= require widgets
350
- ```
351
- Change application.js to:
352
- ```ruby
353
- //= require widget_list
354
- ```
355
- ### #2 - Run `bundle exec rails s` to have widget_list create config/widget-list.yml (by default a sqlite3 memory database is created)
356
-
357
- Configure your connection settings for your primary or secondary widget_list connections.
358
-
359
- http://sequel.rubyforge.org/rdoc/files/doc/opening_databases_rdoc.html
360
-
361
- ### #3 - If you wish to integrate into an existing rails application create a new controller
362
-
363
- rails generate controller WidgetListExamples ruby_items
364
-
365
- Then modify app/views/widget_list_examples/ruby_items.html.erb and add
366
- ```ruby
367
- <div style="margin:50px;">
368
- <%=raw @output%>
369
- </div>
370
- ```
371
- Add config/routes.rb if it is not in there:
372
- ```ruby
373
- match ':controller(/:action)'
374
- ```
375
- Ensure that sessions are loaded into active record because widget_list keeps track of several settings on each list for each session
376
- ```ruby
377
- config.session_store :active_record_store
378
- ```
379
- Add the example shown below to app/controllers/widget_list_examples_controller.rb#ruby_items
380
-
381
- Go To http://localhost:3000/widget_list_examples/ruby_items
382
-
383
- ****
384
-
385
- ### Example Calling Page That Sets up Config and calls WidgetList.render
386
-
387
- ****
388
-
389
- ```ruby
390
- #
391
- # Load Sample "items" Data. Comment out in your first time executing a widgetlist to create the items table
392
- #
393
- =begin
394
- begin
395
- WidgetList::List.get_sequel.create_table :items do
396
- primary_key :id
397
- String :name
398
- Float :price
399
- Fixnum :sku
400
- String :active
401
- Date :date_added
402
- end
403
- items = WidgetList::List.get_sequel[:items]
404
- 100.times {
405
- items.insert(:name => 'ab\'c_quoted_' + rand(35).to_s, :price => rand * 100, :date_added => '2008-02-01', :sku => rand(9999), :active => 'Yes')
406
- items.insert(:name => '12"3_' + rand(35).to_s, :price => rand * 100, :date_added => '2008-02-02', :sku => rand(9999), :active => 'Yes')
407
- items.insert(:name => 'asdf_' + rand(35).to_s, :price => rand * 100, :date_added => '2008-02-03', :sku => rand(9999), :active => 'Yes')
408
- items.insert(:name => 'qwerty_' + rand(35).to_s, :price => rand * 100, :date_added => '2008-02-04', :sku => rand(9999), :active => 'No')
409
- items.insert(:name => 'meow_' + rand(35).to_s, :price => rand * 100, :date_added => '2008-02-05', :sku => rand(9999), :active => 'No')
410
- }
411
- rescue Exception => e
412
- #
413
- # Table already exists
414
- #
415
- logger.info "Test table in items already exists? " + e.to_s
416
- end
417
- =end
418
-
419
- begin
420
-
421
- list_parms = WidgetList::List::init_config()
422
-
423
- #
424
- # Give it a name, some SQL to feed widget_list and set a noDataMessage
425
- #
426
- list_parms['name'] = 'ruby_items_yum'
427
-
428
- #
429
- # Handle Dynamic Filters
430
- #
431
- groupBy = WidgetList::List::get_group_by_selection(list_parms)
432
-
433
- case groupBy
434
- when 'Item Name'
435
- groupByFilter = 'item'
436
- countSQL = 'COUNT(1) as cnt,'
437
- groupBySQL = 'GROUP BY name'
438
- groupByDesc = ' (Grouped By Name)'
439
- when 'Sku Number'
440
- groupByFilter = 'sku'
441
- countSQL = 'COUNT(1) as cnt,'
442
- groupBySQL = 'GROUP BY sku'
443
- groupByDesc = ' (Grouped By Sku Number)'
444
- else
445
- groupByFilter = 'none'
446
- countSQL = ''
447
- groupBySQL = ''
448
- groupByDesc = ''
449
- end
450
-
451
- list_parms['filter'] = []
452
- list_parms['bindVars'] = []
453
- drillDown, filterValue = WidgetList::List::get_filter_and_drilldown(list_parms['name'])
454
-
455
- case drillDown
456
- when 'filter_by_name'
457
- list_parms['filter'] << " name = ? "
458
- list_parms['bindVars'] << filterValue
459
- list_parms['listDescription'] = WidgetList::List::drill_down_back(list_parms['name']) + ' Filtered by Name (' + filterValue + ')' + groupByDesc
460
- when 'filter_by_sku'
461
- list_parms['filter'] << " sku = ? "
462
- list_parms['bindVars'] << filterValue
463
- list_parms['listDescription'] = WidgetList::List::drill_down_back(list_parms['name']) + ' Filtered by SKU (' + filterValue + ')' + groupByDesc
464
- else
465
- list_parms['listDescription'] = ''
466
- list_parms['listDescription'] = WidgetList::List::drill_down_back(list_parms['name']) if !groupByDesc.empty?
467
- list_parms['listDescription'] += 'Showing All Ruby Items' + groupByDesc
468
- end
469
-
470
- # put <%= @output %> inside your view for initial load nothing to do here other than any custom concatenation of multiple lists
471
- #
472
- # Setup your first widget_list
473
- #
474
-
475
- button_column_name = 'actions'
476
-
477
- #
478
- # customFooter will add buttons to the bottom of the list.
479
- #
480
-
481
- list_parms['customFooter'] = WidgetList::Widgets::widget_button('Add New Item', {'page' => '/add/'} ) + WidgetList::Widgets::widget_button('Do something else', {'page' => '/else/'} )
482
-
483
- #
484
- # Give some SQL to feed widget_list and set a noDataMessage
485
- #
486
- list_parms['searchIdCol'] = ['id','sku']
487
-
488
- #
489
- # Because sku_linked column is being used and the raw SKU is hidden, we need to make this available for searching via fields_hidden
490
- #
491
- list_parms['fieldsHidden'] = ['sku']
492
-
493
- drill_downs = []
494
-
495
- drill_downs << WidgetList::List::build_drill_down( :list_id => list_parms['name'],
496
- :drill_down_name => 'filter_by_name',
497
- :data_to_pass_from_view => 'a.name',
498
- :column_to_show => 'a.name',
499
- :column_alias => 'name_linked'
500
- )
501
-
502
- drill_downs << WidgetList::List::build_drill_down(
503
- :list_id => list_parms['name'],
504
- :drill_down_name => 'filter_by_sku',
505
- :data_to_pass_from_view => 'a.sku',
506
- :column_to_show => 'a.sku',
507
- :column_alias => 'sku_linked'
508
- )
509
-
510
- list_parms['view'] = '(
511
- SELECT
512
- ' + countSQL + '
513
- ' + drill_downs.join(' , ') + ',
514
- \'\' AS checkbox,
515
- a.id AS id,
516
- a.active AS active,
517
- a.name AS name,
518
- a.sku AS sku,
519
- a.price AS price,
520
- a.date_added AS date_added
521
- FROM
522
- items a
523
- ' + groupBySQL + '
524
- ) a'
525
-
526
- #
527
- # Map out the visible fields
528
- #
529
- list_parms['fields'] = {}
530
- list_parms['fields']['checkbox'] = 'checkbox_header'
531
- list_parms['fields']['cnt'] = 'Total Items In Group' if groupByFilter != 'none'
532
- list_parms['fields']['id'] = 'Item Id' if groupByFilter == 'none'
533
- list_parms['fields']['name_linked'] = 'Name' if groupByFilter == 'none' or groupByFilter == 'item'
534
- list_parms['fields']['price'] = 'Price of Item' if groupByFilter == 'none'
535
- list_parms['fields']['sku_linked'] = 'Sku #' if groupByFilter == 'none' or groupByFilter == 'sku'
536
- list_parms['fields']['date_added'] = 'Date Added' if groupByFilter == 'none'
537
- list_parms['fields']['active'] = 'Active Item' if groupByFilter == 'none'
538
- list_parms['fields'][button_column_name] = button_column_name.capitalize if groupByFilter == 'none'
539
-
540
-
541
- list_parms['noDataMessage'] = 'No Ruby Items Found'
542
- list_parms['title'] = 'Ruby Items Using Sequel!!!'
543
-
544
- #
545
- # Create small button array and pass to the buttons key
546
- #
547
-
548
- mini_buttons = {}
549
- mini_buttons['button_edit'] = {'page' => '/edit',
550
- 'text' => 'Edit',
551
- 'function' => 'Redirect',
552
- #pass tags to pull from each column when building the URL
553
- 'tags' => {'my_key_name' => 'name','value_from_database'=>'price'}}
554
-
555
- mini_buttons['button_delete'] = {'page' => '/delete',
556
- 'text' => 'Delete',
557
- 'function' => 'alert',
558
- 'innerClass' => 'danger'}
559
- list_parms['buttons'] = {button_column_name => mini_buttons}
560
- list_parms['fieldFunction'] = {
561
- button_column_name => "''",
562
- 'date_added' => ['postgres','oracle'].include?(WidgetList::List::get_db_type) ? "TO_CHAR(date_added, 'MM/DD/YYYY')" : "date_added"
563
- }
564
-
565
- list_parms['groupByItems'] = ['All Records', 'Item Name', 'Sku Number']
566
-
567
-
568
- #
569
- # Setup a custom field for checkboxes stored into the session and reloaded when refresh occurs
570
- #
571
- list_parms = WidgetList::List.checkbox_helper(list_parms,'id')
572
-
573
- #
574
- # Generate a template for the DOWN ARROW for CUSTOM FILTER
575
- #
576
- input = {}
577
-
578
- input['id'] = 'comments'
579
- input['name'] = 'comments'
580
- input['width'] = '170'
581
- input['max_length'] = '500'
582
- input['input_class'] = 'info-input'
583
- input['title'] = 'Optional CSV list'
584
-
585
- button_search = {}
586
- button_search['onclick'] = "alert('This would search, but is not coded. That is for you to do')"
587
-
588
- list_parms['listSearchForm'] = WidgetList::Utils::fill( {
589
- '<!--BUTTON_SEARCH-->' => WidgetList::Widgets::widget_button('Search', button_search),
590
- '<!--COMMENTS-->' => WidgetList::Widgets::widget_input(input),
591
- '<!--BUTTON_CLOSE-->' => "HideAdvancedSearch(this)" } ,
592
- '
593
- <div id="advanced-search-container">
594
- <div class="widget-search-drilldown-close" onclick="<!--BUTTON_CLOSE-->">X</div>
595
- <ul class="advanced-search-container-inline" id="search_columns">
596
- <li>
597
- <div>Search Comments</div>
598
- <!--COMMENTS-->
599
- </li>
600
- </ul>
601
- <br/>
602
- <div style="text-align:right;width:100%;height:30px;" class="advanced-search-container-buttons"><!--BUTTON_RESET--><!--BUTTON_SEARCH--></div>
603
- </div>'
604
- # or to keep HTML out of controller render_to_string(:partial => 'partials/form_xxx')
605
- )
606
-
607
- #
608
- # Control widths of special fields
609
- #
610
-
611
- list_parms['columnWidth'] = {
612
- 'date_added'=>'200px',
613
- 'sku_linked'=>'20px',
614
- }
615
-
616
- #
617
- # If certain statuses of records are shown, visualize
618
- #
619
-
620
- list_parms.deep_merge!({'rowStylesByStatus' =>
621
- {'active'=>
622
- {'Yes' => '' }
623
- }
624
- })
625
- list_parms.deep_merge!({'rowStylesByStatus' =>
626
- {'active'=>
627
- {'No' => 'font-style:italic;color:red;' }
628
- }
629
- })
630
-
631
- list_parms.deep_merge!({'rowColorByStatus' =>
632
- {'active'=>
633
- {'Yes' => '' }
634
- }
635
- })
636
- list_parms.deep_merge!({'rowColorByStatus' =>
637
- {'active'=>
638
- {'No' => '#EBEBEB' }
639
- }
640
- })
641
-
642
-
643
- list_parms['columnPopupTitle'] = {}
644
- list_parms['columnPopupTitle']['checkbox'] = 'Select any record'
645
- list_parms['columnPopupTitle']['cnt'] = 'Total Count'
646
- list_parms['columnPopupTitle']['id'] = 'The primary key of the item'
647
- list_parms['columnPopupTitle']['name_linked'] = 'Name (Click to drill down)'
648
- list_parms['columnPopupTitle']['price'] = 'Price of item (not formatted)'
649
- list_parms['columnPopupTitle']['sku_linked'] = 'Sku # (Click to drill down)'
650
- list_parms['columnPopupTitle']['date_added'] = 'The date the item was added to the database'
651
- list_parms['columnPopupTitle']['active'] = 'Is the item active?'
652
-
653
- output_type, output = WidgetList::List.build_list(list_parms)
654
-
655
- case output_type
656
- when 'html'
657
- # put <%= @output %> inside your view for initial load nothing to do here other than any custom concatenation of multiple lists
658
- @output = output
659
- when 'json'
660
- return render :inline => output
661
- when 'export'
662
- send_data(output, :filename => list_parms['name'] + '.csv')
663
- return
664
- end
665
-
666
- rescue Exception => e
667
-
668
- Rails.logger.info e.to_s + "\n\n" + $!.backtrace.join("\n\n")
669
-
670
- #really this block is just to catch initial ruby errors in setting up your list_parms
671
- #I suggest taking out this rescue when going to production
672
- output_type, output = WidgetList::List.build_list(list_parms)
673
-
674
- case output_type
675
- when 'html'
676
- @output = output
677
- when 'json'
678
- return render :inline => output
679
- when 'export'
680
- send_data(output, :filename => list_parms['name'] + '.csv')
681
- return
682
- end
683
-
684
- end
685
- ```
686
-
687
- ****
688
-
689
- ## Contributing
690
-
691
- ****
692
-
693
- 1. Fork it
694
- 2. Create your feature branch (`git checkout -b my-new-feature`)
695
- 3. Commit your changes (`git commit -am 'Add some feature'`)
696
- 4. Push to the branch (`git push origin my-new-feature`)
697
- 5. Create new Pull Request
698
-
699
-
700
- Meta
701
- ----
702
-
703
- * Gems: <https://rubygems.org/gems/widget_list>
704
-
705
-
706
- Authors
707
- -------
708
-
709
- David Renne :: david_renne @ ya hoo - .com :: @phpnerd
710
-
711
- License
712
- -------
713
-
714
- Copyright 2012 David Renne
715
-
716
- Licensed under the Apache License, Version 2.0 (the "License");
717
- you may not use this file except in compliance with the License.
718
- You may obtain a copy of the License at
719
-
720
- http://www.apache.org/licenses/LICENSE-2.0
721
-
722
- Unless required by applicable law or agreed to in writing, software
723
- distributed under the License is distributed on an "AS IS" BASIS,
724
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
725
- See the License for the specific language governing permissions and
726
- limitations under the License.
727
-
728
- [1]: https://github.com/davidrenne/widget_list_example/blob/master/app/helpers/widget_list_helper.rb
1
+ # WidgetList
2
+ ====================
3
+ ****
4
+
5
+ ## Watch it in Action Here
6
+
7
+ ****
8
+
9
+ https://www.youtube.com/watch?v=A6mZa8Ge2Rk
10
+
11
+
12
+ ****
13
+
14
+ ## Introduction
15
+
16
+ ****
17
+
18
+ This is my first gem ever! It is an exciting gem because it is being used in production by a fortune 500 company. Please use and give me feedback/issues/pull requests.
19
+
20
+ ****
21
+
22
+ ## Summary
23
+
24
+ ****
25
+
26
+ I feel like there are not very good lists in ruby/rails and/or dont care to find any because nothing will compare to widget_list's implementation.
27
+
28
+ In rails you have will_paginate and other ones like it using the ActiveRecord approach, but widget_list adds some awesome treats to standard boring pagers:
29
+
30
+ * A sleek ajaxified list
31
+ * Full Blown configuration administration tool
32
+ * Supports *ALL Databases (Haven't tested everything yet though, I am sure there are tweaks for each DB). mysql, postgres, oracle and sqllite tested (basic example)
33
+ * Full sorting ASC/DESC and paging/limits of list via ajax
34
+ * Easily add row level buttons for each row
35
+ * Custom tags to pass to be replaced by actual data from each column/value
36
+ * Automatic wildcard search support as well as CSV numeric parsing of when to perform a LIKE search or an IN statement on the primary keys
37
+ * Column mappings and names
38
+ * Drill down link helper functions to allow user to click and filter the list by the particular record value
39
+ * Checkboxes for each row for custom selection and mass actions
40
+ * Session rememberance for each list/view of what was last sorted, which page the person was on, the limit and search filters
41
+ * Ability to set a custom HTML arrow which draws a hidden DIV intended for someone to put custom widgets inside of to pass new filters to the list before it executes
42
+ * Buttons for each row and areas on the bottom of the grid where you can add "Action buttons"
43
+ * Export visible data as CSV
44
+ * Grouping/Predefined report filter feature
45
+ * Either use a custom advanced searching form you build, or use the ransack dependency to build out a powerful filtering mechanism on the DOWN ARROW form users click. (See screenshots below)
46
+ * Granular control over site-wide list parameter defaults using [A WidgetList Helper][1] or by simply copying the desired partial from the gem's app/views/widget_list/list_partials into your app/views/widget_list/list_partials and modifying the template for your "site-wide template" and outer list shells
47
+ ** Support for theme plugins such as [The Blue Sky Basin Theme][2]
48
+
49
+ ****
50
+
51
+ ## Screenshots
52
+
53
+ ****
54
+
55
+ ### Main Example Loaded:
56
+
57
+ ![](http://davidrenne.com/github/widget_list/main.png)
58
+
59
+ ###Filter Drop Downs:
60
+
61
+ ![](http://davidrenne.com/github/widget_list/filtered.png)
62
+
63
+ ###Searching a row (with wild card search):
64
+
65
+ ![](http://davidrenne.com/github/widget_list/search.png)
66
+
67
+ ###Searching "name=asdf_18" (With ActiveRecord and Ransack hook):
68
+
69
+ ![](http://davidrenne.com/github/widget_list/ransack1.png)
70
+
71
+ ###Searching "name=asdf_18" and "sku<9000"(With ActiveRecord and Ransack hook):
72
+
73
+ ![](http://davidrenne.com/github/widget_list/ransack2.png)
74
+
75
+ ###Searching "name=asdf_18" and "sku < 9000" and "price > 67" (With ActiveRecord and Ransack hook):
76
+
77
+ ![](http://davidrenne.com/github/widget_list/ransack3.png)
78
+
79
+ ###Theme plugins/gem support ([The Blue Sky Basin Theme][2]):
80
+
81
+ ![](http://davidrenne.com/github/widget_list/theme_blue_sky_basin.png)
82
+
83
+ ****
84
+
85
+ ## Administration Tool
86
+
87
+ ****
88
+
89
+ In order to use this tool please paste your @output into your view
90
+
91
+ ```ruby
92
+ <div style="margin:50px;">
93
+ <%=raw @output%>
94
+ </div>
95
+ ```
96
+
97
+ And then add this to a clean controller. If you have code below, please return below the ajax
98
+
99
+ ```ruby
100
+ @output = WidgetList.go!()
101
+ return render :inline => @output if params.key?('ajax')
102
+ ```
103
+
104
+ Next you will see this interface which will build some starter code for you:
105
+
106
+ ![](http://davidrenne.com/github/widget_list/admin1.jpg)
107
+
108
+ ![](http://davidrenne.com/github/widget_list/admin2.jpg)
109
+
110
+ ![](http://davidrenne.com/github/widget_list/admin3.jpg)
111
+
112
+ ![](http://davidrenne.com/github/widget_list/admin4.jpg)
113
+
114
+ ###As you can see below, there is a preview iframe of what you are configuring:
115
+
116
+ ![](http://davidrenne.com/github/widget_list/admin5.png)
117
+
118
+ ###And finally, the code is output to get you started
119
+
120
+ ![](http://davidrenne.com/github/widget_list/admin6.png)
121
+
122
+ ****
123
+
124
+ ## Installation
125
+
126
+ ****
127
+
128
+ Add this line to your application's Gemfile:
129
+
130
+ ```ruby
131
+ gem 'widget_list'
132
+ ```
133
+ And then execute:
134
+ ```ruby
135
+ $ bundle
136
+ ```
137
+ Or install it yourself as:
138
+ ```ruby
139
+ $ gem install widget_list
140
+ ```
141
+
142
+ ****
143
+
144
+ ## Usage/Examples
145
+
146
+ ****
147
+
148
+ You can either follow the below instructions or take a look at the changes here https://github.com/davidrenne/widget_list_example/commit/e4e8ab54edcf8bc4538b1850ee762c13bc6f5316
149
+
150
+ I recommend if you use widget_list in production that you use config.consider_all_requests_local = true as errors will be handled but the base lists will still draw.
151
+
152
+
153
+ ****
154
+
155
+ ## Feature Configurations
156
+
157
+ ****
158
+
159
+ widget_list features and configurations primarily work by a single large hash passed to the constructor with the features you need for the given request which changes how the list is displayed or filtered.
160
+
161
+ `name` - The unique name/id's of all the pieces that make up your widget list `default=([*('A'..'Z'),*('0'..'9')]-%w(0 1 I O)).sample(16).join`
162
+
163
+ `database` - You can pass which DB connection you would like to use for each list. Only two values/db connections are supported ('primary' or 'secondary') `default='primary'`
164
+
165
+ `title` - This adds an H1 title and horizontal rule on top of your list `default=''`
166
+
167
+ `listDescription` - This adds a grey header box. It is useful for describing the main query `default=''`
168
+
169
+ `pageId` - Base path for requests (typically you never need to change this) `default=$_SERVER['PATH_INFO']`
170
+
171
+ `view` - A sub-select query to your database (ALWAYS ALIASED) `default=''`
172
+
173
+ `data` - A "sequel" formatted resultset like would be returned from _select() method. Instead of running a SQL query, you can pass an array to populate the list `default={}`
174
+
175
+ `colClass` - Your custom td class for all td's `default=''`
176
+
177
+ `colAlign` - td align attribute for all td's `default=''`
178
+
179
+ `fields` - The visible fields shown in the current list. KEY=column name VALUE= displayed column header `default={}`
180
+
181
+ `fieldsHidden` - The non-visible fields in the current list. Typically used when you wish to search on this column, but the main column is a drilldown or some HTML value that isnt easily searchable. VALUE=column name `default=[]`
182
+
183
+ `bindVars` - bindVars that are passed to _select() sequel extension I wrote. Which will replace "?" in your query with the associated bindVar `default=[]`
184
+
185
+ `bindVarsLegacy` - A Hash whose KEYS ARE CAPITALIZED and whose value is the replacement string. Inside the "view" you would use :MY_KEY as the template to be replaced `default={}`
186
+
187
+ `links` - Turn text based record value into a link. KEY=column name VALUE=hash of link Config. Links should most likely pass ['tags']['field_name'] = 'get_var_name' (would yeild get_var_name=1234 for that field value 1234). You can pass ['tags']['onclick'] if you dont want to call ButtonLinkPost which will redirect to the URL built. If you pass ['onclick']['tags'], each field passed will be passed as a parameter for the function you designate `default={}`
188
+
189
+ `buttons` - Buttons to generate for each row. KEY=column name VALUE=Hash of widget_button attributes `default={}`
190
+
191
+ `inputs` - widget_check is the only one supported so far. (See examples) `default={}`
192
+
193
+ `filter` - << "xxx = 123" would be the syntax to add a new filter array. (See examples) `default=[]`
194
+
195
+ `groupBy` - The column name or CSV of names to group by. (See examples) `default=[]`
196
+
197
+ `rowStart` - Which page the list should start at `default=0`
198
+
199
+ `rowLimit` - How many rows per page? `default=10`
200
+
201
+ `orderBy` - Default order by "column_name DIRECTION" `default=''`
202
+
203
+ `allowHTML` - Strip HTML from view or not `default=true`
204
+
205
+ `strlength` - Strip HTML from view or not `default=true`
206
+
207
+ `searchClear` - Clear the list's search session `default=false`
208
+
209
+ `searchClearAll` - Clear all search session for all lists `default=false`
210
+
211
+ `showPagination` - Show pagination HTML `default=true`
212
+
213
+ `searchSession` - Remember and restore the last search performed `default=true`
214
+
215
+ `carryOverRequests` - will allow you to post custom things from request to all sort/paging URLS for each ajax. Takes an array of GETVARS which will be passed to each request `default=['switch_grouping']`
216
+
217
+ `customFooter` - Add buttons or HTML at bottom area of list inside the grey box `default=''`
218
+
219
+ `customHeader` - Add buttons or HTML at top area of list above all headers (such as TABS to delineate Summary/Details) `default=''`
220
+
221
+ `ajaxFunctionAll` - Custom javascript called asychronously during each click of each event someone interacts with on the list `default=''`
222
+
223
+ `ajaxFunction` - Mostly an internal setting `default='ListJumpMin'`
224
+
225
+ `showSearch` - Show top search bar `default=true`
226
+
227
+ `searchOnkeyup` - Search on key up event `default=''`
228
+
229
+ `searchOnclick` - Search on click event `default=''`
230
+
231
+ `searchIdCol` - By default `id` column is here because typically if you call your PK's id and are auto-increment and numeric. This can also take in an array of numeric fields so that users can search CSV's of numbers and get back matches `default='id'`
232
+
233
+ `searchTitle` - Set a title for the search input `default= 'Search by Id or a list of Ids and more'`
234
+
235
+ `searchFieldsIn` - White list of fields to include in a alpha-numeric based like '%%' search `default={}`
236
+
237
+ `searchFieldsOut` - Black list of fields to exclude in a alpha-numeric based search `default={'id'=>true}`
238
+
239
+ `showExport` - Allow users to export current list view as CSV `default=true`
240
+
241
+ `exportButtonTitle` - Title of button `default='Export CSV'`
242
+
243
+ `groupByItems` - Custom drop down's created by passing an array of modes. Best suited to group by the data `default=[]`
244
+
245
+ `groupBySelected` - Initially selected grouping - defaults to first in list if not. Please pass the string value of the "groupByItem" `default=false`
246
+
247
+ `groupByLabel` - Label describing select box `default='Group By'`
248
+
249
+ `groupByClick` - Function to call as a custom function for each click on an item `default=''`
250
+
251
+ `groupByClickDefault` - Default group by handler inside widget_list.js `default="ListChangeGrouping('<!--NAME-->', this);"`
252
+
253
+ `listSearchForm` - Allows you to pass a custom form for the ARROW drop down for advanced searching `default=''`
254
+
255
+ `ransackSearch` - If you pass ModelName.search(params[:q]) ransack will show up in your advanced search `default=false`
256
+
257
+ `cornerRadius` - Either int number of pixels for radius corners. Or '14px' or whatever you want. `default=15`
258
+
259
+ `columnStyle` - Column styles. KEY=column name VALUE= the inline style applied `default={}`
260
+
261
+ `columnClass` - Column class. KEY=column name VALUE= the class name `default={}`
262
+
263
+ `columnPopupTitle` - Column title as you hover over. KEY=column name VALUE=Popup text `default={}`
264
+
265
+ `columnWidth` - Column widths. KEY=column name VALUE= '100px' `default={}`
266
+
267
+ `columnNoSort` - Dont allow sorting on these columns (By default all visible columns have a sort link built). KEY=column name VALUE=column name `default={}`
268
+
269
+ `borderedColumns` - Add a right border to each column. `default=false`
270
+
271
+ `borderedRows` - Style the border of each row. `default=false`
272
+
273
+ `borderRowStyle` - Border style of each row. `default='1px solid #CCCCCC'`
274
+
275
+ `borderHeadFoot` - Style the border of header (bottom) and footer (top). `default=false`
276
+
277
+ `headFootBorderStyle` - Border style of header (bottom) and footer (top). `default='1px solid #CCCCCC'`
278
+
279
+ `borderColumnStyle` - Style of row if you use this above feature. `default='1px solid #CCCCCC'`
280
+
281
+ `bordersEverywhere?` - If true, use borderEverywhere for all four borders you can pass separately `default=false`
282
+
283
+ `borderEverywhere` - The catch all style of borders for headers, rows, outer table border and columns. `default='1px solid #CCCCCC'`
284
+
285
+ `defaultButtonClass` - As you have seen in many screenshots, there are several buttons. This controls the innerClass of those drawn from the list. See lib/widget_list/widgets.rb `default='info'`
286
+
287
+ `useBoxShadow` - Show shadow or not on list `default=true`
288
+
289
+ `shadowInset` - Number or string with '11Px' for an 11PX Inset `default=10`
290
+
291
+ `shadowSpread` - Number or string with '11Px' for an 11PX spread `default=20`
292
+
293
+ `shadowColor` - Color of bottom right shadow `default='shadowColor'`
294
+
295
+ `rowClass` - Class added to all rows `default=''`
296
+
297
+ `rowFontColor` - Font color of all data rows that dont have a rowStylesByStatus color: passed to it `default='black'`
298
+
299
+ `rowColorByStatus` - {'rowColorByStatus' =>
300
+ {'active'=>
301
+ {'No' => '#EBEBEB' }
302
+ }
303
+ }
304
+ Color a row based on the value of the column.
305
+ `default={}`
306
+
307
+ `rowStylesByStatus` - {'rowStylesByStatus' =>
308
+ {'active'=>
309
+ {'No' => 'font-style:italic;color:red;' }
310
+ }
311
+ }
312
+ Style a row based on the value of the column.
313
+ `default={}`
314
+
315
+ `rowOffsets` - Color for each row and offset `default=['FFFFFF','FFFFFF']`
316
+
317
+ `noDataMessage` - Message to show when no data is found `default='Currently no data.'`
318
+
319
+ `useSort` - Allow sorting on list `default=true`
320
+
321
+ `headerClass` - Class of each individual header column `default={}`
322
+
323
+ `fieldFunction` - A way to wrap or inject columns or SQL formatting in place of your columns `default={}`
324
+
325
+ `template` - Pass in a custom template for outer shell `default=''`
326
+
327
+ `templateFilter` - Instead of widget list building your search box. Pass your own HTML `default=''`
328
+
329
+ `storeSessionChecks` - See http://stackoverflow.com/questions/1928204/marshal-data-too-short for configuring larger session storage which checkboxes would eat up if you had this set to true `default=false`
330
+
331
+ `totalRow` - Add in your numeric or dollar amount fields you want to sum or average for the bottom record list_parms['totalRow']['my_field'] = true `default={}`
332
+
333
+ `totalRowFirstCol` - A string to display what the row is showing `default='<strong>Total:</strong>'`
334
+
335
+ `totalRowMethod` - Allows you to pass 'average' to define which columns should average the sum list_parms['totalRowPrefix']['my_field'] = 'average'. There is only support for average right now `default={}`
336
+
337
+ `totalRowPrefix` - The prefix will be automatically generated based off the value such as $ for a dollar amount would be injected without this configuration. But this allows you to pass whatever you want displayed for the bottom summary row list_parms['totalRowPrefix']['my_field'] = true `default={}`
338
+
339
+ `totalRowSuffix` - The suffix will be automatically generated based off the value at the end of the last row. But this allows you to pass whatever you want displayed for the bottom summary row list_parms['totalRowSuffix']['my_field'] = true `default={}`
340
+
341
+ `totalRowSeparator` - Your decimal for the formatted number (if any is shown) `default='.'`
342
+
343
+ `totalRowDelimiter` - Your "comma" for the formatted number (if any is shown) `default=','`
344
+
345
+ `totalRowDefault` - For any columns such as strings which cannot be summed or added into a summary this value will be the place holder for that TD. `default='N/A'`
346
+
347
+ `columnHooks` - Todo `default={}`
348
+
349
+ `rowHooks` - Todo `default={}`
350
+
351
+
352
+ ### #1 - Add widget_list CSS and JS to your application css and js
353
+
354
+ Change application.css to:
355
+ ```ruby
356
+ *= require widget_list
357
+ *= require widgets
358
+ ```
359
+ Change application.js to:
360
+ ```ruby
361
+ //= require widget_list
362
+ ```
363
+ ### #2 - Run `bundle exec rails s` to have widget_list create config/widget-list.yml (by default a sqlite3 memory database is created)
364
+
365
+ Configure your connection settings for your primary or secondary widget_list connections.
366
+
367
+ http://sequel.rubyforge.org/rdoc/files/doc/opening_databases_rdoc.html
368
+
369
+ ### #3 - If you wish to integrate into an existing rails application create a new controller
370
+
371
+ rails generate controller WidgetListExamples ruby_items
372
+
373
+ Then modify app/views/widget_list_examples/ruby_items.html.erb and add
374
+ ```ruby
375
+ <div style="margin:50px;">
376
+ <%=raw @output%>
377
+ </div>
378
+ ```
379
+ Add config/routes.rb if it is not in there:
380
+ ```ruby
381
+ match ':controller(/:action)'
382
+ ```
383
+ Ensure that sessions are loaded into active record because widget_list keeps track of several settings on each list for each session
384
+ ```ruby
385
+ config.session_store :active_record_store
386
+ ```
387
+ Add the example shown below to app/controllers/widget_list_examples_controller.rb#ruby_items
388
+
389
+ Go To http://localhost:3000/widget_list_examples/ruby_items
390
+
391
+ ****
392
+
393
+ ### Example Calling Page That Sets up Config and calls WidgetList.render
394
+
395
+ ****
396
+
397
+ ```ruby
398
+ #
399
+ # Load Sample "items" Data. Comment out in your first time executing a widgetlist to create the items table
400
+ #
401
+ =begin
402
+ begin
403
+ WidgetList::List.get_sequel.create_table :items do
404
+ primary_key :id
405
+ String :name
406
+ Float :price
407
+ Fixnum :sku
408
+ String :active
409
+ Date :date_added
410
+ end
411
+ items = WidgetList::List.get_sequel[:items]
412
+ 100.times {
413
+ items.insert(:name => 'ab\'c_quoted_' + rand(35).to_s, :price => rand * 100, :date_added => '2008-02-01', :sku => rand(9999), :active => 'Yes')
414
+ items.insert(:name => '12"3_' + rand(35).to_s, :price => rand * 100, :date_added => '2008-02-02', :sku => rand(9999), :active => 'Yes')
415
+ items.insert(:name => 'asdf_' + rand(35).to_s, :price => rand * 100, :date_added => '2008-02-03', :sku => rand(9999), :active => 'Yes')
416
+ items.insert(:name => 'qwerty_' + rand(35).to_s, :price => rand * 100, :date_added => '2008-02-04', :sku => rand(9999), :active => 'No')
417
+ items.insert(:name => 'meow_' + rand(35).to_s, :price => rand * 100, :date_added => '2008-02-05', :sku => rand(9999), :active => 'No')
418
+ }
419
+ rescue Exception => e
420
+ #
421
+ # Table already exists
422
+ #
423
+ logger.info "Test table in items already exists? " + e.to_s
424
+ end
425
+ =end
426
+
427
+ begin
428
+
429
+ list_parms = WidgetList::List::init_config()
430
+
431
+ #
432
+ # Give it a name, some SQL to feed widget_list and set a noDataMessage
433
+ #
434
+ list_parms['name'] = 'ruby_items_yum'
435
+
436
+ #
437
+ # Handle Dynamic Filters
438
+ #
439
+ groupBy = WidgetList::List::get_group_by_selection(list_parms)
440
+
441
+ case groupBy
442
+ when 'Item Name'
443
+ groupByFilter = 'item'
444
+ countSQL = 'COUNT(1) as cnt,'
445
+ groupBySQL = 'GROUP BY name'
446
+ groupByDesc = ' (Grouped By Name)'
447
+ when 'Sku Number'
448
+ groupByFilter = 'sku'
449
+ countSQL = 'COUNT(1) as cnt,'
450
+ groupBySQL = 'GROUP BY sku'
451
+ groupByDesc = ' (Grouped By Sku Number)'
452
+ else
453
+ groupByFilter = 'none'
454
+ countSQL = ''
455
+ groupBySQL = ''
456
+ groupByDesc = ''
457
+ end
458
+
459
+ list_parms['filter'] = []
460
+ list_parms['bindVars'] = []
461
+ drillDown, filterValue = WidgetList::List::get_filter_and_drilldown(list_parms['name'])
462
+
463
+ case drillDown
464
+ when 'filter_by_name'
465
+ list_parms['filter'] << " name = ? "
466
+ list_parms['bindVars'] << filterValue
467
+ list_parms['listDescription'] = WidgetList::List::drill_down_back(list_parms['name']) + ' Filtered by Name (' + filterValue + ')' + groupByDesc
468
+ when 'filter_by_sku'
469
+ list_parms['filter'] << " sku = ? "
470
+ list_parms['bindVars'] << filterValue
471
+ list_parms['listDescription'] = WidgetList::List::drill_down_back(list_parms['name']) + ' Filtered by SKU (' + filterValue + ')' + groupByDesc
472
+ else
473
+ list_parms['listDescription'] = ''
474
+ list_parms['listDescription'] = WidgetList::List::drill_down_back(list_parms['name']) if !groupByDesc.empty?
475
+ list_parms['listDescription'] += 'Showing All Ruby Items' + groupByDesc
476
+ end
477
+
478
+ # put <%= @output %> inside your view for initial load nothing to do here other than any custom concatenation of multiple lists
479
+ #
480
+ # Setup your first widget_list
481
+ #
482
+
483
+ button_column_name = 'actions'
484
+
485
+ #
486
+ # customFooter will add buttons to the bottom of the list.
487
+ #
488
+
489
+ list_parms['customFooter'] = WidgetList::Widgets::widget_button('Add New Item', {'page' => '/add/'} ) + WidgetList::Widgets::widget_button('Do something else', {'page' => '/else/'} )
490
+
491
+ #
492
+ # Give some SQL to feed widget_list and set a noDataMessage
493
+ #
494
+ list_parms['searchIdCol'] = ['id','sku']
495
+
496
+ #
497
+ # Because sku_linked column is being used and the raw SKU is hidden, we need to make this available for searching via fields_hidden
498
+ #
499
+ list_parms['fieldsHidden'] = ['sku']
500
+
501
+ drill_downs = []
502
+
503
+ drill_downs << WidgetList::List::build_drill_down( :list_id => list_parms['name'],
504
+ :drill_down_name => 'filter_by_name',
505
+ :data_to_pass_from_view => 'a.name',
506
+ :column_to_show => 'a.name',
507
+ :column_alias => 'name_linked'
508
+ )
509
+
510
+ drill_downs << WidgetList::List::build_drill_down(
511
+ :list_id => list_parms['name'],
512
+ :drill_down_name => 'filter_by_sku',
513
+ :data_to_pass_from_view => 'a.sku',
514
+ :column_to_show => 'a.sku',
515
+ :column_alias => 'sku_linked'
516
+ )
517
+
518
+ list_parms['view'] = '(
519
+ SELECT
520
+ ' + countSQL + '
521
+ ' + drill_downs.join(' , ') + ',
522
+ \'\' AS checkbox,
523
+ a.id AS id,
524
+ a.active AS active,
525
+ a.name AS name,
526
+ a.sku AS sku,
527
+ a.price AS price,
528
+ a.date_added AS date_added
529
+ FROM
530
+ items a
531
+ ' + groupBySQL + '
532
+ ) a'
533
+
534
+ #
535
+ # Map out the visible fields
536
+ #
537
+ list_parms['fields'] = {}
538
+ list_parms['fields']['checkbox'] = 'checkbox_header'
539
+ list_parms['fields']['cnt'] = 'Total Items In Group' if groupByFilter != 'none'
540
+ list_parms['fields']['id'] = 'Item Id' if groupByFilter == 'none'
541
+ list_parms['fields']['name_linked'] = 'Name' if groupByFilter == 'none' or groupByFilter == 'item'
542
+ list_parms['fields']['price'] = 'Price of Item' if groupByFilter == 'none'
543
+ list_parms['fields']['sku_linked'] = 'Sku #' if groupByFilter == 'none' or groupByFilter == 'sku'
544
+ list_parms['fields']['date_added'] = 'Date Added' if groupByFilter == 'none'
545
+ list_parms['fields']['active'] = 'Active Item' if groupByFilter == 'none'
546
+ list_parms['fields'][button_column_name] = button_column_name.capitalize if groupByFilter == 'none'
547
+
548
+
549
+ list_parms['noDataMessage'] = 'No Ruby Items Found'
550
+ list_parms['title'] = 'Ruby Items Using Sequel!!!'
551
+
552
+ #
553
+ # Create small button array and pass to the buttons key
554
+ #
555
+
556
+ mini_buttons = {}
557
+ mini_buttons['button_edit'] = {'page' => '/edit',
558
+ 'text' => 'Edit',
559
+ 'function' => 'Redirect',
560
+ #pass tags to pull from each column when building the URL
561
+ 'tags' => {'my_key_name' => 'name','value_from_database'=>'price'}}
562
+
563
+ mini_buttons['button_delete'] = {'page' => '/delete',
564
+ 'text' => 'Delete',
565
+ 'function' => 'alert',
566
+ 'innerClass' => 'danger'}
567
+ list_parms['buttons'] = {button_column_name => mini_buttons}
568
+ list_parms['fieldFunction'] = {
569
+ button_column_name => "''",
570
+ 'date_added' => ['postgres','oracle'].include?(WidgetList::List::get_db_type) ? "TO_CHAR(date_added, 'MM/DD/YYYY')" : "date_added"
571
+ }
572
+
573
+ list_parms['groupByItems'] = ['All Records', 'Item Name', 'Sku Number']
574
+
575
+
576
+ #
577
+ # Setup a custom field for checkboxes stored into the session and reloaded when refresh occurs
578
+ #
579
+ list_parms = WidgetList::List.checkbox_helper(list_parms,'id')
580
+
581
+ #
582
+ # Generate a template for the DOWN ARROW for CUSTOM FILTER
583
+ #
584
+ input = {}
585
+
586
+ input['id'] = 'comments'
587
+ input['name'] = 'comments'
588
+ input['width'] = '170'
589
+ input['max_length'] = '500'
590
+ input['input_class'] = 'info-input'
591
+ input['title'] = 'Optional CSV list'
592
+
593
+ button_search = {}
594
+ button_search['onclick'] = "alert('This would search, but is not coded. That is for you to do')"
595
+
596
+ list_parms['listSearchForm'] = WidgetList::Utils::fill( {
597
+ '<!--BUTTON_SEARCH-->' => WidgetList::Widgets::widget_button('Search', button_search),
598
+ '<!--COMMENTS-->' => WidgetList::Widgets::widget_input(input),
599
+ '<!--BUTTON_CLOSE-->' => "HideAdvancedSearch(this)" } ,
600
+ '
601
+ <div id="advanced-search-container">
602
+ <div class="widget-search-drilldown-close" onclick="<!--BUTTON_CLOSE-->">X</div>
603
+ <ul class="advanced-search-container-inline" id="search_columns">
604
+ <li>
605
+ <div>Search Comments</div>
606
+ <!--COMMENTS-->
607
+ </li>
608
+ </ul>
609
+ <br/>
610
+ <div style="text-align:right;width:100%;height:30px;" class="advanced-search-container-buttons"><!--BUTTON_RESET--><!--BUTTON_SEARCH--></div>
611
+ </div>'
612
+ # or to keep HTML out of controller render_to_string(:partial => 'partials/form_xxx')
613
+ )
614
+
615
+ #
616
+ # Control widths of special fields
617
+ #
618
+
619
+ list_parms['columnWidth'] = {
620
+ 'date_added'=>'200px',
621
+ 'sku_linked'=>'20px',
622
+ }
623
+
624
+ #
625
+ # If certain statuses of records are shown, visualize
626
+ #
627
+
628
+ list_parms.deep_merge!({'rowStylesByStatus' =>
629
+ {'active'=>
630
+ {'Yes' => '' }
631
+ }
632
+ })
633
+ list_parms.deep_merge!({'rowStylesByStatus' =>
634
+ {'active'=>
635
+ {'No' => 'font-style:italic;color:red;' }
636
+ }
637
+ })
638
+
639
+ list_parms.deep_merge!({'rowColorByStatus' =>
640
+ {'active'=>
641
+ {'Yes' => '' }
642
+ }
643
+ })
644
+ list_parms.deep_merge!({'rowColorByStatus' =>
645
+ {'active'=>
646
+ {'No' => '#EBEBEB' }
647
+ }
648
+ })
649
+
650
+
651
+ list_parms['columnPopupTitle'] = {}
652
+ list_parms['columnPopupTitle']['checkbox'] = 'Select any record'
653
+ list_parms['columnPopupTitle']['cnt'] = 'Total Count'
654
+ list_parms['columnPopupTitle']['id'] = 'The primary key of the item'
655
+ list_parms['columnPopupTitle']['name_linked'] = 'Name (Click to drill down)'
656
+ list_parms['columnPopupTitle']['price'] = 'Price of item (not formatted)'
657
+ list_parms['columnPopupTitle']['sku_linked'] = 'Sku # (Click to drill down)'
658
+ list_parms['columnPopupTitle']['date_added'] = 'The date the item was added to the database'
659
+ list_parms['columnPopupTitle']['active'] = 'Is the item active?'
660
+
661
+ output_type, output = WidgetList::List.build_list(list_parms)
662
+
663
+ case output_type
664
+ when 'html'
665
+ # put <%= @output %> inside your view for initial load nothing to do here other than any custom concatenation of multiple lists
666
+ @output = output
667
+ when 'json'
668
+ return render :inline => output
669
+ when 'export'
670
+ send_data(output, :filename => list_parms['name'] + '.csv')
671
+ return
672
+ end
673
+
674
+ rescue Exception => e
675
+
676
+ Rails.logger.info e.to_s + "\n\n" + $!.backtrace.join("\n\n")
677
+
678
+ #really this block is just to catch initial ruby errors in setting up your list_parms
679
+ #I suggest taking out this rescue when going to production
680
+ output_type, output = WidgetList::List.build_list(list_parms)
681
+
682
+ case output_type
683
+ when 'html'
684
+ @output = output
685
+ when 'json'
686
+ return render :inline => output
687
+ when 'export'
688
+ send_data(output, :filename => list_parms['name'] + '.csv')
689
+ return
690
+ end
691
+
692
+ end
693
+ ```
694
+
695
+ ****
696
+
697
+ ## Contributing
698
+
699
+ ****
700
+
701
+ 1. Fork it
702
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
703
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
704
+ 4. Push to the branch (`git push origin my-new-feature`)
705
+ 5. Create new Pull Request
706
+
707
+
708
+ Meta
709
+ ----
710
+
711
+ * Gems: <https://rubygems.org/gems/widget_list>
712
+
713
+
714
+ Authors
715
+ -------
716
+
717
+ David Renne :: david_renne @ ya hoo - .com :: @phpnerd
718
+
719
+ License
720
+ -------
721
+
722
+ Copyright 2012 David Renne
723
+
724
+ Licensed under the Apache License, Version 2.0 (the "License");
725
+ you may not use this file except in compliance with the License.
726
+ You may obtain a copy of the License at
727
+
728
+ http://www.apache.org/licenses/LICENSE-2.0
729
+
730
+ Unless required by applicable law or agreed to in writing, software
731
+ distributed under the License is distributed on an "AS IS" BASIS,
732
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
733
+ See the License for the specific language governing permissions and
734
+ limitations under the License.
735
+
736
+ [1]: https://github.com/davidrenne/widget_list_example/blob/master/app/helpers/widget_list_helper.rb
729
737
  [2]: https://github.com/davidrenne/widget_list_theme_blue_sky_basin