tidy-table-rails 2.0.5

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: c4238f2a416eaf00ca21668c6a25cc9c9140b39c
4
+ data.tar.gz: 48c6ae4a96d42d59b95f3a02fc6e971a28890ad2
5
+ SHA512:
6
+ metadata.gz: dd4beecca4a8579493b522d34661d4b11107a85107ce95bbc663fd837e2df7b53ebbb36a9c775e4b13a9cfae07527e978478497dc59a50eeb5b2a8969def6325
7
+ data.tar.gz: acf4f0332d518a2e16635ffb07d970460b36535069feb8d6678e5fd71d13132a37760e5ac7989c22c96d12859f673cb427fa541b9c234792a4eabcff9389d497
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in tidy_table-rails.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Damian Baćkowski
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,37 @@
1
+ # Tidy::Table::Rails
2
+
3
+ Asset pipeline bundling of the tidy table jquery plugin (https://labs.mbrooks.info/demos/Tidy-Table/).
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'tidy-table-rails'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install tidy-table-rails
18
+
19
+ In your application.css.scss:
20
+
21
+ *= require tidy-table
22
+
23
+ And in your application.js:
24
+
25
+ //= require tidy-table
26
+
27
+ ## Usage
28
+
29
+ https://labs.mbrooks.info/demos/Tidy-Table/
30
+
31
+ ## Contributing
32
+
33
+ 1. Fork it
34
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
35
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
36
+ 4. Push to the branch (`git push origin my-new-feature`)
37
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,7 @@
1
+ module Tidy
2
+ module Table
3
+ module Rails
4
+ VERSION = "2.0.5"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ require "tidy/table/rails/version"
2
+
3
+ module Tidy
4
+ module Table
5
+ module Rails
6
+ class Engine < ::Rails::Engine
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'tidy/table/rails/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "tidy-table-rails"
8
+ spec.version = Tidy::Table::Rails::VERSION
9
+ spec.authors = ["dbackowski"]
10
+ spec.email = ["damianbackowski@gmail.com"]
11
+ spec.summary = %q{Create a HTML table from JSON that can be sorted, selected, and post-processed using a simple callback.}
12
+ spec.description = %q{Asset pipeline bundling of the tidy table jquery plugin.}
13
+ spec.homepage = "https://github.com/dbackowski/tidy-table-rails"
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_runtime_dependency 'jquery-rails', '>= 3.0.0', '< 5.0'
22
+ spec.add_development_dependency "bundler", "~> 1.7"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ end
@@ -0,0 +1,434 @@
1
+ /**
2
+ * Tidy Table
3
+ * Generate a sortable HTML table from JSON
4
+ *
5
+ * Copyright 2012-2015, Marc S. Brooks (http://mbrooks.info)
6
+ * Licensed under the MIT license:
7
+ * http://www.opensource.org/licenses/mit-license.php
8
+ *
9
+ * Dependencies:
10
+ * jquery.js
11
+ */
12
+
13
+ if (!window.jQuery || (window.jQuery && parseInt(window.jQuery.fn.jquery.replace('.', '')) < parseInt('1.8.3'.replace('.', '')))) {
14
+ throw new Error('Tidy-Table requires jQuery 1.8.3 or greater.');
15
+ }
16
+
17
+ (function($) {
18
+
19
+ /**
20
+ * @namespace TidyTable
21
+ */
22
+ var methods = {
23
+
24
+ /**
25
+ * Create new instance of Tidy-Table
26
+ * @memberof TidyTable
27
+ * @method init
28
+ * @param {Object} settings
29
+ * @param {Object} config
30
+ * @returns {Object} jQuery object
31
+ */
32
+ "init": function(settings, config) {
33
+ var $this = $(this),
34
+ data = $this.data();
35
+
36
+ // default settings
37
+ var defaults = {
38
+ enableCheckbox: false,
39
+ enableMenu: false,
40
+ reverseSortDir: false
41
+ };
42
+
43
+ if (arguments.length > 1) {
44
+ $.extend(defaults, settings);
45
+ }
46
+ else {
47
+ config = settings;
48
+ }
49
+
50
+ // config defaults
51
+ config = $.extend({
52
+ sortByPattern: function(col_num, val) {
53
+ if ( $.trim(col_num) ) {
54
+ return String(val).replace(/$|%|#/g, '');
55
+ }
56
+ }
57
+ }, config);
58
+
59
+ if ( $.isEmptyObject(data) ) {
60
+ $this.data({
61
+ settings: defaults,
62
+ config: config
63
+ });
64
+ }
65
+
66
+ return $this.TidyTable('_createTable');
67
+ },
68
+
69
+ /**
70
+ * Perform cleanup
71
+ * @memberof TidyTable
72
+ * @method destroy
73
+ */
74
+ "destroy": function() {
75
+ $(this).removeData();
76
+ },
77
+
78
+ /**
79
+ * Create HTML table elements
80
+ * @memberof TidyTable
81
+ * @method _createTable
82
+ * @param {String} num
83
+ * @param {String} order
84
+ * @returns {Object} jQuery object
85
+ * @private
86
+ */
87
+ "_createTable": function(num, order) {
88
+ var $this = $(this),
89
+ data = $this.data();
90
+
91
+ // create reusable elements
92
+ var table = $('<table></table>')
93
+ .addClass('tidy_table');
94
+
95
+ table.mousedown(function() { return false; });
96
+ table.mouseover(function() { return false; });
97
+
98
+ var thead = $('<thead></thead>'),
99
+ tbody = $('<tbody></tbody>');
100
+
101
+ // .. <THEAD>
102
+ (function() {
103
+ var row = $('<tr></tr>');
104
+
105
+ for (var i = 0; i < data.config.columnTitles.length; i++) {
106
+ var title = data.config.columnTitles[i];
107
+
108
+ var col = $('<th></th>')
109
+ .append(title)
110
+ .attr('title', title);
111
+ row.append(col);
112
+
113
+ var col_class;
114
+
115
+ // determine column result ordet
116
+ if (!data.settings.reverseSortDir) {
117
+ if (order == 'asc' || !order) {
118
+ col_class = 'sort_asc';
119
+ col.order = 'desc';
120
+ }
121
+ else {
122
+ col_class = 'sort_desc';
123
+ col.order = 'asc';
124
+ }
125
+ }
126
+ else {
127
+ if (order == 'desc' || !order) {
128
+ col_class = 'sort_asc';
129
+ col.order = 'asc';
130
+ }
131
+ else {
132
+ col_class = 'sort_desc';
133
+ col.order = 'desc';
134
+ }
135
+ }
136
+
137
+ // highlight selected column
138
+ if (num == i) {
139
+ col.addClass(col_class);
140
+ }
141
+
142
+ // attach sorting event to each column
143
+ col.on('click', {
144
+ col_number: i,
145
+ sort_order: (num == i) ? col.order : 'asc'
146
+ },
147
+ function(event) {
148
+ $this.TidyTable('_sortByColumn', event.data.col_number, event.data.sort_order);
149
+ });
150
+ }
151
+
152
+ thead.append(row);
153
+ })();
154
+
155
+ // .. <TBODY>
156
+ (function() {
157
+ var vals = data.config.columnValues;
158
+
159
+ for (var j = 0; j < vals.length; j++) {
160
+ var row = $('<tr></tr>');
161
+
162
+ for (var k = 0; k < vals[j].length; k++) {
163
+ var val = vals[j][k];
164
+
165
+ var col = $('<td></td>')
166
+ .append(val)
167
+ .attr('title', val);
168
+ row.append(col);
169
+
170
+ // post-process table column HTML object
171
+ if (data.config.postProcess && $.isFunction(data.config.postProcess.column)) {
172
+ data.config.postProcess.column(col);
173
+ }
174
+ }
175
+
176
+ tbody.append(row);
177
+ }
178
+
179
+ table.append(thead);
180
+ table.append(tbody);
181
+
182
+ // append check boxes to beginning each row
183
+ if (data.settings && data.settings.enableCheckbox) {
184
+ var rows = table.find('tr');
185
+
186
+ rows.each(function(index) {
187
+ var input = $('<input></input>')
188
+ .attr('type', 'checkbox');
189
+
190
+ var col;
191
+
192
+ // first row is always the header
193
+ if (index === 0) {
194
+ col = $('<th></th>');
195
+
196
+ // attach event to check all boxes
197
+ input.on('click', function() {
198
+ $this.TidyTable('_toggleSelRows', rows);
199
+ });
200
+ }
201
+ else {
202
+ col = $('<td></td>');
203
+
204
+ // attach event to each checkbox
205
+ input.on('click', {
206
+ box_number: index
207
+ },
208
+ function(event) {
209
+ $this.TidyTable('_toggleSelRows', rows, event.data.box_number);
210
+ });
211
+ }
212
+
213
+ col.append(input);
214
+
215
+ // insert before first cell
216
+ $(this).prepend(col);
217
+ });
218
+ }
219
+ })();
220
+
221
+ // post-process table results HTML object
222
+ if (data.config.postProcess && $.isFunction(data.config.postProcess.table)) {
223
+ data.config.postProcess.table(table);
224
+ }
225
+
226
+ var block = $this.children('table.tidy_table');
227
+
228
+ // if table exists, perform an in-place update of the element
229
+ if (block[0]) {
230
+ block.replaceWith(table);
231
+ }
232
+
233
+ // generate table/menu elements
234
+ else {
235
+ if (data.settings && data.settings.enableMenu) {
236
+ $this.append(
237
+ $this.TidyTable('_createMenu', table, 'options')
238
+ );
239
+ }
240
+
241
+ $this.append(table);
242
+ }
243
+
244
+ return table;
245
+ },
246
+
247
+ /**
248
+ * Create HTML select menu element
249
+ * @memberof TidyTable
250
+ * @method _createMenu
251
+ * @param {Object} table jQuery object
252
+ * @param {String} name
253
+ * @returns {Object} jQuery object
254
+ * @private
255
+ */
256
+ "_createMenu": function(table, name) {
257
+ var $this = $(this),
258
+ data = $this.data();
259
+
260
+ // create reusable elements
261
+ var select = $('<select></select>')
262
+ .addClass('tidy_table ' + name)
263
+ .change(function() {
264
+ var elm = $(this);
265
+
266
+ var callback = data.config.menuOptions[ elm.val() ][1]['callback'];
267
+
268
+ // callback event
269
+ if ( $.isFunction(callback) ) {
270
+ callback( $this.TidyTable('_getCheckedAsObj', table) );
271
+ }
272
+
273
+ elm.val(0);
274
+ });
275
+
276
+ // .. options
277
+ $.each(data.config.menuOptions, function(index) {
278
+ var option = $('<option>' + data.config.menuOptions[index][0] + '</option>')
279
+ .attr('value', index);
280
+
281
+ select.append(option);
282
+ });
283
+
284
+ // post-process select menu HTML object
285
+ if (data.config.postProcess && $.isFunction(data.config.postProcess.menu)) {
286
+ data.config.postProcess.menu(select);
287
+ }
288
+
289
+ return select;
290
+ },
291
+
292
+ /**
293
+ * Return selected row values as an array
294
+ * @memberof TidyTable
295
+ * @method _getCheckedAsObj
296
+ * @param {Object} table jQuery object
297
+ * @returns {Array}
298
+ * @private
299
+ */
300
+ "_getCheckedAsObj": function(table) {
301
+ var rows = table.find('tbody > tr'),
302
+ objs = [];
303
+
304
+ for (var i = 0; i < rows.length; i++) {
305
+ var cols = rows[i].childNodes;
306
+
307
+ // if the row checkbox is selected
308
+ if (cols[0].firstChild.checked) {
309
+ var row = [];
310
+
311
+ // simulate an associative array
312
+ for (var j = 1; j < cols.length; j++) {
313
+ row[j - 1] = cols[j].textContent;
314
+ }
315
+
316
+ objs.push(row);
317
+ }
318
+ }
319
+
320
+ return objs;
321
+ },
322
+
323
+ /**
324
+ * Select/Deselect (input checkbox and row highlight)
325
+ * @memberof TidyTable
326
+ * @method _toggleSelRows
327
+ * @param {Object} rows jQuery object
328
+ * @param {Number} num
329
+ * @private
330
+ */
331
+ "_toggleSelRows": function(rows, num) {
332
+ var checked = null;
333
+
334
+ rows.each(function(index) {
335
+ var row = $(this),
336
+ input = row.find(':checkbox').first();
337
+
338
+ // update all rows
339
+ if (!num) {
340
+ if (index === 0) {
341
+ checked = (input.is(':checked')) ? true : false;
342
+ return;
343
+ }
344
+
345
+ if (checked) {
346
+ row.removeClass('check_off').addClass('check_on');
347
+ input.prop('checked', true);
348
+ }
349
+ else {
350
+ row.removeClass('check_on').addClass('check_off');
351
+ input.prop('checked', false);
352
+ }
353
+ }
354
+
355
+ // update selected row
356
+ else {
357
+ if (index === 0) {
358
+ return;
359
+ }
360
+
361
+ if (input.is(':checked')) {
362
+ row.removeClass('check_off').addClass('check_on');
363
+ input.prop('checked', true);
364
+ }
365
+ else {
366
+ row.removeClass('check_on').addClass('check_off');
367
+ input.prop('checked', false);
368
+ }
369
+ }
370
+ });
371
+ },
372
+
373
+ /**
374
+ * Display results ordered by selected column
375
+ * @memberof TidyTable
376
+ * @method _sortByColumn
377
+ * @param {Number} num
378
+ * @param {Number} order
379
+ * @private
380
+ */
381
+ "_sortByColumn": function(num, order) {
382
+ var $this = $(this),
383
+ data = $this.data();
384
+
385
+ if ( $.isFunction(data.config.sortByPattern) ) {
386
+ var reverse = (order == 'desc') ? -1 : 1;
387
+
388
+ // sort JSON object by bucket number
389
+ data.config.columnValues.sort(function(a, b) {
390
+ var str1 = data.config.sortByPattern(num, a[num]),
391
+ str2 = data.config.sortByPattern(num, b[num]);
392
+
393
+ if (isNaN(str1)) {
394
+ return [reverse * cmpAny(str1, str2)] >
395
+ [reverse * cmpAny(str2, str1)] ? -1 : 1;
396
+ }
397
+ else {
398
+ return [reverse * cmpInt(str1, str2)];
399
+ }
400
+ });
401
+ }
402
+
403
+ $this.TidyTable('_createTable', num, order);
404
+ }
405
+ };
406
+
407
+ $.fn.TidyTable = function(method) {
408
+ if (methods[method]) {
409
+ return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
410
+ }
411
+ else
412
+ if (typeof method === 'object' || !method) {
413
+ return methods.init.apply(this, arguments);
414
+ }
415
+ else {
416
+ $.error('Method ' + method + ' does not exist in jQuery.TidyTable');
417
+ }
418
+ };
419
+
420
+ /**
421
+ * Generic string comparison functions
422
+ * @param {String} a
423
+ * @param {String} b
424
+ * @returns {Number}
425
+ * @protected
426
+ */
427
+ function cmpAny(a, b) {
428
+ return (a > b) ? 1 : (a < b) ? -1 : 0;
429
+ }
430
+
431
+ function cmpInt(a, b) {
432
+ return b - a;
433
+ }
434
+ })(jQuery);
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Tidy Table
3
+ * Generate a sortable HTML table from JSON
4
+ *
5
+ * Copyright 2012-2015, Marc S. Brooks (http://mbrooks.info)
6
+ * Licensed under the MIT license:
7
+ * http://www.opensource.org/licenses/mit-license.php
8
+ *
9
+ * Dependencies:
10
+ * jquery.js
11
+ */
12
+
13
+ table.tidy_table {
14
+ background-color: #FFFFFF;
15
+ border-collapse: collapse;
16
+ border: 1px solid #CCCCCC;
17
+ cursor: pointer;
18
+ white-space: nowrap;
19
+ }
20
+
21
+ table.tidy_table thead {
22
+ border: none;
23
+ }
24
+
25
+ table.tidy_table tr.check_on {
26
+ background-color: #F5F5F5;
27
+ }
28
+
29
+ table.tidy_table tr.check_off {
30
+ background-color: #FFFFFF;
31
+ }
32
+
33
+ table.tidy_table th {
34
+ background-color: #DDDDDD;
35
+ }
36
+
37
+ table.tidy_table th.sort_asc {
38
+ background: #EEEEEE url( images/arrow_asc.gif ) no-repeat right center;
39
+ }
40
+
41
+ table.tidy_table th.sort_desc {
42
+ background: #EEEEEE url( images/arrow_desc.gif ) no-repeat right center;
43
+ }
44
+
45
+ table.tidy_table th,
46
+ table.tidy_table td {
47
+ padding: 6px 20px 6px 20px;
48
+ }
49
+
50
+ table.tidy_table td {
51
+ border-right: 1px solid #EEEEEE;
52
+ padding: 7px 20px 7px 20px;
53
+ }
54
+
55
+ table.tidy_table th:nth-child(1),
56
+ table.tidy_table td:nth-child(1) {
57
+ width: 10px;
58
+ }
59
+
60
+ table.tidy_table td:nth-child(1) {
61
+ border-right: 1px solid #EEEEEE;
62
+ }
63
+
64
+ table.tidy_table input[type=checkbox],
65
+ table.tidy_table input[type=checkbox] {
66
+ display: block;
67
+ margin: 0px auto 0px auto;
68
+ }
69
+
70
+ table.tidy_table td:nth-last-child(1) {
71
+ border-right: none;
72
+ }
73
+
74
+ table.tidy_table td {
75
+ border-top: 1px solid #CCCCCC;
76
+ }
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tidy-table-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.5
5
+ platform: ruby
6
+ authors:
7
+ - dbackowski
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: jquery-rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 3.0.0
20
+ - - <
21
+ - !ruby/object:Gem::Version
22
+ version: '5.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 3.0.0
30
+ - - <
31
+ - !ruby/object:Gem::Version
32
+ version: '5.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ~>
38
+ - !ruby/object:Gem::Version
39
+ version: '1.7'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: '1.7'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '10.0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ version: '10.0'
61
+ description: Asset pipeline bundling of the tidy table jquery plugin.
62
+ email:
63
+ - damianbackowski@gmail.com
64
+ executables: []
65
+ extensions: []
66
+ extra_rdoc_files: []
67
+ files:
68
+ - .gitignore
69
+ - Gemfile
70
+ - LICENSE.txt
71
+ - README.md
72
+ - Rakefile
73
+ - lib/tidy/table/rails.rb
74
+ - lib/tidy/table/rails/version.rb
75
+ - tidy-table-rails.gemspec
76
+ - vendor/assets/javascripts/tidy-table.js
77
+ - vendor/assets/stylesheets/tidy-table.css
78
+ homepage: https://github.com/dbackowski/tidy-table-rails
79
+ licenses:
80
+ - MIT
81
+ metadata: {}
82
+ post_install_message:
83
+ rdoc_options: []
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ requirements: []
97
+ rubyforge_project:
98
+ rubygems_version: 2.0.14
99
+ signing_key:
100
+ specification_version: 4
101
+ summary: Create a HTML table from JSON that can be sorted, selected, and post-processed
102
+ using a simple callback.
103
+ test_files: []