grid_table 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3822148a7134b0523bad25bba7d31440a68497e9
4
+ data.tar.gz: 9e3b2dbc9d8dc3d316b3995060f4865c26b6b620
5
+ SHA512:
6
+ metadata.gz: b8afb20b6c8d00007a29b256659e4ae15c80c0f3e41f8e29f4daaa7fb450e9a3357583625b4b11220d508d829c9ee979173c06380fd962e6ee053b66acd07b21
7
+ data.tar.gz: b8b6495fb43c7d7aade3d6c2ff881af9af47f0c8de603dcb36e7c738fce7b9e438e6a028574539833d242e7a5b94f7e2d378c9b107a7da2cdb2f3298ae2564da
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gridtable.gemspec
4
+ gemspec
5
+
6
+ gem 'activerecord', require: "active_record"
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Jon Principe
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,124 @@
1
+ # GridTable
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'grid_table'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install grid_table
18
+
19
+ ## Usage
20
+
21
+ 1. Mark up your table in the index.html.haml with the GridTable HTML 5 attributes
22
+ ```
23
+ %table.grid-table{data: {url: users_path}}
24
+ %thead
25
+ %tr
26
+ %th.small-5{data: { field: 'email', sort: 'true', filter: 'true', default_sort: 'asc' }} Email
27
+ %th{data: { field: 'first_name', sort: 'true', filter: 'true' }} First Name
28
+ %th{data: { field: 'last_name', sort: 'true', filter: 'true' }} Last Name
29
+ %th{data: { field: 'customer_name', sort: 'true', filter: 'true' }} Customer
30
+ %th{data: { field: 'created_at', sort: 'true', filter: 'false' }} Created
31
+ %th
32
+ %tr.filters
33
+ %th
34
+ %input{data: {field: 'email'}}
35
+ %th
36
+ %input{data: {field: 'first_name'}}
37
+ %th
38
+ %input{data: {field: 'last_name'}}
39
+ %th
40
+ %input{data: {field: 'customer_name'}}
41
+ %th
42
+ %th
43
+ %tbody
44
+ %tr.no-results.hide
45
+ %td
46
+ %h4 No Results Found
47
+ %td
48
+ %td
49
+ %td
50
+ %td
51
+ %td
52
+ %tcaption
53
+ .grid-pager
54
+ %ul.pagination
55
+ %li
56
+ %button#first
57
+ First
58
+ %li
59
+ %button#previous
60
+ Back
61
+ %li#pagedisplay
62
+ %li
63
+ %button#next
64
+ Next
65
+ %li
66
+ %button#last
67
+ Last
68
+ .pagination
69
+ Results per page:
70
+ #pagesize
71
+ ```
72
+ 2. Create a partial for each row of the table. By default the partial name is ```_row.html.haml```
73
+ ```html
74
+ %tr
75
+ %td= user.email
76
+ %td= user.first_name
77
+ %td= user.last_name
78
+ %td= user.customer.name
79
+ %td= l(user.created_at.to_date)
80
+ %td
81
+ ```
82
+ 3. Define the fields and how they are accessed in the ActiveRecord Model
83
+ ```ruby
84
+ class User < ActiveRecord::Base
85
+ extend GridTable::Model
86
+
87
+ belongs_to :customer
88
+
89
+ grid_table_control :email
90
+ grid_table_control :first_name
91
+ grid_table_control :last_name
92
+ grid_table_control :created_at
93
+ grid_table_control :customer_name,
94
+ source: :customer,
95
+ source_column: 'name'
96
+ end
97
+ ```
98
+ 4. Setup the controller handle the HTML response and the JS response that does the lookup of the data
99
+ ```ruby
100
+ class UsersController < ApplicationController
101
+ def index
102
+ respond_to do |format|
103
+ format.html {}
104
+ format.js { grid_table_for(Users.all, index_params) }
105
+ end
106
+ end
107
+
108
+ private
109
+
110
+ def index_params
111
+ params.permit [].concat(User.grid_table_strong_params)
112
+ end
113
+ end
114
+ ```
115
+
116
+ TODO: Fill out details about options available other than defaults
117
+
118
+ ## Contributing
119
+
120
+ 1. Fork it ( https://github.com/[my-github-username]/gridtable/fork )
121
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
122
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
123
+ 4. Push to the branch (`git push origin my-new-feature`)
124
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'grid_table/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "grid_table"
8
+ spec.version = GridTable::VERSION
9
+ spec.authors = ["Jon Principe", "Mike Raimondi"]
10
+ spec.email = ["jp@adharmonics.com"]
11
+ spec.summary = %q{Utility for powerful HTML Tables}
12
+ spec.description = %q{Library to help manage powerful HTML Tables through the Model, View and Controller.}
13
+ spec.homepage = "http://github.com/jprincipe/grid_table"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.6"
22
+ spec.add_development_dependency "rake"
23
+ end
@@ -0,0 +1,131 @@
1
+ class GridTable::Control
2
+ include ActiveModel::Model
3
+
4
+ attr_writer :model, :attribute, :source, :source_class, :source_column, :filter, :polymorphic
5
+
6
+ def filter(param_filter_value, records)
7
+ unless @filter == false
8
+ arel_query = nil
9
+ strategy_map = {
10
+ exact_match: ->(col) { col.eq(param_filter_value) },
11
+ prefix: ->(col) { col.matches("#{param_filter_value}%") },
12
+ suffix: ->(col) { col.matches("%#{param_filter_value}") },
13
+ fuzzy: ->(col) { col.matches("%#{param_filter_value}%") },
14
+ array: ->(col) { "#{column.to_s} @> ARRAY[#{[param_filter_value].flatten.join(',')}]" }
15
+ }
16
+
17
+ polymorphic_models.each_with_index do |klass, i|
18
+ # TODO implement array filtering
19
+ if i == 0
20
+ arel_query = strategy_map[strategy].call(klass.arel_table[column])
21
+ else
22
+ arel_query = arel_query.or(strategy_map[strategy].call(klass.arel_table[column]))
23
+ end
24
+ end
25
+
26
+ arel_query ||= strategy_map[strategy].call(source_table[column])
27
+ prepared_records(records).where(arel_query)
28
+ end
29
+ end
30
+
31
+ def sort(param_sort_order, records)
32
+ sort_order = %w[asc, desc].include?(param_sort_order) ? param_sort_order : 'asc'
33
+
34
+ if @polymorphic
35
+ models = polymorphic_models
36
+ if models.present?
37
+ prepared_records(records).select("\"#{@model.to_s.tableize}\".*, #{polymorphic_select_sql(models)} AS #{active_source}")
38
+ .order("#{active_source} #{sort_order}")
39
+ else
40
+ records
41
+ end
42
+ else
43
+ prepared_records(records).order("#{table_with_column} #{sort_order}")
44
+ end
45
+ end
46
+
47
+ def url_param
48
+ @attribute
49
+ end
50
+
51
+ private
52
+
53
+ def prepared_records(records)
54
+ if @polymorphic
55
+ polymorphic_models.each do |klass|
56
+ records = records.joins("LEFT OUTER JOIN #{klass.table_name} ON #{model_fk}_id = #{klass.table_name}.id AND #{model_fk}_type = '#{klass}'")
57
+ end
58
+ records
59
+ else
60
+ joined_control? ? records.includes(active_source).references(active_source) : records
61
+ end
62
+ end
63
+
64
+ def column
65
+ @source_column || @attribute
66
+ end
67
+
68
+ def active_source
69
+ @source || @model
70
+ end
71
+
72
+ def joined_control?
73
+ @model != active_source
74
+ end
75
+
76
+ def strategy
77
+ @filter || :fuzzy
78
+ end
79
+
80
+ def source_table
81
+ klass = Object.const_get(@source_class || active_source.to_s.classify)
82
+ klass.arel_table
83
+ end
84
+
85
+ def table_with_column
86
+ "#{source_table.name}.#{column}"
87
+ end
88
+
89
+ def model_fk
90
+ "#{@model.to_s.tableize}.#{@source}"
91
+ end
92
+
93
+ def polymorphic_select_sql(models)
94
+ sql = ''
95
+
96
+ models.each_with_index do |klass, i|
97
+ if models.length == 1
98
+ sql = "#{klass.table_name}.#{column}"
99
+ elsif i == 0
100
+ sql << "(CASE WHEN #{klass.table_name}.#{column} IS NOT NULL THEN #{klass.table_name}.#{column}"
101
+ elsif i == models.length - 1
102
+ sql << " ELSE #{klass.table_name}.#{column} END)"
103
+ else
104
+ sql << " ELSIF #{klass.table_name}.#{column} IS NOT NULL THEN #{klass.table_name}.#{column}"
105
+ end
106
+ end
107
+
108
+ sql
109
+ end
110
+
111
+ def polymorphic_models
112
+ return [] unless @polymorphic
113
+
114
+ if @polymorphic_models.blank?
115
+ col = (active_source.to_s + '_type').to_sym
116
+ @polymorphic_models = Object.const_get(@model.to_s.classify)
117
+ .select(col)
118
+ .uniq
119
+ .where.not(col => nil)
120
+ .pluck(col).map { |klass| Object.const_get(klass) }
121
+ end
122
+
123
+ @polymorphic_models
124
+ end
125
+
126
+ class << self
127
+ def find_by_param(param, controls)
128
+ controls.detect { |control| control.url_param == param.try(:to_sym) }
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,35 @@
1
+ module GridTable
2
+ module Controller
3
+ def grid_table_for(resource, params, options = {})
4
+ grid_table = resource.grid_table
5
+ grid_table.populate!(resource, params)
6
+
7
+ if block_given?
8
+ yield grid_table.records, grid_table.total_rows
9
+ else
10
+ rows = []
11
+
12
+ local = options[:local].try(:to_sym) || grid_table.records.klass.name.demodulize.underscore.to_sym
13
+ grid_table.records.each do |record|
14
+ rows << (render_to_string partial: (options[:partial] || 'row'), locals: { local => record })
15
+ end
16
+
17
+ render json: { total_rows: grid_table.total_rows, rows: rows }
18
+ end
19
+ end
20
+
21
+ def grid_table_export_for(resource, params, options = {})
22
+ grid_table = resource.grid_table
23
+ params[:skip_paging] ||= true
24
+ grid_table.populate!(resource, params)
25
+
26
+ if block_given?
27
+ yield grid_table.records
28
+ else
29
+ csv = grid_table.records.klass.to_csv(grid_table.records)
30
+
31
+ send_data csv, filename: "#{grid_table.records.klass.name.demodulize.underscore}.csv"
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,14 @@
1
+ module GridTable
2
+ module Model
3
+ attr_accessor :grid_table
4
+
5
+ def grid_table_control(attribute, options = {})
6
+ self.grid_table ||= GridTable::Table.new
7
+ self.grid_table.add_control(self, attribute, options)
8
+ end
9
+
10
+ def grid_table_strong_params
11
+ self.grid_table.strong_params
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,72 @@
1
+ class GridTable::Table
2
+ attr_reader :records, :total_rows
3
+
4
+ def initialize
5
+ @controls = []
6
+ end
7
+
8
+ def add_control(model, attribute, options)
9
+ @controls << GridTable::Control.new(
10
+ {
11
+ model: model.name.underscore.to_sym,
12
+ attribute: attribute,
13
+ source: options[:source],
14
+ source_class: options[:source_class],
15
+ source_column: options[:source_column],
16
+ filter: options[:filter],
17
+ polymorphic: options[:polymorphic]
18
+ })
19
+ end
20
+
21
+ def populate!(resource, params)
22
+ @params = params
23
+ @records = resource
24
+
25
+ filter!
26
+ sort!
27
+ @total_rows = @records.size
28
+ page! unless params[:skip_paging]
29
+
30
+ @records
31
+ end
32
+
33
+ def strong_params
34
+ @controls.inject(common_strong_params) do |all_params, control|
35
+ all_params << control.url_param
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def common_strong_params
42
+ [:page, :page_size, :sort, :sort_order]
43
+ end
44
+
45
+ def page
46
+ (@params[:page] || 0).to_i
47
+ end
48
+
49
+ def page_size
50
+ (@params[:page_size] || 10).to_i
51
+ end
52
+
53
+ def filter!
54
+ @params.each do |attribute, attribute_value|
55
+ control = GridTable::Control.find_by_param(attribute, @controls)
56
+ @records = control.filter(attribute_value, @records) if control.present?
57
+ end
58
+ end
59
+
60
+ def sort!
61
+ control = GridTable::Control.find_by_param(@params[:sort], @controls)
62
+
63
+ if control.present?
64
+ @records = control.sort(@params[:sort_order], records)
65
+ end
66
+ end
67
+
68
+ def page!
69
+ @records = @records.offset(page * page_size).limit(page_size)
70
+ end
71
+
72
+ end
@@ -0,0 +1,3 @@
1
+ module GridTable
2
+ VERSION = "1.0.0"
3
+ end
data/lib/grid_table.rb ADDED
@@ -0,0 +1,10 @@
1
+ require "grid_table/version"
2
+ require "grid_table/control"
3
+ require "grid_table/table"
4
+ require "grid_table/controller"
5
+ require "grid_table/model"
6
+
7
+ module GridTable
8
+ class Engine < ::Rails::Engine
9
+ end
10
+ end
@@ -0,0 +1,482 @@
1
+ var GridTable;
2
+
3
+ $(function() {
4
+ $('[data-grid-table-sort]').on('change', function() {
5
+ var gridtable;
6
+ gridtable = GridTableFactory.get($(this));
7
+ return gridtable.refresh((function(_this) {
8
+ return function() {
9
+ var $checked, n, url;
10
+ n = _this.name;
11
+ gridtable = GridTableFactory.get(_this);
12
+ url = gridtable.getUrl();
13
+ gridtable.setFilter(n, null, {
14
+ skip_load: true
15
+ });
16
+ if (_this.type === 'checkbox') {
17
+ $checked = $(':checkbox[name="' + n + '"]:checked');
18
+ if ($checked.length > 0) {
19
+ url += '?' + ($checked.map(function() {
20
+ return "" + n + "=" + this.value;
21
+ }).toArray().join('&'));
22
+ }
23
+ return gridtable.setUrl(url);
24
+ } else {
25
+ return gridtable.setUrl(updateQueryString(n, _this.value, url));
26
+ }
27
+ };
28
+ })(this));
29
+ });
30
+ return $('.grid-table').each(function() {
31
+ var $table;
32
+ $table = $(this);
33
+ return GridTableFactory.createGridTable($table).loadGridTable($table);
34
+ });
35
+ });
36
+
37
+ window.GridTableFactory = (function() {
38
+ function GridTableFactory() {}
39
+
40
+ GridTableFactory.gridTableList = [];
41
+
42
+ GridTableFactory.defaultGridTableId = 'default-grid-table';
43
+
44
+ GridTableFactory.get = function(obj) {
45
+ var $gt, id;
46
+ if (typeof obj === 'object') {
47
+ id = $(obj).data('grid-table-id');
48
+ } else {
49
+ id = obj;
50
+ }
51
+ return $gt = this.gridTableList[id || this.defaultGridTableId];
52
+ };
53
+
54
+ GridTableFactory.createGridTable = function(table, params) {
55
+ var $table, existing_table, gridTable;
56
+ if ((existing_table = this.get(table)) != null) {
57
+ throw new Error(existing_table);
58
+ }
59
+ $table = $(table);
60
+ gridTable = new GridTable(params);
61
+ $table.on('ajax:success', 'a, button', function() {
62
+ gridTable = GridTableFactory.get($table);
63
+ return gridTable.refresh();
64
+ });
65
+ this.gridTableList[$table.data('grid-table-id') || this.defaultGridTableId] = gridTable;
66
+ return gridTable;
67
+ };
68
+
69
+ return GridTableFactory;
70
+
71
+ })();
72
+
73
+ GridTable = (function() {
74
+ var GridTableParams, sortIcons;
75
+
76
+ sortIcons = {
77
+ "default": 'fi-sort',
78
+ asc: 'fi-sort-down',
79
+ desc: 'fi-sort-up'
80
+ };
81
+
82
+ GridTable.prototype.gridTableParams = null;
83
+
84
+ GridTable.prototype.gridTableDOM = null;
85
+
86
+ GridTable.prototype.loadDataCompleteCallback = null;
87
+
88
+ GridTable.prototype.loadDataStartCallback = null;
89
+
90
+ GridTable.prototype.loadDataErrorCallback = null;
91
+
92
+ function GridTable(params) {
93
+ this.gridTableParams = new GridTableParams(params);
94
+ }
95
+
96
+ GridTable.prototype.loadGridTable = function(table, params) {
97
+ if (params == null) {
98
+ params = {};
99
+ }
100
+ this.gridTableDOM = $(table);
101
+ this.gridTableParams.setId(this.gridTableDOM.data('grid-table-id'));
102
+ if (this.gridTableDOM.attr('data-page-size')) {
103
+ this.gridTableParams.setPageSize(this.gridTableDOM.data('page-size'));
104
+ }
105
+ this.gridTableParams.setUrl(this.gridTableDOM.data('url'));
106
+ this.gridTableDOM.find('thead th[data-sort="true"], .thead [data-sort="true"]').each((function(_this) {
107
+ return function(index, column) {
108
+ var $column;
109
+ $column = $(column);
110
+ $column.append(" <i class='" + sortIcons['default'] + "'></i>");
111
+ if ($column.data('default-sort')) {
112
+ _this.setSort($column.data('field'), $column.data('default-sort'));
113
+ }
114
+ return $column.on('click', function(event) {
115
+ _this.gridTableParams.setSort($(event.currentTarget).data('field'), null);
116
+ return _this.loadData();
117
+ });
118
+ };
119
+ })(this));
120
+ this.gridTableDOM.find('select.row-filter').each((function(_this) {
121
+ return function(index, filter) {
122
+ return $(filter).on("change", function(event) {
123
+ _this.gridTableParams.setFilter($(filter).data('field'), $(filter).val());
124
+ return _this.loadData();
125
+ });
126
+ };
127
+ })(this));
128
+ this.gridTableDOM.find('input.row-filter').each((function(_this) {
129
+ return function(index, filter) {
130
+ var timeout;
131
+ _this.gridTableParams.setFilter($(filter).data('field'), $(filter).val());
132
+ timeout = null;
133
+ return $(filter).on("propertychange keyup input paste", function(event) {
134
+ clearTimeout(timeout);
135
+ return timeout = setTimeout((function() {
136
+ _this.gridTableParams.setFilter($(filter).data('field'), $(filter).val());
137
+ return _this.loadData();
138
+ }), 500);
139
+ });
140
+ };
141
+ })(this));
142
+ this.gridTableDOM.find('.grid-pager #pagesize').each((function(_this) {
143
+ return function(index, elem) {
144
+ var pageSizeSelect, size, _i, _len, _ref;
145
+ pageSizeSelect = '<select id="page-size-select">';
146
+ _ref = _this.gridTableParams.pageSizeOptions;
147
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
148
+ size = _ref[_i];
149
+ if (size === _this.gridTableParams.pageSize) {
150
+ pageSizeSelect += "<option selected value=\"" + size + "\">" + size + "</option>";
151
+ } else {
152
+ pageSizeSelect += "<option value=\"" + size + "\">" + size + "</option>";
153
+ }
154
+ }
155
+ pageSizeSelect += '</select>';
156
+ $(elem).append(pageSizeSelect);
157
+ return $(elem).find('#page-size-select').on("change", function(event) {
158
+ return _this.setPageSize($(event.currentTarget).val());
159
+ });
160
+ };
161
+ })(this));
162
+ this.loadData(params);
163
+ return $('.export[data-grid-table-id="' + this.gridTableParams.id + '"]').on('click', (function(_this) {
164
+ return function(event) {
165
+ return _this.exportData();
166
+ };
167
+ })(this));
168
+ };
169
+
170
+ GridTable.prototype.refresh = function(callback) {
171
+ if (typeof callback === "function") {
172
+ callback(callback);
173
+ }
174
+ return this.loadData();
175
+ };
176
+
177
+ GridTable.prototype.setId = function(id) {
178
+ return this.gridTableParams.setId(id);
179
+ };
180
+
181
+ GridTable.prototype.setUrl = function(url) {
182
+ return this.gridTableParams.setUrl(url);
183
+ };
184
+
185
+ GridTable.prototype.getUrl = function() {
186
+ return this.gridTableParams.url;
187
+ };
188
+
189
+ GridTable.prototype.setFilter = function(key, value, options) {
190
+ if (options == null) {
191
+ options = {};
192
+ }
193
+ this.gridTableParams.setFilter(key, value);
194
+ if (this.gridTableDOM !== null && !options.skip_load) {
195
+ return this.loadData();
196
+ }
197
+ };
198
+
199
+ GridTable.prototype.setSort = function(column, direction) {
200
+ this.gridTableParams.setSort(column, direction);
201
+ if (this.gridTableDOM !== null) {
202
+ return this.loadData();
203
+ }
204
+ };
205
+
206
+ GridTable.prototype.loadDataStart = function(callback) {
207
+ return this.loadDataStartCallback = callback;
208
+ };
209
+
210
+ GridTable.prototype.loadDataComplete = function(callback) {
211
+ return this.loadDataCompleteCallback = callback;
212
+ };
213
+
214
+ GridTable.prototype.loadDataError = function(callback) {
215
+ return this.loadDataErrorCallback = callback;
216
+ };
217
+
218
+ GridTable.prototype.buildUrl = function(baseUrl) {
219
+ return this.gridTableParams.buildUrl(baseUrl, true);
220
+ };
221
+
222
+ GridTable.prototype.setPage = function(page) {
223
+ this.gridTableParams.page = page;
224
+ return this.loadData();
225
+ };
226
+
227
+ GridTable.prototype.setPageSize = function(size) {
228
+ this.gridTableParams.pageSize = size;
229
+ this.gridTableParams.page = 0;
230
+ return this.loadData();
231
+ };
232
+
233
+ GridTable.prototype.loadData = function(params) {
234
+ if (params == null) {
235
+ params = {};
236
+ }
237
+ if (params.globalAjax == null) {
238
+ params.globalAjax = true;
239
+ }
240
+ if (typeof this.loadDataStartCallback === "function") {
241
+ this.loadDataStartCallback();
242
+ }
243
+ return $.ajax(this.gridTableParams.buildUrl(this.gridTableParams.url), {
244
+ type: 'GET',
245
+ global: params.globalAjax,
246
+ dataType: 'json',
247
+ error: (function(_this) {
248
+ return function(jqXHR, textStatus, errorThrown) {
249
+ if (typeof _this.loadDataErrorCallback === "function") {
250
+ return _this.loadDataErrorCallback();
251
+ }
252
+ };
253
+ })(this),
254
+ success: (function(_this) {
255
+ return function(data, textStatus, jqXHR) {
256
+ var row, _i, _len, _ref;
257
+ _this.gridTableDOM.find('tbody, .tbody').children().not('.no-results').remove();
258
+ _this.gridTableDOM.find('.no-results').addClass('hide');
259
+ if (data.totals) {
260
+ _this.gridTableDOM.find('thead tr.totals, .thead tr.totals, .thead .tr.totals').html(data.totals);
261
+ }
262
+ if (data.rows.length === 0) {
263
+ _this.gridTableDOM.find('.no-results').removeClass('hide');
264
+ } else {
265
+ _ref = data.rows;
266
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
267
+ row = _ref[_i];
268
+ _this.gridTableDOM.find('tbody, .tbody').append(row);
269
+ }
270
+ }
271
+ _this.updateSortDisplay();
272
+ _this.updatePagerDisplay(data.total_rows);
273
+ if (typeof _this.loadDataCompleteCallback === "function") {
274
+ return _this.loadDataCompleteCallback();
275
+ }
276
+ };
277
+ })(this)
278
+ });
279
+ };
280
+
281
+ GridTable.prototype.exportData = function() {
282
+ var baseUrl, url;
283
+ url = this.gridTableParams.url.split('?');
284
+ if (url.length === 1) {
285
+ baseUrl = url[0] + '.csv';
286
+ } else {
287
+ baseUrl = url[0] + '.csv?' + url[1];
288
+ }
289
+ return window.open(this.gridTableParams.buildUrl(baseUrl));
290
+ };
291
+
292
+ GridTable.prototype.updatePagerDisplay = function(total_rows) {
293
+ var back_enabled, display, first, forward_enabled, last, last_page, next, pager, previous;
294
+ pager = this.gridTableDOM.find('.grid-pager');
295
+ first = $(pager).find('#first');
296
+ previous = $(pager).find('#previous');
297
+ next = $(pager).find('#next');
298
+ last = $(pager).find('#last');
299
+ display = $(pager).find('#pagedisplay');
300
+ $(first).off('click');
301
+ $(previous).off('click');
302
+ $(next).off('click');
303
+ $(last).off('click');
304
+ last_page = Math.floor(total_rows / this.gridTableParams.pageSize);
305
+ if (total_rows % this.gridTableParams.pageSize === 0) {
306
+ last_page -= 1;
307
+ }
308
+ back_enabled = this.gridTableParams.page > 0;
309
+ forward_enabled = this.gridTableParams.page < last_page;
310
+ if (back_enabled) {
311
+ $(first).removeClass('disabled');
312
+ $(first).on('click', (function(_this) {
313
+ return function(event) {
314
+ event.preventDefault();
315
+ return _this.setPage(0);
316
+ };
317
+ })(this));
318
+ $(previous).removeClass('disabled');
319
+ $(previous).on('click', (function(_this) {
320
+ return function(event) {
321
+ event.preventDefault();
322
+ return _this.setPage(_this.gridTableParams.page - 1);
323
+ };
324
+ })(this));
325
+ } else {
326
+ $(first).addClass('disabled');
327
+ $(previous).addClass('disabled');
328
+ }
329
+ if (forward_enabled) {
330
+ $(next).removeClass('disabled');
331
+ $(next).on('click', (function(_this) {
332
+ return function(event) {
333
+ event.preventDefault();
334
+ return _this.setPage(_this.gridTableParams.page + 1);
335
+ };
336
+ })(this));
337
+ $(last).removeClass('disabled');
338
+ $(last).on('click', (function(_this) {
339
+ return function(event) {
340
+ event.preventDefault();
341
+ return _this.setPage(last_page);
342
+ };
343
+ })(this));
344
+ } else {
345
+ $(next).addClass('disabled');
346
+ $(last).addClass('disabled');
347
+ }
348
+ return display.text("" + (this.gridTableParams.page + 1) + " of " + (last_page + 1) + " (" + total_rows + ")");
349
+ };
350
+
351
+ GridTable.prototype.updateSortDisplay = function() {
352
+ var field, sortOrder;
353
+ field = this.gridTableParams.sortCol;
354
+ sortOrder = this.gridTableParams.sortOrder;
355
+ return this.gridTableDOM.find('thead th[data-sort="true"], .thead [data-sort="true"]').each((function(_this) {
356
+ return function(i, c) {
357
+ var value;
358
+ value = $(c).data('field');
359
+ if (value === field) {
360
+ switch (sortOrder) {
361
+ case 'asc':
362
+ $(c).addClass('sorting');
363
+ return $(c).find('i').attr('class', sortIcons['asc']);
364
+ case 'desc':
365
+ $(c).addClass('sorting');
366
+ return $(c).find('i').attr('class', sortIcons['desc']);
367
+ default:
368
+ $(c).removeClass('sorting');
369
+ return $(c).find('i').attr('class', sortIcons['default']);
370
+ }
371
+ } else {
372
+ $(c).removeClass('sorting');
373
+ return $(c).find('i').attr('class', sortIcons['default']);
374
+ }
375
+ };
376
+ })(this));
377
+ };
378
+
379
+ GridTableParams = (function() {
380
+ GridTableParams.prototype.id = null;
381
+
382
+ GridTableParams.prototype.url = null;
383
+
384
+ GridTableParams.prototype.sortCol = '';
385
+
386
+ GridTableParams.prototype.sortOrder = '';
387
+
388
+ GridTableParams.prototype.filter = {};
389
+
390
+ GridTableParams.prototype.page = 0;
391
+
392
+ GridTableParams.prototype.pageSize = 10;
393
+
394
+ GridTableParams.prototype.pageSizeOptions = [5, 10, 25, 50, 100, 200];
395
+
396
+ function GridTableParams(params) {
397
+ if ((params != null)) {
398
+ if ('sortCol' in params) {
399
+ this.sortCol = params['sortCol'];
400
+ }
401
+ if ('sortOrder' in params) {
402
+ this.sortOrder = params['sortOrder'];
403
+ }
404
+ if ('filter' in params) {
405
+ this.filter = params['filter'];
406
+ }
407
+ if ('page' in params) {
408
+ this.page = params['page'];
409
+ }
410
+ if ('pageSize' in params) {
411
+ this.pageSize = params['pageSize'];
412
+ }
413
+ if ('id' in params) {
414
+ this.id = params['id'];
415
+ }
416
+ if ('url' in params) {
417
+ this.url = params['url'];
418
+ }
419
+ }
420
+ }
421
+
422
+ GridTableParams.prototype.setId = function(id) {
423
+ return this.id = id;
424
+ };
425
+
426
+ GridTableParams.prototype.setUrl = function(url) {
427
+ return this.url = url;
428
+ };
429
+
430
+ GridTableParams.prototype.setPageSize = function(pageSize) {
431
+ return this.pageSize = pageSize;
432
+ };
433
+
434
+ GridTableParams.prototype.setSort = function(column, direction) {
435
+ var order;
436
+ this.page = 0;
437
+ if (this.sortCol === column) {
438
+ order = this.sortOrder === 'asc' ? 'desc' : 'asc';
439
+ } else {
440
+ order = 'asc';
441
+ }
442
+ this.sortOrder = direction || order;
443
+ return this.sortCol = column;
444
+ };
445
+
446
+ GridTableParams.prototype.setFilter = function(column, value) {
447
+ this.page = 0;
448
+ if (value === null || value.trim().length === 0) {
449
+ return delete this.filter[column];
450
+ } else {
451
+ return this.filter[column] = value;
452
+ }
453
+ };
454
+
455
+ GridTableParams.prototype.buildUrl = function(baseUrl, skip_paging) {
456
+ var k, url, v, _ref;
457
+ if (skip_paging == null) {
458
+ skip_paging = false;
459
+ }
460
+ url = baseUrl;
461
+ url += /\?/.test(url) ? '&' : '?';
462
+ if (!skip_paging) {
463
+ url += 'page=' + this.page;
464
+ url += "&page_size=" + this.pageSize;
465
+ url += "&sort=" + this.sortCol;
466
+ url += "&sort_order=" + this.sortOrder;
467
+ }
468
+ _ref = this.filter;
469
+ for (k in _ref) {
470
+ v = _ref[k];
471
+ url += '&' + k + '=' + v;
472
+ }
473
+ return url;
474
+ };
475
+
476
+ return GridTableParams;
477
+
478
+ })();
479
+
480
+ return GridTable;
481
+
482
+ })();
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: grid_table
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Jon Principe
8
+ - Mike Raimondi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-11-03 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: '1.6'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ version: '1.6'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ description: Library to help manage powerful HTML Tables through the Model, View and
43
+ Controller.
44
+ email:
45
+ - jp@adharmonics.com
46
+ executables: []
47
+ extensions: []
48
+ extra_rdoc_files: []
49
+ files:
50
+ - .gitignore
51
+ - Gemfile
52
+ - LICENSE.txt
53
+ - README.md
54
+ - Rakefile
55
+ - grid_table.gemspec
56
+ - lib/grid_table.rb
57
+ - lib/grid_table/control.rb
58
+ - lib/grid_table/controller.rb
59
+ - lib/grid_table/model.rb
60
+ - lib/grid_table/table.rb
61
+ - lib/grid_table/version.rb
62
+ - vendor/assets/javascripts/gridtable.js
63
+ homepage: http://github.com/jprincipe/grid_table
64
+ licenses:
65
+ - MIT
66
+ metadata: {}
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubyforge_project:
83
+ rubygems_version: 2.0.14
84
+ signing_key:
85
+ specification_version: 4
86
+ summary: Utility for powerful HTML Tables
87
+ test_files: []