grid_table 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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: []