sortable_skima 0.2.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +192 -0
  3. data/app/assets/javascripts/jquery-ui.min.js +12 -0
  4. data/app/assets/javascripts/jquery.ba-bbq.js +1137 -0
  5. data/app/assets/javascripts/skima-sortable-tables_2_0_10.js +450 -0
  6. data/app/assets/stylesheets/images/animated-overlay.gif +0 -0
  7. data/app/assets/stylesheets/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  8. data/app/assets/stylesheets/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  9. data/app/assets/stylesheets/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  10. data/app/assets/stylesheets/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  11. data/app/assets/stylesheets/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  12. data/app/assets/stylesheets/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  13. data/app/assets/stylesheets/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  14. data/app/assets/stylesheets/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  15. data/app/assets/stylesheets/images/ui-icons_222222_256x240.png +0 -0
  16. data/app/assets/stylesheets/images/ui-icons_2e83ff_256x240.png +0 -0
  17. data/app/assets/stylesheets/images/ui-icons_454545_256x240.png +0 -0
  18. data/app/assets/stylesheets/images/ui-icons_888888_256x240.png +0 -0
  19. data/app/assets/stylesheets/images/ui-icons_cd0a0a_256x240.png +0 -0
  20. data/app/assets/stylesheets/jquery-ui.css +1183 -0
  21. data/app/controllers/sortables_controller.rb +75 -0
  22. data/app/models/sortable.rb +82 -0
  23. data/config/routes.rb +5 -0
  24. data/doc/Backtrace.html +493 -0
  25. data/doc/README_rdoc.html +329 -0
  26. data/doc/SortableHelper.html +364 -0
  27. data/doc/SortableSkima.html +343 -0
  28. data/doc/SortableSkima/Engine.html +131 -0
  29. data/doc/created.rid +7 -0
  30. data/doc/images/add.png +0 -0
  31. data/doc/images/brick.png +0 -0
  32. data/doc/images/brick_link.png +0 -0
  33. data/doc/images/bug.png +0 -0
  34. data/doc/images/bullet_black.png +0 -0
  35. data/doc/images/bullet_toggle_minus.png +0 -0
  36. data/doc/images/bullet_toggle_plus.png +0 -0
  37. data/doc/images/date.png +0 -0
  38. data/doc/images/delete.png +0 -0
  39. data/doc/images/find.png +0 -0
  40. data/doc/images/loadingAnimation.gif +0 -0
  41. data/doc/images/macFFBgHack.png +0 -0
  42. data/doc/images/package.png +0 -0
  43. data/doc/images/page_green.png +0 -0
  44. data/doc/images/page_white_text.png +0 -0
  45. data/doc/images/page_white_width.png +0 -0
  46. data/doc/images/plugin.png +0 -0
  47. data/doc/images/ruby.png +0 -0
  48. data/doc/images/tag_blue.png +0 -0
  49. data/doc/images/tag_green.png +0 -0
  50. data/doc/images/transparent.png +0 -0
  51. data/doc/images/wrench.png +0 -0
  52. data/doc/images/wrench_orange.png +0 -0
  53. data/doc/images/zoom.png +0 -0
  54. data/doc/index.html +347 -0
  55. data/doc/js/darkfish.js +155 -0
  56. data/doc/js/jquery.js +18 -0
  57. data/doc/js/navigation.js +142 -0
  58. data/doc/js/search.js +94 -0
  59. data/doc/js/search_index.js +1 -0
  60. data/doc/js/searcher.js +228 -0
  61. data/doc/rdoc.css +543 -0
  62. data/doc/sortable_parser.html +78 -0
  63. data/doc/table_of_contents.html +114 -0
  64. data/lib/sortable_skima.rb +122 -0
  65. data/lib/sortable_skima/active_record.rb +36 -0
  66. data/lib/sortable_skima/backtrace.rb +53 -0
  67. data/lib/sortable_skima/engine.rb +63 -0
  68. data/lib/sortable_skima/helpers/sortable_helper.rb +188 -0
  69. metadata +142 -0
