sortable_skima 0.2.0.25

Sign up to get free protection for your applications and to get access to all the features.
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
+ });