widget_list 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
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
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in widget_list.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +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
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,260 @@
1
+ widget_list
2
+ ====================
3
+ # WidgetList
4
+
5
+ ## Introduction
6
+
7
+ This is my first gem ever!
8
+
9
+ 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.
10
+
11
+ 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:
12
+
13
+ * A sleek ajaxified list
14
+ * Full sorting
15
+ * Search bar/Ajax searching
16
+ * Column mappings
17
+ * Buttons for each row and areas on the bottom of the grid where you can add "Action buttons" like Add R
18
+
19
+
20
+ ## Installation
21
+
22
+ Add this line to your application's Gemfile:
23
+
24
+ gem 'widget_list'
25
+
26
+ And then execute:
27
+
28
+ $ bundle
29
+
30
+ Or install it yourself as:
31
+
32
+ $ gem install widget_list
33
+
34
+ ## Usage
35
+
36
+ ### #1 - Add widget_list CSS and JS to your application css and js
37
+
38
+ Change application.css to:
39
+
40
+ *= require widget_list
41
+ *= require widgets
42
+
43
+ Change application.js to:
44
+
45
+ //= require widget_list
46
+
47
+ ### #2 - Run bundle exec rails s to have widget_list create config/widget-list.yml
48
+
49
+ Change application.css to:
50
+
51
+ *= require widget_list
52
+ *= require widgets
53
+
54
+ Change application.js to:
55
+
56
+ //= require widget_list
57
+
58
+ ### Example Calling Page That Sets up Config and calls WidgetList.render
59
+
60
+ #
61
+ # Load Sample "items" Data. Comment out in your first time executing a widgetlist to create the items table
62
+ #
63
+
64
+ # no table - create it and load it with 5K records
65
+ WidgetList::List.get_database.create_table :items do
66
+ primary_key :id
67
+ String :name
68
+ Float :price
69
+ end
70
+ items = WidgetList::List.get_database[:items]
71
+ 100.times {
72
+ items.insert(:name => 'abc', :price => rand * 100)
73
+ items.insert(:name => '123', :price => rand * 100)
74
+ items.insert(:name => 'asdf', :price => rand * 100)
75
+ items.insert(:name => 'qwerty', :price => rand * 100)
76
+ items.insert(:name => 'poop', :price => rand * 100)
77
+ }
78
+
79
+
80
+ #
81
+ # Setup your first widget_list
82
+ #
83
+
84
+ button_column_name = 'actions'
85
+ list_parms = {}
86
+
87
+ #
88
+ # action_buttons will add buttons to the bottom of the list.
89
+ #
90
+
91
+ action_buttons = WidgetList::Widgets::widget_button('Add New Item', {'page' => '/add/'} ) + WidgetList::Widgets::widget_button('Do something else', {'page' => '/else/'} )
92
+
93
+ #
94
+ # Give it a name, some SQL to feed widget_list and set a noDataMessage
95
+ #
96
+ list_parms['name'] = 'ruby_items_yum'
97
+ list_parms['view'] = '(SELECT \'\' as checkbox,a.* FROM items a ) a'
98
+ list_parms['noDataMessage'] = 'No Tables Found'
99
+ list_parms['title'] = 'Ruby Items!!!'
100
+
101
+ #
102
+ # Create small button array and pass to the buttons key
103
+ #
104
+
105
+ mini_buttons = {}
106
+ mini_buttons['button_edit'] = {'page' => '/edit',
107
+ 'text' => 'Edit',
108
+ 'function' => 'Redirect',
109
+ #pass tags to pull from each column when building the URL
110
+ 'tags' => {'my_key_name' => 'name','value_from_database'=>'price'}}
111
+
112
+ mini_buttons['button_delete'] = {'page' => '/delete',
113
+ 'text' => 'Delete',
114
+ 'function' => 'alert',
115
+ 'innerClass' => 'danger'}
116
+ list_parms['buttons'] = {button_column_name => mini_buttons}
117
+ list_parms['function'] = {button_column_name => "'' " + button_column_name }
118
+ list_parms['groupByItems']= ['All Records','Another Grouping Item']
119
+
120
+ #
121
+ # Generate a template for the DOWN ARROW for CUSTOM FILTER
122
+ #
123
+
124
+ template = {}
125
+ input = {}
126
+
127
+ input['id'] = 'comments'
128
+ input['name'] = 'comments'
129
+ input['width'] = '170'
130
+ input['max_length'] = '500'
131
+ input['input_class'] = 'info-input'
132
+ input['title'] = 'Optional CSV list'
133
+
134
+ button_search = {}
135
+ button_search['innerClass'] = "success btn-submit"
136
+ button_search['onclick'] = "alert('This would search, but is not coded. That is for you to do')"
137
+
138
+ list_parms['list_search_form'] = WidgetList::Utils::fill( {
139
+ '<!--COMMENTS-->' => WidgetList::Widgets::widget_input(input),
140
+ '<!--BUTTON_SEARCH-->' => WidgetList::Widgets::widget_button('Search', button_search),
141
+ '<!--BUTTON_CLOSE-->' => "HideAdvancedSearch(this)" } ,
142
+ '
143
+ <div id="advanced-search-container">
144
+ <div class="widget-search-drilldown-close" onclick="<!--BUTTON_CLOSE-->">X</div>
145
+ <ul class="advanced-search-container-inline" id="search_columns">
146
+ <li>
147
+ <div>Search Comments</div>
148
+ <!--COMMENTS-->
149
+ </li>
150
+ </ul>
151
+ <br/>
152
+ <div style="text-align:right;width:100%;height:30px;" class="advanced-search-container-buttons"><!--BUTTON_RESET--><!--BUTTON_SEARCH--></div>
153
+ </div>')
154
+
155
+ #
156
+ # Setup a custom field for checkboxes stored into the session and reloaded when refresh occurs
157
+ #
158
+
159
+ list_parms.deep_merge!({'fields' =>
160
+ {
161
+ 'checkbox'=> 'checkbox_header',
162
+ 'id'=> 'Item Id',
163
+ 'name'=> 'Name',
164
+ 'price'=> 'Price of Item',
165
+ button_column_name => button_column_name.capitalize,
166
+ }
167
+ })
168
+
169
+ list_parms.deep_merge!({'inputs' =>
170
+ {'checkbox'=>
171
+ {'type' => 'checkbox'
172
+ }
173
+ }
174
+ })
175
+
176
+ list_parms.deep_merge!({'inputs' =>
177
+ {'checkbox'=>
178
+ {'items' =>
179
+ {
180
+ 'name' => 'visible_checks[]',
181
+ 'value' => 'id', #the value should be a column name mapping
182
+ 'class_handle' => 'info_tables',
183
+ }
184
+ }
185
+ }
186
+ })
187
+
188
+ list_parms.deep_merge!({'inputs' =>
189
+ {'checkbox_header'=>
190
+ {'type' => 'checkbox'
191
+ }
192
+ }
193
+ })
194
+
195
+ list_parms.deep_merge!({'inputs' =>
196
+ {'checkbox_header'=>
197
+ {'items' =>
198
+ {
199
+ 'check_all' => true,
200
+ 'id' => 'info_tables_check_all',
201
+ 'class_handle' => 'info_tables',
202
+ }
203
+ }
204
+ }
205
+ })
206
+
207
+ list = WidgetList::List.new(list_parms)
208
+
209
+ #
210
+ # If AJAX, send back JSON
211
+ #
212
+ if $_REQUEST.key?('BUTTON_VALUE') && $_REQUEST['LIST_NAME'] == list_parms['name']
213
+ ret = {}
214
+ ret['list'] = WidgetList::Utils::fill({ '<!--CUSTOM_CONTENT-->' => action_buttons } , list.render() )
215
+ ret['list_id'] = list_parms['name']
216
+ ret['callback'] = 'ListSearchAheadResponse'
217
+ return render :inline => WidgetList::Utils::json_encode(ret)
218
+ else
219
+ #
220
+ # Else assign to variable for view
221
+ #
222
+ @output = WidgetList::Utils::fill({ '<!--CUSTOM_CONTENT-->' => action_buttons } , list.render() )
223
+ end
224
+
225
+ ## Contributing
226
+
227
+ 1. Fork it
228
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
229
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
230
+ 4. Push to the branch (`git push origin my-new-feature`)
231
+ 5. Create new Pull Request
232
+
233
+
234
+ Meta
235
+ ----
236
+
237
+ * Gems: <http://rubygems.org/gems/widget-list>
238
+
239
+
240
+ Authors
241
+ -------
242
+
243
+ David Renne :: david_renne @ ya hoo - .com :: @phpnerd
244
+
245
+ License
246
+ -------
247
+
248
+ Copyright 2012 David Renne
249
+
250
+ Licensed under the Apache License, Version 2.0 (the "License");
251
+ you may not use this file except in compliance with the License.
252
+ You may obtain a copy of the License at
253
+
254
+ http://www.apache.org/licenses/LICENSE-2.0
255
+
256
+ Unless required by applicable law or agreed to in writing, software
257
+ distributed under the License is distributed on an "AS IS" BASIS,
258
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
259
+ See the License for the specific language governing permissions and
260
+ limitations under the License.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,2054 @@
1
+ require 'widget_list/sequel'
2
+ require 'widget_list/version'
3
+ require 'widget_list/hash'
4
+ require 'widget_list/string'
5
+ require 'widget_list/utils'
6
+ require 'widget_list/tpl'
7
+ require 'widget_list/widgets'
8
+ require 'widget_list/railtie'
9
+ require 'json'
10
+ require 'uri'
11
+ require 'extensions/action_controller_base'
12
+ require 'sequel'
13
+
14
+
15
+ module WidgetList
16
+
17
+ if defined?(Rails) && defined?(Rails::Engine)
18
+ class Engine < ::Rails::Engine
19
+ require 'widget_list/engine'
20
+ end
21
+ end
22
+
23
+ class List
24
+
25
+ @debug = true
26
+
27
+ include ActionView::Helpers::SanitizeHelper
28
+
29
+ def self.connect
30
+
31
+ if Rails.root.join("config", "widget-list.yml").file?
32
+ config = YAML.load(ERB.new(File.new(Rails.root.join("config", "widget-list.yml")).read).result)[Rails.env]
33
+ @primary_conn = config[:primary]
34
+ @secondary_conn = config[:secondary]
35
+ else
36
+ throw 'widget-list.yml not found'
37
+ end
38
+
39
+ $DATABASE = Sequel.connect(@primary_conn) if @primary_conn.class.name == 'String'
40
+ $DATABASE2 = Sequel.connect(@secondary_conn) if @secondary_conn.class.name == 'String'
41
+
42
+ end
43
+
44
+ def self.get_database
45
+ case $current_db_selection
46
+ when 'primary'
47
+ $DATABASE
48
+ when 'secondary'
49
+ $DATABASE2
50
+ else
51
+ $DATABASE
52
+ end
53
+ end
54
+
55
+ # @param [Hash] list
56
+ def initialize(list={})
57
+
58
+ @items = {
59
+ 'name' => ([*('A'..'Z'),*('0'..'9')]-%w(0 1 I O)).sample(16).join,
60
+ 'database' => 'primary',
61
+ 'title' => '',# will add <h1> title and horizontal rule
62
+ 'listDescription' => '',# will add grey header box
63
+ 'pageId' => $_SERVER['PATH_INFO'],
64
+ 'sql' => '',
65
+ 'table' => '',
66
+ 'view' => '',
67
+ 'data' => {},
68
+ 'mode' => 'passive',
69
+ 'collClass' => '',
70
+ 'collAlign' => '',
71
+ 'fields' => {},
72
+ 'columns' => {},
73
+ 'bindVars' => [],
74
+ 'bindVarsLegacy' => {},
75
+ 'links' => {},
76
+ 'results' => {},
77
+ 'buttons' => {},
78
+ 'inputs' => {},
79
+ 'filter' => '',
80
+ 'rowStart' => 0,
81
+ 'rowLimit' => 10,
82
+ 'orderBy' => '',
83
+ 'allowHTML' => true,
84
+ 'strlength' => 30,
85
+ 'searchClear' => false, # build a custom conditional for each page to clear session
86
+ 'searchClearAll' => false, # build a custom conditional for each page to clear session
87
+ 'showPagination' => true,
88
+ 'searchSession' => true, #on list render use last filter
89
+
90
+ #
91
+ # Custom count query
92
+ #
93
+ 'force_count_sql' => '',
94
+ 'force_query_sql' => '',
95
+
96
+ #
97
+ # Counts
98
+ #
99
+ 'count_cache_time' => 180, #
100
+ 'cachedCount' => -1, #pass the count
101
+
102
+ #
103
+ # Ajax
104
+ #
105
+ 'ajax_action' => '',
106
+ 'ajax_function' => 'ListJumpMin',
107
+ 'ajax_search_function'=> 'ListJumpMin',
108
+
109
+ #
110
+ # Search
111
+ #
112
+ 'showSearch' => true,
113
+ 'searchOnkeyup' => '',
114
+ 'searchOnclick' => '',
115
+ 'searchIdCol' => 'id', #By default `id` column is here because typically if you call your PK's id and are auto-increment
116
+ 'searchInputLegacyCSS'=> false,
117
+ 'searchBtnName' => 'Search by Id or a list of Ids and more',
118
+ 'searchTitle' => '',
119
+ 'searchFieldsIn' => {}, #White list of fields to include in a alpha-numeric based search
120
+ 'searchFieldsOut' => {'id'=>true}, #Black list of fields to include in a alpha-numeric based search (default `id` to NEVER search when alpha seach)
121
+
122
+
123
+ #
124
+ # Group By Box
125
+ #
126
+ 'groupByItems' => [], #array of strings (each a new "select option")
127
+ 'groupBySelected' => false, #initially selected grouping - defaults to first in list if not
128
+ 'groupByLabel' => 'Group By',
129
+
130
+
131
+ #
132
+ # Advanced searching
133
+ #
134
+ 'list_search_form' => '', #The HTML form used for the advanced search drop down
135
+ 'list_search_attribs' => {}, #widgetinput "search_ahead" attributes
136
+
137
+ #
138
+ # Column Specific
139
+ #
140
+ 'columnStyle' => {},
141
+ 'columnClass' => {},
142
+ 'columnPopupTitle' => {},
143
+ 'columnSort' => {},
144
+ 'columnWidth' => {},
145
+ 'columnNoSort' => {},
146
+ 'columnFilter' => {},
147
+
148
+ #
149
+ # Row specifics
150
+ #
151
+ 'rowColor' => '#FFFFFF',
152
+ 'rowClass' => '',
153
+ 'rowColorByStatus' => {},
154
+ 'rowStylesByStatus' => {},
155
+ 'offsetRows' => true,
156
+ 'rowOffsets' => ['FFFFFF','FFFFFF'],
157
+
158
+ 'class' => 'listContainerPassive',
159
+ 'tableclass' => '',
160
+ 'noDataMessage' => 'Currently no data.',
161
+ 'useSort' => true,
162
+ 'headerClass' => {},
163
+ 'groupBy' => '',
164
+ 'function' => {},
165
+ 'buttonVal' => 'templateListJump',
166
+ 'linkFunction' => 'ButtonLinkPost',
167
+ 'template' => '',
168
+ 'templateFilter' => '',
169
+ 'pagerFull' => true,
170
+ 'LIST_COL_SORT_ORDER' => 'ASC',
171
+ 'LIST_COL_SORT' => '',
172
+ 'LIST_FILTER_ALL' => '',
173
+ 'ROW_LIMIT' => '',
174
+ 'LIST_SEQUENCE' => 1,
175
+ 'NEW_SEARCH' => false,
176
+
177
+ #
178
+ # Checkbox
179
+ #
180
+ 'checked_class' => 'widgetlist-checkbox',
181
+ 'checked_flag' => {},
182
+
183
+ #
184
+ # Hooks
185
+ #
186
+ 'column_hooks' => {},
187
+ 'row_hooks' => {}
188
+ }
189
+
190
+ @totalRowCount= 0
191
+ @totalPages = 0
192
+ @fixHtmlLinksReplace = {}
193
+
194
+ @sequence = 1
195
+ @totalRows = 0
196
+ @totalPage = 0
197
+ @listSortNext = 'ASC'
198
+ @filter = ''
199
+ @listFilter = ''
200
+ @fieldList = []
201
+ @templateFill = {}
202
+ @results = {}
203
+
204
+ @items.deep_merge!({'template' =>
205
+ '
206
+ <!--HEADER-->
207
+ <div class="<!--CLASS-->" id="<!--NAME-->">
208
+ <table class="list <!--TABLE_CLASS-->" style="<!--INLINE_STYLE-->" border="0" width="100%" cellpadding="0" cellspacing="0">
209
+ <!--LIST_TITLE-->
210
+ <tr class="list_header"><!--HEADERS--></tr>
211
+ <!--DATA-->
212
+ <tr>
213
+ <td colspan="<!--COLSPAN_FULL-->" align="left" style="padding:0px;margin:0px;text-align:left">
214
+ <div style="background-color:#ECECEC;height:50px;"><div style="padding:10px"><!--CUSTOM_CONTENT--></div>
215
+ </td>
216
+ </tr>
217
+ </table>
218
+ <div class="pagination" style="float:left;text-align:left;width:100%;margin:0px;padding:0px;"><div style="margin:auto;float:left;margin:0px;padding:0px;"><!--PAGINATION_LIST--></div></div>
219
+ <!--FILTER-->
220
+ <input type="hidden" name="<!--JUMP_URL_NAME-->" id="<!--JUMP_URL_NAME-->" value="<!--JUMP_URL-->">
221
+ </div>
222
+ '
223
+ })
224
+
225
+ @items.deep_merge!({'row' =>
226
+ '
227
+ <tr style="background-color:<!--BGCOLOR-->;<!--ROWSTYLE-->" class="<!--ROWCLASS-->"><!--CONTENT--></tr>
228
+ '
229
+ })
230
+
231
+ @items.deep_merge!({'list_description' =>
232
+ '
233
+ <tr class="summary">
234
+ <td id="<!--LIST_NAME-->_list_description" class="header" style="text-align:left;padding-bottom:5px;padding-top:5px;" colspan="<!--COLSPAN-->"><!--LIST_DESCRIPTION--></td>
235
+ </tr>
236
+ '
237
+ })
238
+
239
+ @items.deep_merge!({'col' =>
240
+ '
241
+ <td class="<!--CLASS-->" align="<!--ALIGN-->" title="<!--TITLE-->" onclick="<!--ONCLICK-->" style="<!--STYLE-->"><!--CONTENT--></td>
242
+ '
243
+ })
244
+
245
+ @items.deep_merge!({'templateSequence' =>
246
+ '
247
+ <!--LIST_SEQUENCE--> of <!--TOTAL_PAGES-->
248
+ '
249
+ })
250
+ #Sorting
251
+ #
252
+ @items.deep_merge!({'templateSortColumn' =>
253
+ '
254
+ <td style="font-weight:bold;<!--INLINE_STYLE-->" id="<!--COL_HEADER_ID-->" class="<!--COL_HEADER_CLASS-->" valign="middle"><span onclick="<!--FUNCTION-->(\'<!--COLSORTURL-->\',\'<!--NAME-->\')" style="cursor:pointer;background:none;" title="<!--TITLE_POPUP-->"><!--TITLE--><!--COLSORTICON-></span></td>
255
+ '
256
+ })
257
+
258
+ @items.deep_merge!({'templateNoSortColumn' =>
259
+ '
260
+ <td style="font-weight:bold;<!--INLINE_STYLE-->" title="<!--TITLE_POPUP-->" id="<!--COL_HEADER_ID-->" class="<!--COL_HEADER_CLASS-->" valign="middle"><span style="background:none;"><!--TITLE--></span></td>
261
+ '
262
+ })
263
+
264
+ @items.deep_merge!({'statement' =>
265
+ {'select'=>
266
+ {'view' =>
267
+ '
268
+ SELECT <!--FIELDS--> FROM <!--SOURCE--> <!--WHERE--> <!--GROUPBY--> <!--ORDERBY--> <!--LIMIT-->
269
+ '
270
+ }
271
+ }
272
+ })
273
+
274
+ @items.deep_merge!({'statement' =>
275
+ {'select'=>
276
+ {'sql' =>
277
+ '
278
+ SELECT <!--FIELDS--> FROM (<!--SQL-->) a <!--WHERE--> <!--GROUPBY--> <!--ORDERBY--> <!--LIMIT-->
279
+ '
280
+ }
281
+ }
282
+ })
283
+
284
+ @items.deep_merge!({'statement' =>
285
+ {'count'=>
286
+ {'view' =>
287
+ '
288
+ SELECT count(1) total FROM <!--VIEW--> <!--WHERE-->
289
+ '
290
+ }
291
+ }
292
+ })
293
+
294
+ @items.deep_merge!({'statement' =>
295
+ {'count'=>
296
+ {'sql' =>
297
+ '
298
+ SELECT count(1) total FROM (<!--SQL-->) s <!--WHERE-->
299
+ '
300
+ }
301
+ }
302
+ })
303
+
304
+ @items.deep_merge!({'statement' =>
305
+ {'count'=>
306
+ {'table' =>
307
+ '
308
+ SELECT count(1) total FROM <!--TABLE--> <!--WHERE-->
309
+ '
310
+ }
311
+ }
312
+ })
313
+
314
+ #Pagintion
315
+ #
316
+
317
+ @items.deep_merge!({'template_pagination_wrapper' =>
318
+ '
319
+ <ul id="pagination" class="page_legacy">
320
+ Page <!--PREVIOUS_BUTTON-->
321
+ <input type="text" value="<!--SEQUENCE-->" size="1" style="width:15px;padding:0px;font-size:10px;">
322
+ <input type="hidden" id="<!--LIST_NAME-->_total_rows" value="<!--TOTAL_ROWS-->">
323
+ <!--NEXT_BUTTON--> of <!--TOTAL_PAGES--> pages <span style="margin-left:20px">Total <!--TOTAL_ROWS--> records found</span>
324
+ <span style="padding-left:20px;">Show <!--PAGE_SEQUENCE_JUMP_LIST--> per page</span>
325
+ </ul>
326
+ '
327
+ })
328
+
329
+ @items.deep_merge!({'template_pagination_next_active' =>
330
+ "
331
+ <li><span onclick=\"<!--FUNCTION-->('<!--NEXT_URL-->','<!--LIST_NAME-->')\" style=\"cursor:pointer;background: transparent url(<!--HTTP_SERVER-->images/page-next.gif) no-repeat\">&nbsp;</span></li>
332
+ "
333
+ })
334
+
335
+ @items.deep_merge!({'template_pagination_next_disabled' =>
336
+ "
337
+ <li><span style=\"opacity:0.4;filter:alpha(opacity=40);background: transparent url(<!--HTTP_SERVER-->images/page-next.gif) no-repeat\">&nbsp;</span></li>
338
+ "
339
+ })
340
+
341
+ @items.deep_merge!({'template_pagination_previous_active' =>
342
+ "
343
+ <li><span onclick=\"<!--FUNCTION-->('<!--PREVIOUS_URL-->','<!--LIST_NAME-->')\" style=\"cursor:pointer;background: transparent url(<!--HTTP_SERVER-->images/page-back.gif) no-repeat\">&nbsp;</span></li>
344
+ "
345
+ })
346
+
347
+ @items.deep_merge!({'template_pagination_previous_disabled' =>
348
+ "
349
+ <li><span style=\"opacity:0.4;filter:alpha(opacity=40);background: transparent url(<!--HTTP_SERVER-->images/page-back.gif) no-repeat\">&nbsp;</span></li>
350
+ "
351
+ })
352
+
353
+ @items.deep_merge!({'template_pagination_jump_active' =>
354
+ '
355
+ <li><div class="active"><!--SEQUENCE--></div></li>
356
+ '
357
+ })
358
+
359
+ @items.deep_merge!({'template_pagination_jump_unactive' =>
360
+ '
361
+ <li onclick="<!--FUNCTION-->(\'<!--JUMP_URL-->\',\'<!--LIST_NAME-->\')"><div><!--SEQUENCE--></div></li>
362
+ '
363
+ })
364
+
365
+ @items = WidgetList::Widgets::populate_items(list,@items)
366
+
367
+
368
+ begin
369
+ @isJumpingList = false
370
+
371
+ #Ajax ListJump
372
+ if ! $_REQUEST.empty?
373
+ if $_REQUEST.key?('LIST_FILTER_ALL')
374
+ @items['LIST_FILTER_ALL'] = $_REQUEST['LIST_FILTER_ALL']
375
+ @isJumpingList = true
376
+ end
377
+
378
+ if $_REQUEST.key?('LIST_COL_SORT')
379
+ @items['LIST_COL_SORT'] = $_REQUEST['LIST_COL_SORT']
380
+ @isJumpingList = true
381
+ end
382
+
383
+ if $_REQUEST.key?('LIST_COL_SORT_ORDER')
384
+ @items['LIST_COL_SORT_ORDER'] = $_REQUEST['LIST_COL_SORT_ORDER']
385
+ @isJumpingList = true
386
+ end
387
+
388
+ if $_REQUEST.key?('LIST_SEQUENCE')
389
+ @items['LIST_SEQUENCE'] = $_REQUEST['LIST_SEQUENCE'].to_i
390
+ @isJumpingList = true
391
+ end
392
+
393
+ if $_REQUEST.key?('ROW_LIMIT')
394
+ @items['ROW_LIMIT'] = $_REQUEST['ROW_LIMIT']
395
+ @isJumpingList = true
396
+
397
+ if @items['showPagination']
398
+ $_SESSION['pageDisplayLimit'] = $_REQUEST['ROW_LIMIT']
399
+ $_SESSION.deep_merge!({'ROW_LIMIT' => { @items['name'] => $_REQUEST['ROW_LIMIT']} })
400
+ end
401
+
402
+ end
403
+
404
+ clear_sort_get_vars()
405
+
406
+ if $_REQUEST.key?('list_action') && $_REQUEST['list_action'] == 'ajax_widgetlist_checks'
407
+ ajax_maintain_checks()
408
+ end
409
+
410
+ end
411
+
412
+ # current_db is a flag of the last known primary or secondary YML used or defaulted when running a list
413
+ $current_db_selection = @items['database']
414
+
415
+ @items['groupByClick'] = "ListChangeGrouping('" + @items['name'] + "')"
416
+
417
+ =begin
418
+ #todo
419
+ @items['fieldNames'] = {};
420
+ if (empty(@items['fields']) && empty(@items['data']))
421
+ {
422
+ #Lazy mode where new columns added to view show up in list (unless you name the column "HIDE_xxxxx")
423
+ #
424
+ if (@items['sql'])
425
+ {
426
+ preg_match("/\s+from\s+`?([a-z\d_]+)`?/i", @items['sql'], $match);
427
+ $viewName = $match[1];
428
+ }
429
+ elseif (@items['view'])
430
+ {
431
+ $viewName = @items['view'];
432
+ }
433
+
434
+ if ($this->DATABASE->Select("SHOW FULL COLUMNS IN ".$viewName))
435
+ {
436
+ foreach($this->DATABASE->results['FIELD'] as $col)
437
+ {
438
+ @items['fieldNames'][] = $col;
439
+ $columnUpper = strtoupper($col);
440
+ $columnLower = strtolower($col);
441
+ if (substr($columnUpper,0,5) != 'HIDE_')
442
+ {
443
+ #any columns named HIDE_ will not show
444
+ #
445
+ @items['fields'][$columnLower] = $this->autoColumnName($columnUpper);
446
+ if ($columnLower != 'features')
447
+ {
448
+ @items['columnSort'][$columnLower] = $columnLower;
449
+ }
450
+ }
451
+ }
452
+ }
453
+ }
454
+ =end
455
+
456
+ if $_REQUEST.key?('searchClear')
457
+ clear_search_session()
458
+ end
459
+
460
+ if @items['searchClear'] || @items['searchClearAll']
461
+ clear_search_session(@items.key?('searchClearAll'))
462
+ end
463
+
464
+ matchesCurrentList = $_REQUEST.key?('BUTTON_VALUE') && $_REQUEST['BUTTON_VALUE'] == @items['buttonVal']
465
+ isSearchRequest = $_REQUEST.key?('search_filter')
466
+ templateCustomSearch = !@items['templateFilter'].empty? # if you define templateFilter WidgetList will not attempt to build a where clause with search
467
+
468
+ #
469
+ # Search restore
470
+ #
471
+ if !isSearchRequest && $_SESSION.key?('SEARCH_FILTER') && $_SESSION['SEARCH_FILTER'].key?(@items['name']) && @items['searchSession']
472
+ isSearchRestore = true
473
+ end
474
+
475
+ if (isSearchRequest && matchesCurrentList && !templateCustomSearch && @items['showSearch']) || isSearchRestore
476
+ if !isSearchRestore
477
+ $_SESSION.deep_merge!({'SEARCH_FILTER' => { @items['name'] => $_REQUEST['search_filter']} })
478
+ searchFilter = $_REQUEST['search_filter'].strip_or_self()
479
+ else
480
+ searchFilter = $_SESSION['SEARCH_FILTER'][@items['name']]
481
+ end
482
+
483
+ if ! searchFilter.empty?
484
+ if ! @items['filter'].empty? && @items['filter'].class.name != 'Array'
485
+ # convert string to array filter
486
+ filterString = @items['filter']
487
+ @items['filter'] = []
488
+ @items['filter'] << filterString
489
+ end
490
+
491
+ fieldsToSearch = @items['fields']
492
+
493
+ @items['columns'].each { |columnPivot|
494
+ fieldsToSearch[columnPivot] = columnPivot
495
+ }
496
+
497
+ searchCriteria = searchFilter.strip_or_self()
498
+ searchSQL = []
499
+ numericSearch = false
500
+
501
+ #
502
+ # Comma delimited search
503
+ #
504
+ if searchFilter.include?(',')
505
+ #It is either a CSV or a comma inside the search string
506
+ #
507
+ criteriaTmp = searchFilter.split_it(',')
508
+
509
+ #Assumed a CSV of numeric ids
510
+ #
511
+ isNumeric = true
512
+ criteriaTmp.each_with_index { |value, key|
513
+ if !value.empty?
514
+ criteriaTmp[key] = value.strip_or_self()
515
+
516
+ if !criteriaTmp[key].nil? && ! criteriaTmp[key].empty?
517
+ if ! WidgetList::Utils::numeric?(criteriaTmp[key])
518
+ isNumeric = false
519
+ end
520
+ else
521
+ criteriaTmp.delete(key)
522
+ end
523
+ end
524
+ }
525
+
526
+ if isNumeric
527
+ if @items['searchIdCol'].class.name == 'Array'
528
+ @items['searchIdCol'].each { |searchIdCol|
529
+ if(fieldsToSearch.key?(searchIdCol))
530
+ searchSQL << "`" + searchIdCol + "` IN(" + searchFilter + ")"
531
+ end
532
+ }
533
+
534
+ if !searchSQL.empty?
535
+ #
536
+ # Assemble Numeric Filter
537
+ #
538
+ @items['filter'] << "(" + searchSQL.join(' OR ') + ")"
539
+ end
540
+ elsif @items['fields'].key?(@items['searchIdCol'])
541
+ numericSearch = true
542
+ @items['filter'] << "`#{@items['searchIdCol']}` IN(" + criteriaTmp.join(',') + ")"
543
+ end
544
+ end
545
+ elsif @items['searchIdCol'].class.name == 'Array'
546
+ if WidgetList::Utils::numeric?(searchFilter) && ! searchFilter.include?('.')
547
+ @items['searchIdCol'].each { |searchIdCol|
548
+ if fieldsToSearch.key?(searchIdCol)
549
+ searchSQL << "`#{searchIdCol}` IN(#{searchFilter})"
550
+ end
551
+ }
552
+
553
+ if !searchSQL.empty?
554
+ #
555
+ # Assemble Numeric Filter
556
+ #
557
+ @items['filter'] << "(" + searchSQL.join(' OR ') + ")"
558
+ end
559
+ end
560
+ #elsif WidgetList::Utils::numeric?(searchFilter) && ! searchFilter.include?('.') && @items['fields'].key?(@items['searchIdCol'])
561
+ # #19.95 is numeric, but people might be searching for dollar amounts which should be string based search
562
+ # numericSearch = true
563
+ #
564
+ # @items['filter'] << "`#{@items['searchIdCol']}` IN(" + searchFilter + ")"
565
+ end
566
+
567
+ # If it is not an id or a list of ids then it is assumed a string search
568
+ if !numericSearch
569
+ ii = 0
570
+ fieldsToSearch.each { |fieldName,fieldTitle|
571
+
572
+ # new lodgette. if function exists, find all matches and skip them
573
+ skip = false
574
+ (@items['function']||{}).each { |k,v|
575
+ if fieldName == k
576
+ skip = true
577
+ end
578
+ }
579
+
580
+ #buttons must ALWAYS BE ON THE RIGHT SIDE IN ORDER FOR THIS NOT TO SEARCH A NON-EXISTENT COLUMN (used to be hard coded to 'features' as a column to remove)
581
+ if (!@items['buttons'].empty? && ii == (fieldsToSearch.length - 1)) || skip
582
+ next
583
+ end
584
+
585
+ #Search only specified fields. This can involve a dynamic field list from an advanced search form
586
+ #
587
+ if ! @items['searchFieldsIn'].empty?
588
+ #
589
+ # If it exists in either key or value
590
+ #
591
+ if ! @items['searchFieldsIn'].key?(fieldName) && ! @items['searchFieldsIn'].include?(fieldName)
592
+ next
593
+ end
594
+ elsif ! @items['searchFieldsOut'].empty?
595
+ if @items['searchFieldsOut'].key?(fieldName) || @items['searchFieldsOut'].include?(fieldName)
596
+ next
597
+ end
598
+ end
599
+
600
+ #todo - escape bind variables using Sequel
601
+ searchSQL << "`#{fieldName}` LIKE '%" + searchCriteria + "%'"
602
+ ii = ii + 1
603
+ }
604
+
605
+ #
606
+ # Assemble String Filter
607
+ #
608
+ if(! searchSQL.empty?)
609
+ @items['filter'] << "(" + searchSQL.join(' OR ') + ")"
610
+ end
611
+ end
612
+ end
613
+ end
614
+
615
+ if !$_REQUEST.key?('BUTTON_VALUE')
616
+
617
+ #Initialize page load/Session stuff whe list first loads
618
+ #
619
+ clear_check_box_session(@items['name'])
620
+ end
621
+
622
+
623
+ if ! @items.key?('templateHeader')
624
+ @items['templateHeader'] = ''
625
+ end
626
+
627
+ #Set a list title if it exists
628
+ #
629
+
630
+ if ! $_REQUEST.key?('BUTTON_VALUE') && !@items['title'].empty?
631
+ @items['templateHeader'] = '
632
+ <h1><!--TITLE--></h1><div class="horizontal_rule"></div>
633
+ <!--FILTER_HEADER-->
634
+ '
635
+ else
636
+ if !$_REQUEST.key?('BUTTON_VALUE')
637
+ # Only if not in ajax would we want to output the filter header
638
+ #
639
+ @items['templateHeader'] = '
640
+ <!--FILTER_HEADER-->
641
+ '
642
+ end
643
+ end
644
+
645
+ # Build the filter (If any)
646
+ #
647
+ # todo - unit test filter
648
+ if !@items['filter'].empty? && @items['filter'].class.name == 'Array'
649
+ @filter = @items['filter'].join(' AND ')
650
+ elsif !@items['filter'].empty? && @items['filter'].class.name == 'String'
651
+ @filter = @items['filter']
652
+ end
653
+
654
+ #Sorting
655
+ #
656
+
657
+ if !@items['LIST_COL_SORT'].empty?
658
+ @items['LIST_SEQUENCE'] = 1
659
+ end
660
+
661
+ if @items['LIST_SEQUENCE'].class.name == 'Fixnum' && @items['LIST_SEQUENCE'] > 0
662
+ @sequence = @items['LIST_SEQUENCE'].to_i
663
+ end
664
+
665
+ if ! @items['ROW_LIMIT'].empty?
666
+ @items['rowLimit'] = @items['ROW_LIMIT'].to_i
667
+ end
668
+
669
+ if $_SESSION.key?('ROW_LIMIT') && $_SESSION['ROW_LIMIT'].key?(@items['name']) && !$_SESSION['ROW_LIMIT'][@items['name']].empty?
670
+ @items['rowLimit'] = $_SESSION['ROW_LIMIT'][@items['name']].to_i
671
+ end
672
+
673
+ if ! @items['LIST_COL_SORT'].empty?
674
+ case @items['LIST_COL_SORT_ORDER']
675
+ when 'ASC'
676
+ @listSortNext = 'DESC'
677
+ else
678
+ @listSortNext = 'ASC'
679
+ end
680
+ end
681
+
682
+ generate_limits()
683
+ rescue Exception => e
684
+ @templateFill['<!--DATA-->'] = '<tr><td colspan="50"><div id="noListResults">' + generate_error_output(e) + @items['noDataMessage'] + '</div></td></tr>'
685
+ end
686
+ end
687
+
688
+ def ajax_maintain_checks()
689
+
690
+ #
691
+ # A list must be provided
692
+ #
693
+ if $_REQUEST.key?('LIST_NAME')
694
+ listName = $_REQUEST['LIST_NAME']
695
+ sqlHash = $_REQUEST['SQL_HASH']
696
+
697
+ #
698
+ # The placeholder is created when the list initially forms. This validates it and makes it so
699
+ # not just anything can be injected into the session via this method.
700
+ #
701
+
702
+ #
703
+ # For each posted check box
704
+ #
705
+
706
+ $_REQUEST.each { |value, checked|
707
+ if checked.to_s == '1'
708
+ #
709
+ # Set it as checked
710
+ #
711
+ $_SESSION.deep_merge!({'list_checks' => { listName + sqlHash + value => true } })
712
+ else
713
+ #
714
+ # Unset if it exists and is unchecked
715
+ #
716
+ if $_SESSION['list_checks'].key?(listName + sqlHash + value)
717
+ $_SESSION['list_checks'].delete(listName + sqlHash + value)
718
+ end
719
+ end
720
+ }
721
+
722
+ #
723
+ # Check All
724
+ #
725
+ if $_REQUEST.key?('checked_all')
726
+ if $_SESSION.key?('list_checks')
727
+
728
+ if $_SESSION['list_checks'].key?('check_all_' + sqlHash + $_REQUEST['LIST_NAME'] + $_REQUEST['LIST_SEQUENCE'])
729
+ if $_REQUEST['checked_all'].empty?
730
+ $_SESSION['list_checks'].delete('check_all_' + sqlHash + $_REQUEST['LIST_NAME'] + $_REQUEST['LIST_SEQUENCE'])
731
+ else
732
+ $_SESSION.deep_merge!({'list_checks' => { 'check_all_' + sqlHash + $_REQUEST['LIST_NAME'] + $_REQUEST['LIST_SEQUENCE'] => true } })
733
+ end
734
+ else
735
+ if ! $_REQUEST['checked_all'].empty?
736
+ $_SESSION.deep_merge!({'list_checks' => { 'check_all_' + sqlHash + $_REQUEST['LIST_NAME'] + $_REQUEST['LIST_SEQUENCE'] => true } })
737
+ end
738
+ end
739
+ end
740
+ end
741
+ end
742
+ end
743
+
744
+ def clear_check_box_session(name='')
745
+
746
+ if $_SESSION.key?('DRILL_DOWN_FILTERS')
747
+ $_SESSION.delete('DRILL_DOWN_FILTERS')
748
+ end
749
+
750
+ if $_SESSION.key?('DRILL_DOWNS')
751
+ $_SESSION.delete('DRILL_DOWNS')
752
+ end
753
+
754
+ end
755
+
756
+ def clear_search_session(all=false)
757
+
758
+ if $_SESSION.key?('SEARCH_FILTER') && $_SESSION['SEARCH_FILTER'].key?(@items['name'])
759
+ $_SESSION['SEARCH_FILTER'].delete(@items['name'])
760
+ end
761
+
762
+ if $_SESSION.key?('ROW_LIMIT') && $_SESSION['ROW_LIMIT'].key?(@items['name'])
763
+ $_SESSION['ROW_LIMIT'].delete(@items['name'])
764
+ end
765
+
766
+ if all && $_SESSION.key?('SEARCH_FILTER')
767
+ $_SESSION.delete('SEARCH_FILTER')
768
+ end
769
+
770
+ if all && $_SESSION.key?('ROW_LIMIT')
771
+ $_SESSION.delete('ROW_LIMIT')
772
+ end
773
+
774
+ end
775
+
776
+ def clear_sql_session(all=false)
777
+
778
+ if $_SESSION.key?('LIST_SEQUENCE') && $_SESSION['LIST_SEQUENCE'].key?(@sqlHash)
779
+ $_SESSION['LIST_SEQUENCE'].delete(@sqlHash)
780
+ end
781
+
782
+ if $_SESSION.key?('LIST_COL_SORT') && $_SESSION['LIST_COL_SORT'].key?(@sqlHash)
783
+ $_SESSION['LIST_COL_SORT'].delete(@sqlHash)
784
+ end
785
+
786
+ if all && $_SESSION.key?('LIST_COL_SORT')
787
+ $_SESSION.delete('LIST_COL_SORT')
788
+ end
789
+
790
+ if all && $_SESSION.key?('LIST_SEQUENCE')
791
+ $_SESSION.delete('LIST_SEQUENCE')
792
+ end
793
+
794
+ end
795
+
796
+ def clear_sort_get_vars()
797
+ $_REQUEST.delete('LIST_FILTER_ALL')
798
+ $_REQUEST.delete('ROW_LIMIT')
799
+ $_REQUEST.delete('LIST_SEQUENCE')
800
+ $_REQUEST.delete('LIST_COL_SORT_ORDER')
801
+ $_REQUEST.delete('LIST_COL_SORT')
802
+ $_REQUEST.delete('LIST_FILTER_ALL')
803
+ end
804
+
805
+ def generate_limits()
806
+ #Pagination
807
+ #
808
+ @items['bindVarsLegacy']['LOW'] = @items['rowStart']
809
+ @items['bindVarsLegacy']['HIGH'] = @items['rowLimit']
810
+
811
+ if @sequence.to_i > 1 && ! @items['NEW_SEARCH']
812
+ @items['bindVarsLegacy']['LOW'] = (((@sequence * @items['rowLimit']) - @items['rowLimit']))
813
+ end
814
+ end
815
+
816
+ # @param [Hash] results
817
+ # pass results of $DATABASE.final_results after running a _select query
818
+ def render(results={})
819
+
820
+ begin
821
+ if !results.empty?
822
+ @items['data'] = results
823
+ end
824
+
825
+ #Get total records for statement validation and pagination
826
+ #
827
+ @items['data'].keys.each { |column|
828
+ @items['fields'][column.downcase] = auto_column_name(column)
829
+ } if !@items['data'].empty? && @items['fields'].empty?
830
+
831
+ if @items['data'].empty?
832
+ # Generate count() from database
833
+ #
834
+ @totalResultCount = get_total_records()
835
+ else
836
+ # Count the items in the passed data
837
+ #
838
+ @items['data'].keys.each { |column|
839
+ @totalResultCount = @items['data'][column].count
840
+ @totalRowCount = @totalResultCount
841
+ @totalRows = @totalResultCount
842
+ break
843
+ }
844
+ end
845
+
846
+ build_rows()
847
+
848
+ build_headers()
849
+
850
+ listJumpUrl = {}
851
+ listJumpUrl['PAGE_ID'] = @items['pageId']
852
+ listJumpUrl['ACTION'] = 'AJAX'
853
+ listJumpUrl['BUTTON_VALUE'] = @items['buttonVal']
854
+ listJumpUrl['LIST_COL_SORT'] = @items['LIST_COL_SORT']
855
+ listJumpUrl['LIST_COL_SORT_ORDER'] = @items['LIST_COL_SORT_ORDER']
856
+ listJumpUrl['LIST_FILTER_ALL'] = @items['LIST_FILTER_ALL']
857
+ listJumpUrl['ROW_LIMIT'] = @items['ROW_LIMIT']
858
+ listJumpUrl['LIST_SEQUENCE'] = @sequence
859
+ listJumpUrl['LIST_NAME'] = @items['name']
860
+ listJumpUrl['SQL_HASH'] = @sqlHash
861
+
862
+ if @items.key?('ajax_action')
863
+ listJumpUrl['list_action'] = @items['ajax_action']
864
+ end
865
+
866
+ @templateFill['<!--HEADER-->'] = @items['templateHeader']
867
+ @templateFill['<!--TITLE-->'] = @items['title']
868
+ @templateFill['<!--NAME-->'] = @items['name']
869
+ @templateFill['<!--JUMP_URL-->'] = WidgetList::Utils::build_url(@items['pageId'],listJumpUrl,(!$_REQUEST.key?('BUTTON_VALUE')))
870
+ @templateFill['<!--JUMP_URL_NAME-->'] = @items['name'] + '_jump_url'
871
+ @templateFill['<!--CLASS-->'] = @items['class']
872
+
873
+ if @totalRowCount > 0
874
+ @templateFill['<!--INLINE_STYLE-->'] = ''
875
+ @templateFill['<!--TABLE_CLASS-->'] = @items['tableclass']
876
+ else
877
+ @templateFill['<!--INLINE_STYLE-->'] = 'table-layout:auto;'
878
+ end
879
+ #Filter form
880
+ #
881
+ if @items['showSearch'] === true
882
+ if ! @items['templateFilter'].empty?
883
+ @templateFill['<!--FILTER_HEADER-->'] = @items['templateFilter']
884
+ else
885
+ if !$_REQUEST.key?('search_filter') && !@isJumpingList
886
+
887
+ #Search page url
888
+ #
889
+ searchUrl = ''
890
+ searchVal = ''
891
+
892
+ if ! @items['buttonVal'].empty?
893
+ searchVal = @items['buttonVal']
894
+ else
895
+ searchVal = @items['name']
896
+ end
897
+
898
+ filterParameters = {}
899
+ filterParameters['BUTTON_VALUE'] = searchVal
900
+ filterParameters['PAGE_ID'] = @items['pageId']
901
+ filterParameters['LIST_NAME'] = @items['name']
902
+ filterParameters['SQL_HASH'] = @sqlHash
903
+ if @items.key?('ajax_action') && ! @items['ajax_action'].empty?
904
+ filterParameters['list_action'] = @items['ajax_action']
905
+ end
906
+
907
+ searchUrl = WidgetList::Utils::build_url(@items['pageId'], filterParameters, (!$_REQUEST.key?('BUTTON_VALUE')))
908
+
909
+ list_search = {}
910
+ #
911
+ # Search value
912
+ #
913
+ list_search['value'] = ''
914
+
915
+ if @items['searchSession']
916
+ if $_SESSION.key?('SEARCH_FILTER') && $_SESSION['SEARCH_FILTER'].key?(@items['name'])
917
+ list_search['value'] = $_SESSION['SEARCH_FILTER'][@items['name']]
918
+ end
919
+ end
920
+
921
+ #
922
+ # Search Input Field
923
+ #
924
+ list_search['list-search'] = true
925
+ list_search['width'] = '500'
926
+ list_search['input_class'] = 'info-input'
927
+ list_search['title'] = (@items['searchTitle'].empty?) ? @items['searchBtnName'] :@items['searchTitle']
928
+ list_search['id'] = 'list_search_id_' + @items['name']
929
+ list_search['name'] = 'list_search_name_' + @items['name']
930
+ list_search['class'] = 'inputOuter widget-search-outer ' + @items['name'].downcase + '-search'
931
+ list_search['search_ahead'] = {
932
+ 'url' => searchUrl,
933
+ 'skip_queue' => false,
934
+ 'target' => @items['name'],
935
+ 'search_form' => @items['list_search_form'],
936
+ 'onclick' => (! @items['searchOnclick'].empty? && ! @items['list_search_form'].empty?) ? @items['searchOnclick'] : '',
937
+ 'onkeyup' => (! @items['searchOnkeyup'].empty?) ? @items['searchOnkeyup'] : ''
938
+ }
939
+
940
+ @templateFill['<!--FILTER_HEADER-->'] = WidgetList::Widgets::widget_input(list_search)
941
+
942
+ end
943
+
944
+ #
945
+ # Grouping box
946
+ #
947
+ if ! @items['groupByItems'].empty?
948
+ list_group = {}
949
+ list_group['arrow_action'] = 'var stub;'
950
+ list_group['readonly'] = true
951
+ if @items['groupBySelected']
952
+ list_group['value'] = @items['groupBySelected']
953
+ else
954
+ list_group['value'] = @items['groupByItems'][0]
955
+ end
956
+
957
+ list_group['style'] = 'cursor:pointer;margin-left:5px;'
958
+ list_group['input_style'] = 'cursor:pointer;'
959
+ list_group['outer_onclick'] = 'ToggleAdvancedSearch(this);SelectBoxResetSelectedRow(\'' + @items['name'] + '\');'
960
+ list_group['list-search'] = false
961
+ list_group['width'] = '200' #hard code for now. needs to be dynamic based on max str length if this caller is made into a "WidgetFakeSelect"
962
+ list_group['id'] = 'list_group_id_' + @items['name']
963
+ list_group['name'] = 'list_group_name_' + @items['name']
964
+ list_group['class'] = 'inputOuter widget-search-outer ' + @items['name'].downcase + '-group'
965
+
966
+ className = ''
967
+ groupRows = []
968
+ if !@items['groupBySelected']
969
+ className = 'widget-search-results-row-selected'
970
+ end
971
+
972
+ @items['groupByItems'].each { |grouping|
973
+ if @items['groupBySelected'] && @items['groupBySelected'] === grouping
974
+ className = 'widget-search-results-row-selected'
975
+ end
976
+ groupRows << '<div class="widget-search-results-row ' + className + '" title="' + grouping + '" onmouseover="jQuery(\'.widget-search-results-row\').removeClass(\'widget-search-results-row-selected\')" onclick="SelectBoxSetValue(\'' + grouping + '\',\'' + @items['name'] + '\');' + @items['groupByClick'] + '">' + grouping + '</div>'
977
+ className = ''
978
+ }
979
+
980
+ list_group['search_ahead'] = {
981
+ 'skip_queue' => false,
982
+ 'search_form'=> '
983
+ <div id="advanced-search-container" style="height:100% !important;">
984
+ ' + groupRows.join("\n") + '
985
+ </div>',
986
+ 'onclick' => @items['searchOnclick']
987
+ }
988
+ if !@templateFill.key?('<!--FILTER_HEADER-->')
989
+ @templateFill['<!--FILTER_HEADER-->'] = ''
990
+ end
991
+ @templateFill['<!--FILTER_HEADER-->'] += '<div class="fake-select"><div class="label">' + @items['groupByLabel'] + ':</div> ' + WidgetList::Widgets::widget_input(list_group) + '</div>'
992
+ end
993
+ end
994
+ end
995
+ rescue Exception => e
996
+ out = '<tr><td colspan="50"><div id="noListResults">' + generate_error_output(e) + @items['noDataMessage'] + '</div></td></tr>'
997
+ if !@templateFill.key?('<!--DATA-->')
998
+ @templateFill['<!--DATA-->'] = out
999
+ else
1000
+ @templateFill['<!--DATA-->'] += out
1001
+ end
1002
+ end
1003
+
1004
+ return WidgetList::Utils::fill(@templateFill, @items['template'])
1005
+
1006
+ end
1007
+
1008
+ def build_pagination()
1009
+ pageRange = 3
1010
+ pageNext = 1
1011
+ pagePrev = 1
1012
+ showPrev = false
1013
+ showNext = true
1014
+ prevUrl = ''
1015
+ nextUrl = ''
1016
+ tags = ''
1017
+ urlTags = {}
1018
+ templates = {}
1019
+
1020
+ urlTags['SQL_HASH'] = @sqlHash
1021
+ urlTags['PAGE_ID'] = @items['pageId']
1022
+ urlTags['LIST_NAME'] = @items['name']
1023
+ urlTags['BUTTON_VALUE'] = @items['buttonVal']
1024
+ urlTags['LIST_FILTER_ALL'] = @items['LIST_FILTER_ALL']
1025
+
1026
+ templates['btn_previous'] = @items['template_pagination_previous_disabled']
1027
+ templates['btn_next'] = @items['template_pagination_next_active']
1028
+
1029
+ if $_REQUEST.key?('search_filter') && ! $_REQUEST['search_filter'].empty?
1030
+ urlTags['search_filter'] = $_REQUEST['search_filter']
1031
+ end
1032
+
1033
+ if @items['LIST_COL_SORT'].empty?
1034
+ urlTags['LIST_COL_SORT'] = @items['LIST_COL_SORT']
1035
+ urlTags['LIST_COL_SORT_ORDER'] = @items['LIST_COL_SORT_ORDER']
1036
+ urlTags['ROW_LIMIT'] = @items['ROW_LIMIT']
1037
+ end
1038
+
1039
+ if @items['links'].key?('paginate') && @items['links']['paginate'].class.name == 'Hash'
1040
+ @items['links']['paginate'].each { |tagName, tag|
1041
+ urlTags[tagName] = tag
1042
+ }
1043
+ end
1044
+
1045
+ if @items.key?('ajax_action') && ! @items['ajax_action'].empty?
1046
+ urlTags['list_action'] = @items['ajax_action']
1047
+ end
1048
+
1049
+ if (@sequence == @totalPages || ! (@totalPages > 0))
1050
+ showNext = false
1051
+ else
1052
+ urlTags['LIST_SEQUENCE'] = @sequence + 1
1053
+ nextUrl = WidgetList::Utils::build_url(@items['pageId'],urlTags,(!$_REQUEST.key?('BUTTON_VALUE')))
1054
+ end
1055
+
1056
+ if @sequence > 1
1057
+ pagePrev = @sequence - 1
1058
+ urlTags['LIST_SEQUENCE'] = pagePrev
1059
+ prevUrl = WidgetList::Utils::build_url(@items['pageId'],urlTags,(!$_REQUEST.key?('BUTTON_VALUE')))
1060
+ showPrev = true
1061
+ end
1062
+
1063
+ if !showNext
1064
+ templates['btn_next'] = @items['template_pagination_next_disabled']
1065
+ end
1066
+
1067
+ if showPrev
1068
+ templates['btn_previous'] = @items['template_pagination_previous_active']
1069
+ end
1070
+
1071
+ #Assemble navigation buttons
1072
+ #
1073
+ pieces = {
1074
+ '<!--NEXT_URL-->' => nextUrl,
1075
+ '<!--LIST_NAME-->' => @items['name'],
1076
+ '<!--HTTP_SERVER-->' => $_SERVER['rack.url_scheme'] + '://' + $_SERVER['HTTP_HOST'] + '/assets/',
1077
+ '<!--PREVIOUS_URL-->' => prevUrl,
1078
+ '<!--FUNCTION-->' => @items['ajax_function']
1079
+ }
1080
+
1081
+ templates['btn_next'] = WidgetList::Utils::fill(pieces,templates['btn_next'])
1082
+ templates['btn_previous'] = WidgetList::Utils::fill(pieces,templates['btn_previous'])
1083
+
1084
+ #
1085
+ # Sequence Range Drop Down
1086
+ #
1087
+ # Show x per page
1088
+ #
1089
+ urlTags['LIST_SEQUENCE'] = @sequence
1090
+ urlTags['ROW_LIMIT'] = 10
1091
+
1092
+ # Automate select box and rules
1093
+ #
1094
+ rowLimitSelect = [10,20,50,100,500,1000]
1095
+ rowLimitSelectData = {}
1096
+ rowLimitSelectConfigs = {}
1097
+
1098
+ #Set a default of 10
1099
+ #
1100
+ urlTags['ROW_LIMIT'] = 10
1101
+ options = ''
1102
+ rowLimitSelect.each_with_index { |jumpCount, key|
1103
+ if (@totalRows >= jumpCount || @totalRows > rowLimitSelect[key-1])
1104
+ urlTags['ROW_LIMIT'] = jumpCount
1105
+
1106
+ rowLimitUrl = WidgetList::Utils::build_url(@items['pageId'],urlTags,(!$_REQUEST.key?('BUTTON_VALUE')))
1107
+ selected = ''
1108
+ if (@items['rowLimit'] == jumpCount)
1109
+ selected = 'selected'
1110
+ end
1111
+ options += "<option value='#{rowLimitUrl}' #{selected}>#{jumpCount}</option> "
1112
+ end
1113
+ }
1114
+
1115
+ # WidgetSelect( todo)
1116
+ pageSelect = <<-EOD
1117
+ <select onchange="#{@items['ajax_function']}(this.value,'#{@items['name']}')" style="width:58px">
1118
+ #{options}
1119
+ </select>
1120
+ EOD
1121
+
1122
+ #Ensure the range does not exceed the actual number of pages
1123
+ #
1124
+ if @totalPages < pageRange
1125
+ pageRange = @totalPages
1126
+ end
1127
+
1128
+ ###
1129
+ # Create a range of x or less numbers.
1130
+ #
1131
+ # Take 2 off and add 2 or as much as possible either way
1132
+ ###
1133
+ startingPoint = @sequence
1134
+ vkill = pageRange
1135
+
1136
+ while vkill > 0 do
1137
+ vkill = vkill - 1
1138
+ if startingPoint <= 1
1139
+ break
1140
+ else
1141
+ startingPoint = startingPoint-1
1142
+ end
1143
+ end
1144
+
1145
+ endPoint = @sequence
1146
+ vkill = pageRange
1147
+
1148
+ while vkill > 0 do
1149
+ vkill = vkill - 1
1150
+ if endPoint <= 1
1151
+ endPoint = endPoint+1
1152
+ else
1153
+ break
1154
+ end
1155
+ end
1156
+
1157
+ jumpSection = []
1158
+
1159
+ #Builds jump section previous 4 5 6 7 next
1160
+ #
1161
+ for page in startingPoint..endPoint
1162
+ urlTags['LIST_SEQUENCE'] = page
1163
+ urlTags['SQL_HASH'] = @sqlHash
1164
+ jumpTemplate = ''
1165
+ jumpUrl = ''
1166
+ jumpUrl = WidgetList::Utils::build_url(@items['pageId'], urlTags, (!$_REQUEST.key?('BUTTON_VALUE')))
1167
+
1168
+ if page == @sequence
1169
+ jumpTemplate = @items['template_pagination_jump_active']
1170
+ else
1171
+ jumpTemplate = @items['template_pagination_jump_unactive']
1172
+ end
1173
+
1174
+ jumpSection << WidgetList::Utils::fill({'<!--SEQUENCE-->'=>page,'<!--JUMP_URL-->'=>jumpUrl,'<!--LIST_NAME-->'=>@items['name'],'<!--FUNCTION-->'=>@items['ajax_function']}, jumpTemplate)
1175
+ end
1176
+
1177
+ pieces = {
1178
+ '<!--PREVIOUS_BUTTON-->' => templates['btn_previous'],
1179
+ '<!--SEQUENCE-->' => @sequence,
1180
+ '<!--NEXT_BUTTON-->' => templates['btn_next'],
1181
+ '<!--TOTAL_PAGES-->' => @totalPages,
1182
+ '<!--TOTAL_ROWS-->' => @totalRows,
1183
+ '<!--PAGE_SEQUENCE_JUMP_LIST-->' => pageSelect,
1184
+ '<!--JUMP-->' => jumpSection.join(''),
1185
+ '<!--LIST_NAME-->' => @items['name'],
1186
+ }
1187
+
1188
+ paginationOutput = WidgetList::Utils::fill(pieces,@items['template_pagination_wrapper'])
1189
+
1190
+ if (@items['showPagination'])
1191
+ return paginationOutput
1192
+ else
1193
+ return ''
1194
+ end
1195
+
1196
+ end
1197
+
1198
+ def build_headers()
1199
+ headers = []
1200
+ @items['fields'].each { |field, fieldTitle|
1201
+ colWidthStyle = '';
1202
+ colClass = '';
1203
+ popupTitle = '';
1204
+ templateIdx = 'templateNoSortColumn'
1205
+
1206
+ #Column class
1207
+ #
1208
+ if ! @items['headerClass'].empty?
1209
+ if @items['headerClass'].key?(field.downcase)
1210
+ colClass = @items['headerClass'][field.downcase]
1211
+ end
1212
+ end
1213
+
1214
+ #Column width
1215
+ #
1216
+ if ! @items['columnWidth'].empty?
1217
+ if @items['columnWidth'].key?(field.downcase)
1218
+ colWidthStyle = "width:" + @items['columnWidth'][field.downcase] + ";"
1219
+ end
1220
+ end
1221
+
1222
+ $_SESSION.deep_merge!({'LIST_SEQUENCE' => { @sqlHash => @sequence} })
1223
+
1224
+ #Hover Title
1225
+ #
1226
+ if @items['columnPopupTitle'].key?(field.downcase)
1227
+ popupTitle = @items['columnPopupTitle'][field.downcase]
1228
+ end
1229
+
1230
+
1231
+ #
1232
+ # Column is an input
1233
+ #
1234
+ if @items['inputs'].key?(fieldTitle) && @items['inputs'][fieldTitle].class.name == 'Hash'
1235
+ #
1236
+ # Default checkbox hover to "Select All"
1237
+ #
1238
+ # Do specific input type functions
1239
+ #
1240
+ case @items['inputs'][fieldTitle]['type']
1241
+ when 'checkbox'
1242
+
1243
+ if popupTitle.empty? && @items['inputs'][fieldTitle]['items']['check_all']
1244
+ popupTitle = 'Select All'
1245
+ end
1246
+
1247
+ #
1248
+ # No sort on this column
1249
+ #
1250
+ if ! @items['columnNoSort'].key?(fieldTitle)
1251
+ @items['columnNoSort'][field] = field
1252
+ end
1253
+
1254
+ if colClass.empty?
1255
+ @items['headerClass'] = { fieldTitle => 'widgetlist-checkbox-header'}
1256
+ colClass = @items['headerClass'][fieldTitle]
1257
+ end
1258
+ end
1259
+
1260
+ #
1261
+ # Build the input
1262
+ #
1263
+ fieldTitle = build_column_input(fieldTitle)
1264
+
1265
+ end
1266
+
1267
+ if (@items['useSort'] && (@items['columnSort'].include?(field) || (@items['columnSort'].key?(field)) && !@items['columnNoSort'].include?(field)) || (@items['columnSort'].empty? && !@items['columnNoSort'].include?(field)))
1268
+
1269
+ templateIdx = 'templateSortColumn'
1270
+ colSort = {}
1271
+
1272
+ #Assign the column to be sorted
1273
+ #
1274
+ if !@items['columnSort'].empty? && @items['columnSort'].key?(field)
1275
+ colSort['LIST_COL_SORT'] = @items['columnSort'][field]
1276
+ elsif (!@items['columnSort'].empty? && @items['columnSort'].include?(field)) || @items['columnSort'].empty?
1277
+ colSort['LIST_COL_SORT'] = field
1278
+ end
1279
+
1280
+ colSort['PAGE_ID'] = @items['pageId']
1281
+ colSort['LIST_NAME'] = @items['name']
1282
+ colSort['BUTTON_VALUE'] = @items['buttonVal']
1283
+ colSort['LIST_COL_SORT_ORDER'] = @listSortNext
1284
+ colSort['LIST_FILTER_ALL'] = @items['LIST_FILTER_ALL']
1285
+ colSort['ROW_LIMIT'] = @items['ROW_LIMIT']
1286
+ colSort['LIST_SEQUENCE'] = @sequence
1287
+
1288
+ icon = ""
1289
+
1290
+ if (
1291
+ ( (@items.key?('LIST_COL_SORT') && !@items['LIST_COL_SORT'].empty?) && @items['LIST_COL_SORT'] == colSort['LIST_COL_SORT']) ||
1292
+ ( $_SESSION.key?('LIST_COL_SORT') && $_SESSION['LIST_COL_SORT'].key?(@sqlHash) && $_SESSION['LIST_COL_SORT'][@sqlHash].key?(field))
1293
+ )
1294
+ changedSession = false
1295
+ if @items.key?('LIST_COL_SORT') && !@items['LIST_COL_SORT'].empty?
1296
+ changedSession = ( $_SESSION.key?('LIST_COL_SORT') && $_SESSION['LIST_COL_SORT'].key?(@sqlHash) && ! $_SESSION['LIST_COL_SORT'][@sqlHash].key?(@items['LIST_COL_SORT']) )
1297
+ if $_SESSION.key?('LIST_COL_SORT') && $_SESSION['LIST_COL_SORT'].key?(@sqlHash)
1298
+ $_SESSION['LIST_COL_SORT'].delete(@sqlHash)
1299
+ end
1300
+ $_SESSION.deep_merge!({'LIST_COL_SORT' => { @sqlHash => {@items['LIST_COL_SORT']=> @items['LIST_COL_SORT_ORDER'] } } })
1301
+ end
1302
+
1303
+ if !changedSession && @items.key?('LIST_COL_SORT') && ! @items['LIST_COL_SORT'].empty?
1304
+ if @items['LIST_COL_SORT_ORDER'] == 'DESC'
1305
+ icon = "&uarr;"
1306
+ else
1307
+ icon = "&darr;"
1308
+ end
1309
+ elsif !changedSession && $_SESSION['LIST_COL_SORT'].class.name == 'Hash' && $_SESSION['LIST_COL_SORT'].key?(@sqlHash)
1310
+ #load sort from session
1311
+ $_SESSION['LIST_COL_SORT'][@sqlHash].each_with_index { |order,void|
1312
+ if order[1] == 'DESC'
1313
+ colSort['LIST_COL_SORT_ORDER'] = "ASC"
1314
+ icon = "&uarr;"
1315
+ else
1316
+ colSort['LIST_COL_SORT_ORDER'] = "DESC"
1317
+ icon = "&darr;"
1318
+ end
1319
+ }
1320
+ end
1321
+ end
1322
+
1323
+ #Carry over any search criteria on a sort to SORT URL
1324
+ #
1325
+ if $_REQUEST.key?('search_filter') && ! $_REQUEST['search_filter'].empty?
1326
+ if $_REQUEST['search_filter'].empty?
1327
+ colSort['search_filter'] = $_REQUEST['search_filter']
1328
+ end
1329
+ end
1330
+
1331
+ if @items.key?('ajax_action') && ! @items['ajax_action'].empty?
1332
+ colSort['list_action'] = @items['ajax_action']
1333
+ end
1334
+ colSort['SQL_HASH'] = @sqlHash
1335
+
1336
+ pieces = { '<!--COLSORTURL-->' => WidgetList::Utils::build_url(@items['pageId'],colSort,(!$_REQUEST.key?('BUTTON_VALUE'))),
1337
+ '<!--NAME-->' => @items['name'],
1338
+ '<!--COLSORTICON->' => icon,
1339
+ '<!--COL_HEADER_ID-->' => strip_tags(field).gsub(/\s/,'_'),
1340
+ '<!--INLINE_STYLE-->' => colWidthStyle,
1341
+ '<!--TITLE_POPUP-->' => popupTitle,
1342
+ '<!--COL_HEADER_CLASS-->' => colClass,
1343
+ '<!--TITLE-->' => fieldTitle,
1344
+ '<!--FUNCTION-->' => @items['ajax_function']
1345
+ }
1346
+ headers << WidgetList::Utils::fill(pieces, @items[templateIdx])
1347
+ else
1348
+ pieces = { '<!--TITLE-->' => fieldTitle,
1349
+ '<!--INLINE_STYLE-->' => colWidthStyle,
1350
+ '<!--TITLE_POPUP-->' => popupTitle,
1351
+ '<!--COL_HEADER_CLASS-->' => colClass,
1352
+ '<!--COL_HEADER_ID-->' => strip_tags(field).gsub(/\s/,'_')
1353
+ }
1354
+
1355
+ headers << WidgetList::Utils::fill(pieces, @items[templateIdx])
1356
+ end
1357
+ }
1358
+
1359
+ @templateFill['<!--COLSPAN_FULL-->'] = headers.count()
1360
+
1361
+ if @items['mode'] != 'passive'
1362
+ pieces = {'<!--LIST_SEQUENCE-->' => @sequence,
1363
+ '<!--TOTAL_PAGES-->' => @totalPages}
1364
+
1365
+ @templateFill['<!--PAGE_SEQUENCE_DISPLAY-->'] = WidgetList::Utils::fill(pieces, @items['templateSequence'])
1366
+ end
1367
+
1368
+ @templateFill['<!--PAGINATION_LIST-->'] = build_pagination()
1369
+ @templateFill['<!--HEADERS-->'] = headers.join('')
1370
+
1371
+ if ! @items['listDescription'].empty?
1372
+ fillDesc = {}
1373
+ fillDesc['<!--COLSPAN-->'] = headers.count()
1374
+ fillDesc['<!--LIST_DESCRIPTION-->'] = @items['listDescription']
1375
+ fillDesc['<!--LIST_NAME-->'] = @items['name']
1376
+ @templateFill['<!--LIST_TITLE-->'] = WidgetList::Utils::fill(fillDesc,@items['list_description'])
1377
+ else
1378
+ @templateFill['<!--LIST_TITLE-->'] = ''
1379
+ end
1380
+
1381
+ end
1382
+
1383
+ # @param [String] column (the name)
1384
+ # @param [Fixnum] row (the id or pointer in the loop to fetch the data)
1385
+ def build_column_input(column, row='')
1386
+ content = ''
1387
+
1388
+ inputManager = @items['inputs'][column]
1389
+ case inputManager['type']
1390
+ when "checkbox"
1391
+
1392
+
1393
+ input = {}
1394
+ input['name'] = 'widget_check_name'
1395
+ input['id'] = 'widget_check_id'
1396
+ input['check_all'] = false
1397
+ input['value'] = ''
1398
+ input['checked'] = ''
1399
+ input['onclick'] = ''
1400
+ input['input_class'] = 'widgetlist-checkbox-input'
1401
+
1402
+ input['class_handle'] = ''
1403
+
1404
+ input = WidgetList::Widgets::populate_items(inputManager['items'],input)
1405
+
1406
+ onClick = []
1407
+ checkAllId = ''
1408
+
1409
+ #
1410
+ # Get a value. Assumes it is a column initially.
1411
+ #
1412
+ # @note headers are ignored and would fail as row would be null
1413
+ #
1414
+ if @results.key?(input['value'].upcase) && !@results[input['value'].upcase][row].to_s.empty?
1415
+ input['value'] = @results[ input['value'].upcase ][row]
1416
+ end
1417
+
1418
+ #
1419
+ # Append class handle
1420
+ #
1421
+ input['input_class'] = "#{input['input_class']} #{input['class_handle']}"
1422
+
1423
+ if input['check_all']
1424
+ checkAllId = input['id']
1425
+ if $_SESSION.key?('list_checks') && $_SESSION['list_checks'].key?('check_all_' + @sqlHash.to_s + @items['name'].to_s + @sequence.to_s)
1426
+ input['checked'] = true
1427
+ end
1428
+
1429
+ #
1430
+ # Set header class
1431
+ #
1432
+ if @items['headerClass'].class.name == 'Array' && @items['headerClass'].key?('checkbox')
1433
+ if $_SESSION['list_checks'].key?('check_all_' + @sqlHash.to_s + @items['name'].to_s + @sequence.to_s)
1434
+ input['checked'] = true
1435
+ end
1436
+ end
1437
+ else
1438
+ input['input_class'] = "#{input['input_class']} #{input['class_handle']} #{input['class_handle']}_list"
1439
+ end
1440
+
1441
+ #
1442
+ # Setup onclick action
1443
+ #
1444
+ if input['onclick'].empty?
1445
+ listJumpUrl = {}
1446
+ listJumpUrl['BUTTON_VALUE'] = @items['buttonVal']
1447
+ listJumpUrl['LIST_COL_SORT'] = @items['LIST_COL_SORT']
1448
+ listJumpUrl['LIST_COL_SORT_ORDER'] = @items['LIST_COL_SORT_ORDER']
1449
+ listJumpUrl['LIST_FILTER_ALL'] = @items['LIST_FILTER_ALL']
1450
+ listJumpUrl['ROW_LIMIT'] = @items['ROW_LIMIT']
1451
+ listJumpUrl['LIST_SEQUENCE'] = @sequence
1452
+ listJumpUrl['LIST_NAME'] = @items['name']
1453
+ listJumpUrl['SQL_HASH'] = @sqlHash
1454
+ listJumpUrl['list_action'] = 'ajax_widgetlist_checks'
1455
+
1456
+ onClick << "AjaxMaintainChecks(this, '#{input['class_handle']}', '#{@items['name']}', '" + WidgetList::Utils::build_url(@items['pageId'],listJumpUrl,(!$_REQUEST.key?('BUTTON_VALUE'))) + "', '#{checkAllId}');"
1457
+ end
1458
+
1459
+ input['onclick'] = onClick.join(' ')
1460
+
1461
+ #
1462
+ # Checkbox is checked or not per query value
1463
+ #
1464
+ if ! @items['checked_flag'].empty?
1465
+ if @items['checked_flag'].key?(column)
1466
+ input['checked'] = !!@results[ @items['checked_flag'][column].upcase ][row]
1467
+ end
1468
+ end
1469
+
1470
+ #
1471
+ # Checkbox is checked or not per session (overwrites query)
1472
+ #
1473
+ if $_SESSION.key?('list_checks') && $_SESSION['list_checks'].key?(@items['name'] + @sqlHash + input['value'].to_s)
1474
+ input['checked'] = true
1475
+ end
1476
+
1477
+ content = WidgetList::Widgets::widget_check(input)
1478
+
1479
+ #todo never implemented
1480
+
1481
+ when "text"
1482
+ a=1
1483
+ #content = WidgetInput()
1484
+
1485
+ when "select"
1486
+ a=1
1487
+ #content = WidgetSelect()
1488
+
1489
+ end
1490
+
1491
+ return content
1492
+ end
1493
+
1494
+ def build_column_button(column,j)
1495
+ buttons = @items['buttons'][column]
1496
+ columnValue = @results[column.upcase][j]
1497
+ btnOut = []
1498
+ strCnt = 0
1499
+ nameId = ''
1500
+
1501
+ buttons.each { |buttonId,buttonAttribs|
1502
+ #url = array('PAGE_ID')
1503
+ function = @items['linkFunction']
1504
+ parameters = ''
1505
+ renderButton = true
1506
+
1507
+ if buttonAttribs.key?('tags')
1508
+ buttonAttribs['tags'].each { | tagName , tag |
1509
+ #only uppercase will be replaced
1510
+ #
1511
+
1512
+ if @results.key?(tag.upcase) && @results[tag.upcase][j]
1513
+
1514
+ buttonAttribs.deep_merge!({'args' =>
1515
+ {
1516
+ tagName => @results[tag.upcase][j]
1517
+ }
1518
+ })
1519
+ else
1520
+ buttonAttribs.deep_merge!({'args' =>
1521
+ {
1522
+ tagName => tag
1523
+ }
1524
+ })
1525
+ end
1526
+ }
1527
+ end
1528
+ nameId = buttonId.to_s + '_' + j.to_s
1529
+
1530
+ buttonAttribs['name'] = nameId
1531
+ buttonAttribs['id'] = nameId
1532
+
1533
+ #if buttonAttribs.key?('condition')
1534
+ #never show button if you pass a condition unless explicitly matching the value of the features
1535
+ #
1536
+ #renderButton = false
1537
+ #allConditions = columnValue.split(':')
1538
+ #if (in_array(ltrim($buttonAttribs['condition'], ':'), $allConditions))
1539
+ # renderButton = true
1540
+ #end
1541
+ #end
1542
+
1543
+ if (renderButton)
1544
+ strCnt += (buttonAttribs['text'].length * 15)
1545
+ btnOut << WidgetList::Widgets::widget_button(buttonAttribs['text'], buttonAttribs, true)
1546
+ end
1547
+ }
1548
+
1549
+ #BS width algorithm. HACK/TWEAK/OMG Get it working.
1550
+ #
1551
+ colWidth = ((strCnt + (btnOut.count * 35)) / 2) + 10
1552
+
1553
+ return '<div style="border:0px solid black;text-align:center;white-space:nowrap;margin:auto;width:' + colWidth.to_s + 'px"><div style="margin:auto;display:inline-block">' + btnOut.join('') + '</div></div>'
1554
+ end
1555
+
1556
+ # @param [String] column
1557
+ def build_column_link(column,j)
1558
+
1559
+ links = @items['links'][column]
1560
+ url = {'PAGE_ID' => @items['pageId']}
1561
+ function = @items['linkFunction']
1562
+ parameters = ''
1563
+
1564
+ if links.key?('PAGE_ID') && ! links['PAGE_ID'].empty?
1565
+ url['PAGE_ID'] = links['PAGE_ID']
1566
+ end
1567
+
1568
+ if links.key?('ACTION') && ! links['ACTION'].empty?
1569
+ url['list_action'] = links['ACTION']
1570
+ end
1571
+
1572
+ if links.key?('BUTTON_VALUE') && ! links['BUTTON_VALUE'].empty?
1573
+ url['BUTTON_VALUE'] = links['BUTTON_VALUE']
1574
+ end
1575
+
1576
+ #todo unit test this and all of column links
1577
+ if links.key?('tags')
1578
+ links['tags'].each { | tagName, tag |
1579
+ if @results[tag][j]
1580
+ url[tagName] = @results[tag][j]
1581
+ else
1582
+ url[tagName] = tag
1583
+ end
1584
+ }
1585
+ end
1586
+
1587
+ if links.key?('onclick') && links['onclick'].class.name == 'Hash'
1588
+ if links['onclick'].key?('function') && !links['onclick']['function'].empty?
1589
+ function = links['onclick']['function']
1590
+ end
1591
+
1592
+ if links['onclick'].key?('tags') && !links['onclick']['tags'].empty?
1593
+ links['onclick']['tags'].each { | tagName , tag|
1594
+ if @results.key?(tag.upcase)
1595
+ parameters = ", '" + @results[tag.upcase][j] + "'"
1596
+ end
1597
+ }
1598
+ end
1599
+ end
1600
+
1601
+ if @items.key?('ajax_action') && !@items['ajax_action'].empty?
1602
+ url['list_action'] = @items['ajax_action']
1603
+ end
1604
+
1605
+ url['SQL_HASH'] = @sqlHash
1606
+ linkUrl = WidgetList::Utils::build_url(@items['pageId'],(!$_REQUEST.key?('BUTTON_VALUE')))
1607
+
1608
+ "#{function}('#{linkUrl}'#{parameters})"
1609
+ end
1610
+
1611
+ def build_rows()
1612
+ sql = build_statement()
1613
+ if @totalResultCount > 0
1614
+ if @items['data'].empty?
1615
+ #Run the actual statement
1616
+ #
1617
+ @totalRowCount = WidgetList::List.get_database._select(sql, @items['bindVars'], @items['bindVarsLegacy'])
1618
+ end
1619
+
1620
+ if @totalRowCount > 0
1621
+ if @items['data'].empty?
1622
+ @results = WidgetList::List.get_database.final_results
1623
+ else
1624
+ @results = @items['data']
1625
+ end
1626
+
1627
+ #Build each row
1628
+ #
1629
+ max = @totalRowCount-1
1630
+ rows = []
1631
+ j = 0
1632
+ for j in j..max
1633
+ columns = []
1634
+ customRowColor = ''
1635
+ customRowStyle = ''
1636
+
1637
+ #
1638
+ # For each column (field) in this row
1639
+ #
1640
+
1641
+ @items['fields'].each { |column , fieldTitle|
1642
+ colPieces = {}
1643
+ colClasses = []
1644
+ theStyle = ''
1645
+ colData = ''
1646
+ colClass = ''
1647
+ onClick = ''
1648
+ colWidthStyle = ''
1649
+ content = ''
1650
+ contentTitle = ''
1651
+
1652
+
1653
+
1654
+ #todo unit test build_column_link
1655
+
1656
+ #
1657
+ # Column is a Link
1658
+ #
1659
+ if @items['links'].key?(column) && @items['links'][column].class.name == 'Hash'
1660
+ onClick = build_column_link(column,j)
1661
+
1662
+ #
1663
+ # Column is a Button
1664
+ #
1665
+ elsif @items['buttons'].key?(column) && @items['buttons'][column].class.name == 'Hash'
1666
+ content = build_column_button(column, j)
1667
+
1668
+
1669
+ #
1670
+ # Column is an input
1671
+ #
1672
+ elsif @items['inputs'].key?(column) && @items['inputs'][column].class.name == 'Hash'
1673
+ colClasses << @items['checked_class']
1674
+ content = build_column_input(column, j)
1675
+
1676
+
1677
+ #
1678
+ # Column is text
1679
+ #
1680
+ else
1681
+ cleanData = strip_tags(@results[column.upcase][j].to_s)
1682
+
1683
+ if cleanData.length > @items['strlength']
1684
+ =begin
1685
+ $contentTitle = $cleanData;
1686
+
1687
+ $possibleMatches = array("/(.*)(\(<a.*?>.*?<\/a>\)\s)(.*)/i" => array(3), #<a>(id)</a> Text
1688
+ "/(.*)(<a.*?>)(.*)(<\/a>)(.*)/i" => array(3) #<a>Text</a> other text
1689
+ );
1690
+
1691
+ foreach($possibleMatches as $regex => $toFix)
1692
+ {
1693
+ $matched = preg_match_all($regex, @results[strtoupper($column)][$j], $matches, PREG_PATTERN_ORDER);
1694
+
1695
+ if(! empty($matched))
1696
+ {
1697
+ $pieces = {};
1698
+
1699
+ unset($matches[0]);
1700
+
1701
+ foreach($matches as $key => $theText)
1702
+ {
1703
+ $fixedText = '';
1704
+
1705
+ if(in_array($key, $toFix))
1706
+ {
1707
+ $fixedText = substr($theText[0], 0, @items['strlength']) . '...';
1708
+ }
1709
+ else
1710
+ {
1711
+ $fixedText = $theText[0];
1712
+ }
1713
+
1714
+ $pieces[] = $fixedText;
1715
+ }
1716
+
1717
+ $content = implode('', $pieces);
1718
+
1719
+ break;
1720
+ }
1721
+ }
1722
+
1723
+ if(empty($matched))
1724
+ {
1725
+ if ((strpos(@results[strtoupper($column)][$j],'&#') !== false && strpos(@results[strtoupper($column)][$j],';') !== false))
1726
+ {
1727
+ $content = @results[strtoupper($column)][$j];
1728
+ }
1729
+ else
1730
+ {
1731
+ $content = substr(@results[strtoupper($column)][$j], 0, @items['strlength']) . '...';
1732
+ }
1733
+ }
1734
+ =end
1735
+ content = @results[column.upcase][j].to_s[ 0, @items['strlength'] ] + '...'
1736
+
1737
+ else
1738
+ content = @results[column.upcase][j].to_s
1739
+ end
1740
+
1741
+ #Strip HTML
1742
+ #
1743
+ if !@items['allowHTML']
1744
+ content = strip_tags(content)
1745
+ end
1746
+ content = WidgetList::List.get_database._bind(content, @items['bindVarsLegacy'])
1747
+
1748
+ # Column color
1749
+ #
1750
+ if ! @items['columnStyle'].empty?
1751
+ if @items['columnStyle'].key?(column.downcase)
1752
+ colHeader = @items['columnStyle'][column.downcase]
1753
+
1754
+ if @results.key?(colHeader.upcase)
1755
+ theStyle = @results[colHeader.upcase][j]
1756
+ else
1757
+ theStyle = colHeader
1758
+ end
1759
+
1760
+ end
1761
+ end
1762
+
1763
+ # Column width
1764
+ #
1765
+ if ! @items['columnWidth'].empty?
1766
+ if @items['columnWidth'].key?(column.downcase)
1767
+ colWidthStyle = "width:" + @items['columnWidth'][column.downcase] + ";"
1768
+ end
1769
+ end
1770
+
1771
+ # Column Class
1772
+ #
1773
+ if !@items['columnClass'].empty?
1774
+ if @items['columnClass'].key?(column.downcase)
1775
+ colClasses << @items['columnClass'][column.downcase]
1776
+ end
1777
+ end
1778
+
1779
+ end
1780
+
1781
+
1782
+ #
1783
+ # Setup any column classes
1784
+ #
1785
+ colClasses << @items['collClass']
1786
+ colClass = colClasses.join(' ')
1787
+
1788
+ #
1789
+ # Row Color
1790
+ #
1791
+ if !@items['rowColorByStatus'].empty? && @items['rowColorByStatus'].key?(column) && !@items['rowColorByStatus'][column].empty?
1792
+ @items['rowColorByStatus'][column].each { |status,color|
1793
+ if status === content
1794
+ customRowColor = color
1795
+ end
1796
+ }
1797
+ end
1798
+
1799
+ #
1800
+ # Row Style
1801
+ #
1802
+ if !@items['rowStylesByStatus'].empty? && @items['rowStylesByStatus'].key?(column) && !@items['rowStylesByStatus'][column].empty?
1803
+ @items['rowStylesByStatus'][column].each { |status,inlineStyle|
1804
+ if status === content
1805
+ customRowStyle = color
1806
+ end
1807
+ }
1808
+ end
1809
+
1810
+ #
1811
+ # Set up Column Pieces
1812
+ #
1813
+ colPieces['<!--CLASS-->'] = colClass
1814
+ colPieces['<!--ALIGN-->'] = @items['collAlign']
1815
+ colPieces['<!--STYLE-->'] = theStyle + colWidthStyle
1816
+ colPieces['<!--ONCLICK-->'] = onClick
1817
+ colPieces['<!--TITLE-->'] = contentTitle #todo htmlentities needed ?
1818
+ colPieces['<!--CONTENT-->'] = content
1819
+ #
1820
+ # Assemble the Column
1821
+ #
1822
+ columns << WidgetList::Utils::fill(colPieces, @items['col'])
1823
+
1824
+ }
1825
+
1826
+ #Draw the row
1827
+ #
1828
+
1829
+ pieces = {'<!--CONTENT-->' => columns.join('') }
1830
+ if @items['rowColorByStatus'].empty? && @items['rowStylesByStatus'].empty?
1831
+ #Set the row color
1832
+ #
1833
+ rowColor = @items['rowColor']
1834
+
1835
+ if @items['offsetRows']
1836
+ if( j % 2 ==0)
1837
+ rowColor = @items['rowOffsets'][1]
1838
+ else
1839
+ rowColor = @items['rowOffsets'][0]
1840
+ end
1841
+ end
1842
+
1843
+ #Draw default color
1844
+ #
1845
+ pieces['<!--BGCOLOR-->'] = rowColor
1846
+ pieces['<!--ROWSTYLE-->'] = ''
1847
+ pieces['<!--ROWCLASS-->'] = @items['rowClass']
1848
+ else
1849
+ pieces['<!--BGCOLOR-->'] = !customRowColor.empty? ? customRowColor : @items['rowColor']
1850
+ pieces['<!--ROWSTYLE-->'] = customRowStyle.empty? ? customRowStyle : ''
1851
+ pieces['<!--ROWCLASS-->'] = @items['rowClass']
1852
+ end
1853
+ rows << WidgetList::Utils::fill(pieces, @items['row'])
1854
+
1855
+ end
1856
+
1857
+ @templateFill['<!--DATA-->'] = rows.join('')
1858
+
1859
+ else
1860
+ @templateFill['<!--DATA-->'] = '<tr><td colspan="50"><div id="noListResults">' + generate_error_output() + @items['noDataMessage'] + '</div></td></tr>'
1861
+ end
1862
+
1863
+ else
1864
+ @templateFill['<!--DATA-->'] = '<tr><td colspan="50"><div id="noListResults">' + generate_error_output() + @items['noDataMessage'] + '</div></td></tr>'
1865
+ end
1866
+
1867
+ end
1868
+
1869
+ def generate_error_output(ex='')
1870
+ sqlDebug = ""
1871
+ if Rails.env == 'development'
1872
+ sqlDebug += "<br/><br/><textarea style='width:100%;height:400px;'>" + WidgetList::List.get_database.last_sql.to_s + "</textarea>"
1873
+ end
1874
+
1875
+ if Rails.env == 'development' && WidgetList::List.get_database.errors
1876
+ sqlDebug += "<br/><br/><strong style='color:red'>(" + WidgetList::List.get_database.last_error.to_s + ")</strong>"
1877
+ end
1878
+
1879
+ if Rails.env == 'development' && ex != ''
1880
+ sqlDebug += "<br/><br/><strong style='color:red'>(" + ex.to_s + ") <pre>" + $!.backtrace.join("\n\n") + "</pre></strong>"
1881
+ end
1882
+
1883
+ sqlDebug
1884
+ end
1885
+
1886
+ def build_statement()
1887
+ statement = ''
1888
+ pieces = { '<!--FIELDS-->' => '',
1889
+ '<!--SOURCE-->' => '',
1890
+ '<!--WHERE-->' => '',
1891
+ '<!--GROUPBY-->' => '',
1892
+ '<!--ORDERBY-->' => '',
1893
+ '<!--LIMIT-->' => ''}
1894
+
1895
+ if !@items['sql'].empty? || !@items['force_query_sql'].empty?
1896
+ if !@items['fieldNames'].empty?
1897
+ @items['fieldNames'].each { |column|
1898
+ tick = '`'
1899
+ if(isset(@items['function'][column]))
1900
+ tick = ''
1901
+ column = @items['function'][column]
1902
+ end
1903
+ @fieldList << "#{tick}#{column}#{tick}"
1904
+ }
1905
+ fields = @fieldList.join(',')
1906
+
1907
+
1908
+ else
1909
+ fields = "*";
1910
+ end
1911
+
1912
+
1913
+ sqlPieces = {};
1914
+ sqlPieces['<!--FIELDS-->'] = fields;
1915
+ sqlPieces['<!--SQL-->'] = @items['sql'];
1916
+
1917
+ if !@items['force_query_sql'].empty?
1918
+ statement = @items['force_query_sql']
1919
+ else
1920
+ statement = @items['statement']['select']['sql']
1921
+ end
1922
+
1923
+ statement = WidgetList::Utils::fill(sqlPieces, @items['statement']['count']['table'])
1924
+
1925
+ elsif !@items['view'].empty?
1926
+ #Build out a list of columns to select from
1927
+ #
1928
+ @items['fields'].each { |column, fieldTitle|
1929
+ if @items['function'].key?(column) && !@items['function'][column].empty?
1930
+ column = @items['function'][column]
1931
+ end
1932
+
1933
+ @fieldList << column
1934
+ }
1935
+
1936
+ #Add any columns without corresponding header titles
1937
+ #
1938
+ @items['columns'].each { |column|
1939
+ @fieldList << column
1940
+ }
1941
+
1942
+ viewPieces = {}
1943
+ viewPieces['<!--FIELDS-->'] = @fieldList.join(',')
1944
+ viewPieces['<!--SOURCE-->'] = @items['view']
1945
+
1946
+ statement = WidgetList::Utils::fill(viewPieces, @items['statement']['select']['view'])
1947
+ end
1948
+
1949
+ @sqlHash = Digest::SHA2.hexdigest( WidgetList::Utils::fill(pieces, statement) )
1950
+
1951
+ if @items['searchClear'] || @items['searchClearAll']
1952
+ clear_sql_session(@items.key?('searchClearAll'))
1953
+ end
1954
+
1955
+ if !$_REQUEST.key?('BUTTON_VALUE') && $_SESSION.key?('LIST_SEQUENCE') && $_SESSION['LIST_SEQUENCE'].key?(@sqlHash) && $_SESSION['LIST_SEQUENCE'][@sqlHash] > 0
1956
+ @sequence = $_SESSION['LIST_SEQUENCE'][@sqlHash]
1957
+ generate_limits
1958
+ end
1959
+
1960
+ if !@filter.empty?
1961
+ where = ' WHERE '
1962
+ pieces['<!--WHERE-->'] = where + @filter
1963
+ end
1964
+
1965
+ if !@items['groupBy'].empty?
1966
+ pieces['<!--GROUPBY-->'] += ' GROUP BY ' + @items['groupBy']
1967
+ end
1968
+
1969
+ if !@items['LIST_COL_SORT'].empty? || $_SESSION.key?('LIST_COL_SORT') && $_SESSION['LIST_COL_SORT'].class.name == 'Hash' && $_SESSION['LIST_COL_SORT'].key?(@sqlHash)
1970
+ if ! @items['LIST_COL_SORT'].empty?
1971
+ pieces['<!--ORDERBY-->'] += ' ORDER BY `' + @items['LIST_COL_SORT'] + "` " + @items['LIST_COL_SORT_ORDER']
1972
+ else
1973
+ $_SESSION['LIST_COL_SORT'][@sqlHash].each_with_index { |order,void|
1974
+ pieces['<!--ORDERBY-->'] += ' ORDER BY `' + order[0] + "` " + order[1]
1975
+ } if $_SESSION.key?('LIST_COL_SORT') && $_SESSION['LIST_COL_SORT'].class.name == 'Hash' && $_SESSION['LIST_COL_SORT'].key?(@sqlHash)
1976
+ end
1977
+
1978
+ # Add base order by
1979
+ if ! @items['orderBy'].empty?
1980
+ pieces['<!--ORDERBY-->'] += ',' + @items['orderBy']
1981
+ end
1982
+
1983
+ elsif !@items['orderBy'].empty?
1984
+ pieces['<!--ORDERBY-->'] += ' ORDER BY ' + @items['orderBy']
1985
+ end
1986
+
1987
+ pieces['<!--LIMIT-->'] = ' LIMIT :LOW, :HIGH'
1988
+
1989
+ statement = WidgetList::Utils::fill(pieces, statement)
1990
+
1991
+ if @items['rowLimit'] >= @totalRows
1992
+ @items['bindVarsLegacy']['LOW'] = 0
1993
+ @sequence = 1
1994
+ end
1995
+
1996
+ statement
1997
+ end
1998
+
1999
+ def auto_column_name(name='')
2000
+ name.gsub(/\_/,' ').gsub(/\-/,' ').capitalize
2001
+ end
2002
+
2003
+ def get_total_records()
2004
+
2005
+ filter = ''
2006
+ fields = {}
2007
+ sql = ''
2008
+ hashed = false
2009
+
2010
+ if !@items['force_count_sql'].empty?
2011
+ sql = @items['force_count_sql']
2012
+ elsif !@items['table'].empty?
2013
+ sql = WidgetList::Utils::fill({'<!--TABLE-->' => @items['table']}, @items['statement']['count']['table'])
2014
+ elsif !@items['sql'].empty?
2015
+ sql = WidgetList::Utils::fill({'<!--SQL-->' => @items['sql']}, @items['statement']['count']['sql'])
2016
+ elsif !@items['view'].empty?
2017
+ sql = WidgetList::Utils::fill({'<!--VIEW-->' => @items['view']}, @items['statement']['count']['view'])
2018
+ end
2019
+
2020
+ if ! @filter.empty?
2021
+ filter = ' WHERE ' + @filter
2022
+ end
2023
+
2024
+ sql = WidgetList::Utils::fill({'<!--WHERE-->' => filter}, sql)
2025
+
2026
+ if ! sql.empty?
2027
+ if @items['showPagination']
2028
+ if WidgetList::List.get_database._select(sql, [], @items['bindVarsLegacy']) > 0
2029
+ rows = WidgetList::List.get_database.final_results['TOTAL'][0]
2030
+ else
2031
+ rows = 0
2032
+ end
2033
+ if rows > 0
2034
+ @totalRows = rows
2035
+ end
2036
+ else
2037
+ rows = 1
2038
+ end
2039
+ else
2040
+ rows = 0
2041
+ end
2042
+
2043
+ if @totalRows > 0
2044
+ @totalPages = (@totalRows.to_f / @items['rowLimit'].to_f).ceil()
2045
+ end
2046
+
2047
+ rows
2048
+ end
2049
+
2050
+ end
2051
+
2052
+ end
2053
+
2054
+