@@ -0,0 +1,450 @@
1
+ //= require jquery-ui.min
2
+ //= require jquery.ba-bbq
3
+ //these lines above arent working...sprockets gem should make it work but I couldn't figure how to
4
+
5
+ //creates filters from submit action
6
+ //WARNING THIS SHOULD BE IN A DIFFERENT FILE
7
+
8
+
9
+ /**------------SORTABLE TABLE JQUERY PLUGIN-------------------
10
+ * Author: xbits @ skima on 3/21/14.
11
+ *
12
+ * Requires: jquery.js, jquery-ui.js, jquery-ui.css(including images)
13
+ *
14
+ * Requires: The whole fkin gem
15
+ *
16
+ * Description:
17
+ *
18
+ * Jquery plugin for sortable tables
19
+ *
20
+ *
21
+ * Add to a table example:
22
+ * $('.myTable').sortableTable();
23
+ **/
24
+
25
+ var SortableLocale = {
26
+ noDataMessage: 'No results found'
27
+ }
28
+ $(document).ready(function(){
29
+ jQuery.fn.sortableTable = sortableTable;
30
+ $("[data-sortable-query]").sortableTable();//inits sortable tables for the chosen selector
31
+
32
+ //change pagination to work by ajax on sortable columns
33
+
34
+ function sortableTable(options){
35
+ var QUERY_ATTR = 'data-sortable-query';
36
+
37
+ var SORT_ATTR = 'sort-field';//attribute(in each <th>) name of the field to order IE: sortField ='id'
38
+ var SOURCE_ATTR = 'sort-source';//attr(in <table>) name of the path to query, if empty the current domain is queried
39
+ var LINK_ITEM_ATTR = 'data-link-item';
40
+ var PER_PAGE_ATTR = "data-per-page";
41
+ var CLASS_ATTR = 'data-class';
42
+ var INIT_ON_CLIENT_ATTR = "data-initialize-on-client"
43
+ var PRE_SORT_ATTR = 'sort-default';//attr(in <table>) name of currently sorted column IE: 'name ASC'
44
+ var DONT_SORT_ATTR = 'dont-sort';//the attr(in each <th>) for local sorting tables skips sorting on this column
45
+ var LOAD_BY_AJAX_ATTR = 'load-by-ajax';//attr(in <table>) boolean defaults to true, if true only the tbody content will be loaded by an ajax call, else the whole page will be loaded
46
+ var TOKEN_ATTR = 'data-table-token';//unique identifier for this particular query for backtraces
47
+ var GROUP_ID_ATTR = 'data-group-id'//identifier for the groups of related table and filters
48
+ var FILTER_KEY_ATTR = 'data-filter-key'//identifier for the filter column
49
+
50
+ var LOCAL_DATA_FLAG = 'useLocalData';//set attr 'sortSource' as this to sort only locally with already available <td> rows
51
+
52
+ var ORDER_ATTR = 'sort-order';//for internal use
53
+ var DEF_ORDER = "DESC";//default/initial sort order
54
+ var UP_ICON = "ui-icon-triangle-1-n";
55
+ var DOWN_ICON = "ui-icon-triangle-1-s";
56
+
57
+ var EVT_LOADED = 'sortable.loaded';
58
+
59
+ options = options || {};
60
+
61
+ $(this).each(function(){//create sortable table for all elements returned by jquery's selector
62
+ options = this.sortableTableOptions = $.extend(this.sortableTableOptions, options);
63
+ var $tableElm = $(this);
64
+ var $tBody = $tableElm.find('tbody');
65
+ // var $filtersForm = $("["+FILTERS_ID_ATTR+"='"+$tableElm.attr(FILTERS_ID_ATTR)+"']");
66
+ var $filters = $("select["+GROUP_ID_ATTR+"='"+$tableElm.attr(GROUP_ID_ATTR)+"']");
67
+ var $paginateContainer = $(".paginate-container["+GROUP_ID_ATTR+"='"+$tableElm.attr(GROUP_ID_ATTR)+"']");
68
+ var curField = "";
69
+ var curOrder = "";
70
+ var prevField = "";
71
+ var prevOrder = "";
72
+ var sortBtns = [];
73
+ var loaderDiv;
74
+ // var lastSort = "";
75
+ var useLocalData = false;
76
+ var curPage = 1;
77
+ var fields ={};
78
+ var initialRequest = !($tableElm.attr(INIT_ON_CLIENT_ATTR) == 'true');
79
+ var filtersLock = false;//disables filters lock during update
80
+
81
+ init();
82
+ function init (){
83
+ if($tableElm.data('sortableTableInit')){
84
+ //console.log("This table was already initiated",$tableElm.attr(GROUP_ID_ATTR),$(this))
85
+ return;
86
+ }
87
+ $tableElm.data('sortableTableInit',true)
88
+ useLocalData = $tableElm.attr(SOURCE_ATTR) == LOCAL_DATA_FLAG;
89
+ var fieldHeaderSelector = (useLocalData)?'th':'th['+SORT_ATTR+']';
90
+ var sortClickMethod = (useLocalData)?sortClickLocal:onSortClickRemote;
91
+ var indexes = [];
92
+ $tableElm.find(fieldHeaderSelector).each(function(){
93
+ if($(this).html() != '' && !this.sortableTableInit && !$(this).attr(DONT_SORT_ATTR)){
94
+ this.sortableTableInit = true;//dont add twice
95
+ if(useLocalData){ $(this).attr(SORT_ATTR, $(this).html());}
96
+ if($(this).attr(SORT_ATTR)){
97
+ var curIndex = $(this).position().left;//use x position
98
+ indexes.push(curIndex);
99
+ fields[$(this).attr(SORT_ATTR)] = {
100
+ tmpIndex:curIndex,
101
+ $element:$(this),
102
+ linkItem:$(this).attr(LINK_ITEM_ATTR),
103
+ class: $(this).attr(CLASS_ATTR)
104
+ }
105
+ }
106
+ if(!$(this).attr('disabled')){
107
+ var btnDiv = document.createElement('div');//add div for css-position fix
108
+ btnDiv.innerHTML = $(this).html();
109
+ var rowspan = parseInt($(this).attr('rowspan') || 1)
110
+ $(this).css('padding',0);
111
+ $(this).html(btnDiv);
112
+ $(btnDiv).css('width','100%').css('height',rowspan*1.8+'em');//$(this).height()-2+'px');
113
+ $(btnDiv).button();
114
+ $(btnDiv).children().css('line-height',$(this).height()-2+'px');
115
+ $(btnDiv).click(sortClickMethod);
116
+ sortBtns.push($(btnDiv));
117
+ }
118
+ }
119
+ });
120
+ //Give colindexes sequential values instead of X position
121
+ indexes = indexes.sort(function (a, b) { return a-b; });
122
+ for(var i = 0; i < indexes.length; i++){
123
+ for(fieldName in fields){
124
+ if(fields[fieldName].tmpIndex == indexes[i]){
125
+ fields[fieldName].colIndex = i;
126
+ delete fields[fieldName].tmpIndex
127
+ break;
128
+ }
129
+ }
130
+ }
131
+ var preSort = $tableElm.attr(PRE_SORT_ATTR);
132
+ if(preSort){
133
+ preSort = preSort.split(',')[0].split(' ');
134
+ curField = preSort[0];
135
+ curOrder = preSort[1];
136
+ updateArrowDisplay();
137
+ }
138
+ initPagination();
139
+ initFilters();
140
+ autoLoadIfEmpty()
141
+ }
142
+ function initFilters(){
143
+ $filters.change(onFiltersChange);
144
+ }
145
+
146
+ function onFiltersChange(){
147
+ if(!filtersLock){
148
+ curPage = 1;
149
+ loadAjaxContent(curPage);
150
+ }
151
+ }
152
+
153
+ //these two function hijack the pagination links
154
+ function initPagination(){
155
+
156
+ $paginateContainer.find('.pagination').first().click(onPaginationClick)
157
+ }
158
+ function onPaginationClick(e){
159
+ //I think most of the code in this method is outdated and useless in current version
160
+ // but its working so I cant be bothered to refactor it! Some day...maybe...
161
+ //try{
162
+ if( $(e.target).attr('href')){
163
+ var href = $(e.target).attr('href');
164
+ var paramObj = $.deparam.querystring(href);
165
+ var newPage = parseInt(paramObj.page);
166
+ if(newPage != curPage){
167
+ var $curPageLink = $(this).find('.current');
168
+ curPage = curPage || $.deparam.querystring().page;
169
+ paramObj.page = curPage;//set this for old link build
170
+ var linkUrl = location.pathname+'?'+ $.param(paramObj);
171
+ var pagelinks = $(this).children();
172
+ var totalPages = parseInt(pagelinks.eq(pagelinks.length-2).html());
173
+ $(this).html('');
174
+
175
+ var upperLimit = Math.max(8,newPage+4);
176
+ for(var i = 1; i <= totalPages; i++){
177
+ if(i==3 && i < totalPages-8 && i < newPage -4 ){
178
+ i = Math.min(totalPages-8 , newPage -4);
179
+ $(this).append('<span class="gap">...</span> ');
180
+ }else if(i == upperLimit+1 && i < totalPages-2){
181
+ i = totalPages-1;
182
+ $(this).append('<span class="gap">...</span> ');
183
+ }
184
+ var selectedClass = (i == newPage)?'current':'';
185
+ paramObj.page = i;
186
+ linkUrl = location.pathname+'?'+ $.param(paramObj);
187
+ $(this).append('<a class="'+selectedClass+'" href="'+linkUrl+'">'+i+'</a> ');
188
+ }
189
+
190
+ paramObj.page = Math.max(1,newPage-1);
191
+ linkUrl = location.pathname+'?'+ $.param(paramObj);
192
+ $(this).prepend('<a href="'+linkUrl+'" class="previous_page" rel="prev">⇐ Anterior</a>');
193
+ paramObj.page = Math.min(totalPages,newPage+1);
194
+ linkUrl = location.pathname+'?'+ $.param(paramObj);
195
+ $(this).append('<a href="'+linkUrl+'" class="next_page" rel="next">Próximo ⇒</a>');
196
+
197
+ curPage = newPage;
198
+ loadFromRemote(newPage);
199
+ }
200
+ }
201
+
202
+ return false;
203
+ }
204
+
205
+ function autoLoadIfEmpty(){
206
+ if(!$tBody.html().trim()){
207
+ !$tBody.html('.');
208
+ updateArrowDisplay();
209
+ var loadByAjax = $tableElm.attr(LOAD_BY_AJAX_ATTR);
210
+ if(loadByAjax != 'false'){
211
+ loadAjaxContent(curPage);
212
+ }
213
+ }
214
+ }
215
+
216
+ function getNewOrder(btn){
217
+ var newOrder = $(btn).attr(ORDER_ATTR);
218
+ if(newOrder != undefined){
219
+ newOrder = (curOrder == 'ASC')? 'DESC':'ASC';
220
+ }else{
221
+ newOrder = DEF_ORDER;
222
+ }
223
+ $(btn).attr(ORDER_ATTR, newOrder);
224
+ return newOrder;
225
+ }
226
+
227
+ function sortClickLocal(){
228
+ curField = $(this).parent().attr(SORT_ATTR);
229
+ curOrder = getNewOrder(this);
230
+ var fieldIndex = $tableElm.find('th').get().indexOf($(this).parent().get()[0]);
231
+ var ascending = (curOrder == 'ASC');
232
+ var findValue = function(row){
233
+ return $(row).children('td:eq('+fieldIndex+')').text().toLowerCase();
234
+ };
235
+ var numeric = true;
236
+ $tBody.children('tr').each(function(){
237
+ var value = findValue(this);
238
+ if(value != '' && !isNumber(value)){
239
+ numeric = false;
240
+ return false;
241
+ }
242
+ });
243
+ var compare = (ascending)?function(a,b){return a<b}:function(a,b){return a>b};
244
+ var sorted;
245
+ if(numeric){
246
+ sorted = $tBody.find('tr').sort(function(a,b){
247
+ var aValue = parseFloat(findValue(a));
248
+ aValue = aValue || 0; // count NaN as zero
249
+ return compare(aValue,parseFloat(findValue(b)));
250
+ });
251
+ }else{
252
+ sorted = $tBody.find('tr').sort(function(a,b){
253
+ return compare(findValue(a),findValue(b));
254
+ });
255
+ }
256
+ $tBody.html(sorted);
257
+ updateArrowDisplay();
258
+ }
259
+
260
+ function onSortClickRemote(){
261
+ var newField = $(this).parent().attr(SORT_ATTR);
262
+
263
+ var newOrder = getNewOrder(this);
264
+
265
+ if(newField != curField){//if new field has changed save it in previous for double sorting
266
+ prevField = curField;
267
+ prevOrder = curOrder;
268
+ }
269
+ curOrder = newOrder;
270
+ curField = newField;
271
+ loadFromRemote(curPage );
272
+ }
273
+
274
+ function loadFromRemote(pageNum){
275
+ var loadByAjax = $tableElm.attr(LOAD_BY_AJAX_ATTR);
276
+ if(loadByAjax != 'false'){
277
+ loadAjaxContent(pageNum);
278
+ }else{
279
+ navigateToSorted(pageNum);
280
+ }
281
+ updateArrowDisplay();
282
+ }
283
+
284
+ function getRemoteURL(itemsOnly,pageNum) {
285
+ var tableToken = $tableElm.attr(TOKEN_ATTR);
286
+ var perPage = $tableElm.attr(PER_PAGE_ATTR);
287
+ var sourceUrl = '/sortable_data';//$tableElm.attr(SOURCE_ATTR) || ''; //document.domain +
288
+ var sortStr = curField + ' ' + curOrder;
289
+ var query = $tableElm.attr(QUERY_ATTR);
290
+
291
+ var paramsObj = $.deparam.querystring();
292
+ paramsObj.query = query;
293
+
294
+ if(!initialRequest){
295
+ if (prevField) {//use previous order
296
+ sortStr += ',' + prevField + ' ' + prevOrder;
297
+ }
298
+ paramsObj.order_by = sortStr;
299
+
300
+ var filters = {};
301
+ $filters.each(function(index,selectEl) {
302
+ var $this = $(this);
303
+ // if($this.attr(FILTER_ACTIVE_ATTR)) {
304
+ var filterKey = $this.attr(FILTER_KEY_ATTR);
305
+ var filterVal = $this.val();
306
+ filters[filterKey] = filterVal;
307
+ // }
308
+ });
309
+ paramsObj.filters = filters;
310
+ }
311
+
312
+ if (pageNum) {
313
+ paramsObj.page = pageNum;
314
+ }
315
+
316
+ if(perPage){
317
+ paramsObj.per_page = perPage;
318
+ }
319
+
320
+ paramsObj.table_token = tableToken;
321
+
322
+ initialRequest = false;
323
+
324
+ return sourceUrl+'?'+ $.param(paramsObj);
325
+ }
326
+
327
+ function navigateToSorted(pageNum){
328
+ window.location.href = getRemoteURL(false,pageNum);
329
+ }
330
+ function loadAjaxContent(pageNum){
331
+ showLoader();
332
+ $.ajax({url:getRemoteURL(true, pageNum), dataType: "json"}).done(onAjaxLoaded)
333
+ }
334
+
335
+ function showLoader(){
336
+ if(!loaderDiv){
337
+ loaderDiv = $(document.createElement('div'));
338
+ loaderDiv.css('position','absolute');
339
+ loaderDiv.css('opacity','0.4');
340
+ }
341
+
342
+ var offset = $tBody.offset();
343
+ loaderDiv.css(offset);
344
+ loaderDiv.width($tBody.width());
345
+ loaderDiv.height($tBody.height());
346
+ try{//TODO why the fail here??
347
+ $(loaderDiv).progressbar({value: false});
348
+ }catch(er){}
349
+ $('body').append(loaderDiv);//html(loader+$tBody.html());
350
+ }
351
+
352
+ function updateArrowDisplay(){
353
+ sortBtns.forEach(function(btn){
354
+ var icon = null;
355
+ if(btn.parents('th['+SORT_ATTR+']').attr(SORT_ATTR) == curField){
356
+ icon = (curOrder == 'ASC')?UP_ICON:DOWN_ICON;
357
+ btn.attr(ORDER_ATTR, curOrder);//this is repeated in updateOrder...remove the other maybe
358
+ }
359
+ btn.button( "option", "icons", { secondary: icon } );
360
+ })
361
+ }
362
+
363
+ function onAjaxLoaded(data){
364
+ $(loaderDiv).remove();
365
+ $tBody.html('');
366
+ $(data.rows_data).each(function(index,row){
367
+ var $tr = $(document.createElement("tr"));
368
+ var orderedCells = [];
369
+ for (var prop in row) {
370
+ if(fields[prop]){
371
+ var cell = row[prop].val;
372
+ if(!row[prop].no_display){
373
+ var $td = $(document.createElement("td"));
374
+ if(row[prop].path){
375
+ var $cell = $(document.createElement("a"));
376
+ $cell.attr('href',row[prop].path);
377
+ $cell.addClass('link_item');
378
+ $cell.html(cell);
379
+ $td.addClass('link');
380
+ $td.append($cell);
381
+ }else{
382
+ $td.html(cell);
383
+ }
384
+ $td.addClass(fields[prop].class);
385
+ orderedCells[fields[prop].colIndex] = $td;
386
+ }
387
+ }
388
+ $tr.append(orderedCells)
389
+ }
390
+ $tr[0].sortableData = row;
391
+ $tBody.append($tr);
392
+ });
393
+
394
+ if(data.rows_data.length == 0){// 0 results returned
395
+ var $tr = $(document.createElement("tr"));
396
+ var $td = $(document.createElement("td"));
397
+ $td.attr('colspan',$tableElm.find('th').length);
398
+ $td.css('text-align','center').css('background','#eee');
399
+ $td.html(SortableLocale.noDataMessage);
400
+ $tr.append($td);
401
+ $tBody.append($tr);
402
+
403
+ }
404
+
405
+ if(data.pagination){
406
+ $paginateContainer.html(data.pagination);
407
+ initPagination();
408
+ }else{
409
+ $paginateContainer.html('');//.html('no paginate');
410
+ }
411
+ if(data.filters){
412
+ filtersLock = true;
413
+ for(filter_key in data.filters ){
414
+ var filter_value = data.filters[filter_key];
415
+ var $filter = getFilterElement(filter_key);
416
+ $filter.val(filter_value);
417
+ }
418
+ filtersLock = false;
419
+ }
420
+
421
+ if(data.cur_order && (typeof data.cur_order == 'string')){
422
+ var splittedOrder = data.cur_order.split(' ');
423
+ if(splittedOrder.length > 1){
424
+ curField = splittedOrder[0];
425
+ curOrder = splittedOrder[1];
426
+ updateArrowDisplay();
427
+ }
428
+ }
429
+
430
+ var onLoadedCallBack = $tableElm[0].sortableTableOptions.onLoad;
431
+ $tableElm.trigger(EVT_LOADED, data, $tableElm, $tableElm.attr(QUERY_ATTR));
432
+ if(onLoadedCallBack){
433
+ onLoadedCallBack(data, $tableElm,$tableElm.attr(QUERY_ATTR));
434
+ }
435
+
436
+ }
437
+ function getFilterElement(filterKey){
438
+ var $filter = $('nomatch');
439
+ $filters.each(function(){
440
+ if($(this).attr(FILTER_KEY_ATTR) == filterKey){
441
+ $filter = $(this);
442
+ return false;
443
+ }
444
+ })
445
+ return $filter;
446
+ }
447
+ })
448
+ };
449
+
450
+ });