osom-tables 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 +7 -0
- data/README.md +147 -0
- data/lib/osom-tables.rb +6 -0
- data/lib/osom_tables.rb +3 -0
- data/lib/osom_tables/helper.rb +91 -0
- data/lib/osom_tables/railtie.rb +16 -0
- data/vendor/assets/images/osom-tables-spinner.gif +0 -0
- data/vendor/assets/javascripts/osom-tables.js +104 -0
- data/vendor/assets/stylesheets/osom-tables.css.scss +88 -0
- metadata +51 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5fd6cce444e1be672327791d4721d373553335f8
|
4
|
+
data.tar.gz: facda0539d1e13e51ae6844b22d93c2cb814e2cb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b4524680c19d243df750a93e986406db7de9edb56b4af6b8e07ab2e6327dbf76620a810f807db89e460a9fdc5a769d6efa5208713455c9e61a4beb8f9aefd9a0
|
7
|
+
data.tar.gz: 96141a88e8fe9fe7f22a00ae24587e83bf58efe78d37363fa898184794b8ea38c47a592203ab84507ffee74a18e1ae1c17aac86e0ce1d90e6e978b872dff886e
|
data/README.md
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
# OsomTables
|
2
|
+
|
3
|
+
Ajax tables engine that respects MVC and goes well with the rails way.
|
4
|
+
|
5
|
+
## The Merits
|
6
|
+
|
7
|
+
1. Rails friendly, relies on partials, scopes, etc.
|
8
|
+
2. Respects MVC, views are for views, models are for models
|
9
|
+
3. Flexible, you write your views in templates and paint them as you pleased
|
10
|
+
4. Unit testable, every moving part is independent and unit-testable
|
11
|
+
5. Light footprint, the whole thing is less than 100 lines of JS
|
12
|
+
|
13
|
+
|
14
|
+
## Simple Setup
|
15
|
+
|
16
|
+
Add this gem to your `Gemfile`
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
gem 'osom-tables'
|
20
|
+
```
|
21
|
+
|
22
|
+
Make a partial called `_table.html.haml` in your resource views
|
23
|
+
|
24
|
+
```haml
|
25
|
+
= osom_table_for @things, any_options do |t|
|
26
|
+
|
27
|
+
= t.head do
|
28
|
+
%th Name
|
29
|
+
%th Size
|
30
|
+
|
31
|
+
= t.body do |thing|
|
32
|
+
%td= thing.name
|
33
|
+
%td= thing.size
|
34
|
+
```
|
35
|
+
|
36
|
+
Put it into your `index.html.haml` file the usual way
|
37
|
+
|
38
|
+
```haml
|
39
|
+
%h1 Things
|
40
|
+
|
41
|
+
= render 'table'
|
42
|
+
```
|
43
|
+
|
44
|
+
Add the following thing into your controller
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
class ThingsController < ApplicationController
|
48
|
+
def index
|
49
|
+
@things = Thing.page(params[:page])
|
50
|
+
|
51
|
+
render partial: 'table', layout: false if request.xhr?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
```
|
55
|
+
|
56
|
+
And finally, add the assets to your `application.js` and `application.css` files the usual way
|
57
|
+
|
58
|
+
```js
|
59
|
+
*= require 'osom-tables'
|
60
|
+
```
|
61
|
+
|
62
|
+
And you're good to go!
|
63
|
+
|
64
|
+
|
65
|
+
## Adding Sorting
|
66
|
+
|
67
|
+
OsomTables don't enforce any sort of dealing with the sorting, just use your standard scopes.
|
68
|
+
The osom-tables will just handle the views and the `params[:order]` for you.
|
69
|
+
|
70
|
+
Add the order keys to your `t.head` section like so
|
71
|
+
|
72
|
+
```haml
|
73
|
+
= osom_table_for @things do |t|
|
74
|
+
|
75
|
+
= t.head do
|
76
|
+
%th{order: 'name'} Name
|
77
|
+
%th{order: 'size'} Size
|
78
|
+
|
79
|
+
= t.body do |thing|
|
80
|
+
%td= thing.name
|
81
|
+
%td= thing.size
|
82
|
+
```
|
83
|
+
|
84
|
+
This will handle the `params[:order]` automatically, which you can use in your controllers say like that
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
class ThingsController < ApplicationController
|
88
|
+
def index
|
89
|
+
@things = Thing.page(params[:page]).order_by(params[:order])
|
90
|
+
|
91
|
+
render parital: 'table', layout: false if request.xhr?
|
92
|
+
end
|
93
|
+
end
|
94
|
+
```
|
95
|
+
|
96
|
+
And then in your models, for example like that
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
class Thing
|
100
|
+
scope :order_by, ->(param) {
|
101
|
+
sort = param.ends_with?('_desc') ? 'DESC' : 'ASC'
|
102
|
+
|
103
|
+
case param.sub('_desc', '')
|
104
|
+
when 'name' then order("name #{sort}")
|
105
|
+
when 'size' then order("size #{sort}")
|
106
|
+
else scopped # fallback
|
107
|
+
end
|
108
|
+
}
|
109
|
+
end
|
110
|
+
```
|
111
|
+
|
112
|
+
And don't forget to enjoy the awesomeness of easily unit-testable code!
|
113
|
+
|
114
|
+
|
115
|
+
## HTML5 Push State
|
116
|
+
|
117
|
+
OsomTables can easily hook you up with the html5 push-state goodness.
|
118
|
+
Yes, it's just like `pjax` (whoever come up with this name) only better
|
119
|
+
coz it renders only what needs to be rendered.
|
120
|
+
|
121
|
+
To switch push state on, just pass the `push: true` option with your table
|
122
|
+
|
123
|
+
```haml
|
124
|
+
= osom_tables_for @things, push: true do |t|
|
125
|
+
...
|
126
|
+
```
|
127
|
+
|
128
|
+
|
129
|
+
## Custom Urls
|
130
|
+
|
131
|
+
By default `osom-tables` will use your current url as the base one. But,
|
132
|
+
in case you would like to reuse the `_table` partial, in different locations,
|
133
|
+
you do so, but specifying the `url: smth_path` option with your tables
|
134
|
+
|
135
|
+
```haml
|
136
|
+
= osom_tables_for @things, url: other_things_path do |t|
|
137
|
+
...
|
138
|
+
```
|
139
|
+
|
140
|
+
## License & Copyright
|
141
|
+
|
142
|
+
All code in this repository is released under the terms of the MIT license
|
143
|
+
|
144
|
+
Copyright (C) 2013 Nikolay Nemshilov
|
145
|
+
|
146
|
+
|
147
|
+
|
data/lib/osom-tables.rb
ADDED
data/lib/osom_tables.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
module OsomTables::Helper
|
2
|
+
|
3
|
+
def osom_table_for(items, options={}, &block)
|
4
|
+
push = options[:push] == true and options.delete(:push)
|
5
|
+
url = options[:url] || request.fullpath and options.delete(:url)
|
6
|
+
search = options[:search] == true and options.delete(:search)
|
7
|
+
paginate = options[:paginate] || {} and options.delete(:paginate)
|
8
|
+
url = url.gsub(/(\?|&)osom_tables_cache_killa=[^&]*?/, '')
|
9
|
+
|
10
|
+
options[:data] ||= {}
|
11
|
+
options[:data][:url] = url
|
12
|
+
options[:data][:push] = true if push
|
13
|
+
|
14
|
+
content_tag :div, class: 'osom-table' do
|
15
|
+
osom_tables_search(url, search) +
|
16
|
+
|
17
|
+
content_tag(:table, options) {
|
18
|
+
content_tag(:caption, image_tag('osom-tables-spinner.gif', alt: nil), class: 'locker') +
|
19
|
+
capture(Table.new(self, items), &block)
|
20
|
+
} +
|
21
|
+
|
22
|
+
osom_tables_pagination(items, url, paginate)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def osom_tables_search(url, search)
|
27
|
+
''.html_safe if ! search
|
28
|
+
end
|
29
|
+
|
30
|
+
def osom_tables_pagination(items, url, options)
|
31
|
+
if respond_to?(:paginate) # kaminari
|
32
|
+
options[:params] = Rails.application.routes.recognize_path(url, method: :get).merge(options[:params] || {})
|
33
|
+
paginate(items, options)
|
34
|
+
elsif respond_to?(:will_paginate)
|
35
|
+
will_paginate items, options
|
36
|
+
else
|
37
|
+
''.html_safe
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# The thing that we yield into the block
|
43
|
+
#
|
44
|
+
class Table
|
45
|
+
def initialize(context, items)
|
46
|
+
@context = context
|
47
|
+
@items = items
|
48
|
+
end
|
49
|
+
|
50
|
+
def head(&block)
|
51
|
+
head_row = @context.content_tag :tr, &block
|
52
|
+
|
53
|
+
while m = head_row.match(/<th(.*?) (order=("|')(.+?)\3)(.*?)>/)
|
54
|
+
m = m.to_a
|
55
|
+
key = m[4]
|
56
|
+
css = 'sortable'
|
57
|
+
css << ' asc' if @context.params[:order] == key
|
58
|
+
css << ' desc' if @context.params[:order] == key + '_desc'
|
59
|
+
|
60
|
+
[1,5].each do |i|
|
61
|
+
if mc = m[i].match(/ class=("|')(.+)\1/)
|
62
|
+
m[i] = m[i].gsub(mc[0], '')
|
63
|
+
css = "#{mc[2]} #{css}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
head_row.gsub! m[0], "<th#{m[1]} class='#{css}' data-#{m[2]}#{m[5]}>"
|
68
|
+
end
|
69
|
+
|
70
|
+
@context.content_tag :thead, head_row.html_safe
|
71
|
+
end
|
72
|
+
|
73
|
+
def body(&block)
|
74
|
+
@context.content_tag :tbody do
|
75
|
+
@items.map do |item|
|
76
|
+
if defined?(ActiveRecord) && item.is_a?(ActiveRecord::Base)
|
77
|
+
@context.content_tag_for(:tr, item){ yield(item) }
|
78
|
+
else
|
79
|
+
@context.content_tag(:tr){ yield(item) }
|
80
|
+
end
|
81
|
+
end.join("\n").html_safe
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def foot(&block)
|
86
|
+
@context.content_tag :tfoot do
|
87
|
+
@context.content_tag :tr, &block
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class OsomTables::Railtie < Rails::Railtie
|
2
|
+
initializer "osom_tables.view_helpers" do
|
3
|
+
ActionView::Base.send :include, OsomTables::Helper
|
4
|
+
end
|
5
|
+
|
6
|
+
initializer "osom_tables.configure_rails_initialization" do
|
7
|
+
ActionController::Base.instance_eval do
|
8
|
+
before_filter do
|
9
|
+
params.delete(:osom_tables_cache_killa)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class OsomTables::Engine < Rails::Engine
|
16
|
+
end
|
Binary file
|
@@ -0,0 +1,104 @@
|
|
1
|
+
/**
|
2
|
+
* The OsomTables scriptery
|
3
|
+
*
|
4
|
+
* Copyright (C) 2013 Nikolay Nemshilov
|
5
|
+
*/
|
6
|
+
(function($) {
|
7
|
+
|
8
|
+
if (!$) { return console.log("No jQuery? Osom!"); }
|
9
|
+
|
10
|
+
$(document).on('click', '.osom-table .pagination a', function(e) {
|
11
|
+
e.preventDefault();
|
12
|
+
load_table($(this).closest('.osom-table'), this.getAttribute('href'));
|
13
|
+
});
|
14
|
+
|
15
|
+
$(document).on('click', '.osom-table th[data-order]', function(e) {
|
16
|
+
var order = $(this).data('order'), asc = $(this).hasClass('asc');
|
17
|
+
|
18
|
+
load_table($(this).closest('.osom-table'), build_url(
|
19
|
+
$(this).closest('table').data('url'), {
|
20
|
+
order: order + (asc ? '_desc' : ''), page: 1
|
21
|
+
}
|
22
|
+
));
|
23
|
+
});
|
24
|
+
|
25
|
+
$(window).on('popstate', function(e) {
|
26
|
+
var state = e.originalEvent.state;
|
27
|
+
if (state && state.url) {
|
28
|
+
if (current_table && current_table.find('table').data('push')) {
|
29
|
+
load_table(current_table, state.url, true);
|
30
|
+
} else {
|
31
|
+
document.location.href = state.url;
|
32
|
+
}
|
33
|
+
}
|
34
|
+
});
|
35
|
+
|
36
|
+
var current_table = null;
|
37
|
+
|
38
|
+
function load_table(container, url, no_push) {
|
39
|
+
current_table = container.addClass('loading');
|
40
|
+
actual_table = container.find('table');
|
41
|
+
|
42
|
+
actual_table.trigger('osom-table:request');
|
43
|
+
|
44
|
+
if (history.pushState && !no_push && actual_table.data('push')) {
|
45
|
+
history.pushState({url: url}, 'osom-table', url);
|
46
|
+
url = build_url(url, {osom_tables_cache_killa: true});
|
47
|
+
}
|
48
|
+
|
49
|
+
$.ajax(url, {
|
50
|
+
success: function(new_content) {
|
51
|
+
container.html(new_content);
|
52
|
+
},
|
53
|
+
complete: function() {
|
54
|
+
container.removeClass('loading');
|
55
|
+
actual_table.trigger('osom-table:loaded');
|
56
|
+
}
|
57
|
+
});
|
58
|
+
};
|
59
|
+
|
60
|
+
/**
|
61
|
+
* Rebuilds the url with the extra prams
|
62
|
+
*/
|
63
|
+
function build_url(url, params) {
|
64
|
+
var path, args; path = parse_url(url);
|
65
|
+
args = path[1]; path = path[0];
|
66
|
+
|
67
|
+
for (var key in params) {
|
68
|
+
args[key] = params[key];
|
69
|
+
}
|
70
|
+
|
71
|
+
return path + "?" + $.param(args);
|
72
|
+
}
|
73
|
+
|
74
|
+
/**
|
75
|
+
* Parsing the arguments out of the url query
|
76
|
+
*/
|
77
|
+
function parse_url(url) {
|
78
|
+
var path, query, args={}, list, key, value;
|
79
|
+
path = url.split("?"); query = path[1]; path = path[0];
|
80
|
+
|
81
|
+
if (query) {
|
82
|
+
for (var i=0, list = query.split('&'); i < list.length; i++) {
|
83
|
+
key = list[i].split('=');
|
84
|
+
value = key[1]; key = key[0];
|
85
|
+
|
86
|
+
key = decodeURIComponent(key);
|
87
|
+
value = decodeURIComponent((value||'').replace(/\+/g, ' '));
|
88
|
+
|
89
|
+
if (key.substr(-2) === "[]") {
|
90
|
+
if (args[key]) {
|
91
|
+
args[key].push(value)
|
92
|
+
} else {
|
93
|
+
args[key] = [value]
|
94
|
+
}
|
95
|
+
} else {
|
96
|
+
args[key] = value
|
97
|
+
}
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
return [path, args];
|
102
|
+
}
|
103
|
+
|
104
|
+
})(jQuery);
|
@@ -0,0 +1,88 @@
|
|
1
|
+
/**
|
2
|
+
* Some stock styling for the osom-tables
|
3
|
+
* to provide nice locker/spinner to highlight
|
4
|
+
* the tables loading process
|
5
|
+
*
|
6
|
+
* Copyright (C) 2013 Nikolay Nemshilov
|
7
|
+
*/
|
8
|
+
.osom-table {
|
9
|
+
|
10
|
+
table {
|
11
|
+
position: relative;
|
12
|
+
|
13
|
+
.locker {
|
14
|
+
display: none;
|
15
|
+
position: absolute;
|
16
|
+
z-index: 9999;
|
17
|
+
left: 0;
|
18
|
+
top: 0;
|
19
|
+
width: 100%;
|
20
|
+
height: 100%;
|
21
|
+
background-color: #eee;
|
22
|
+
text-align: center;
|
23
|
+
border-radius: .25em;
|
24
|
+
opacity: .6;
|
25
|
+
|
26
|
+
img {
|
27
|
+
position: relative;
|
28
|
+
top: 40%;
|
29
|
+
height: 25%;
|
30
|
+
width: auto;
|
31
|
+
max-height: 5em;
|
32
|
+
max-width: 5em;
|
33
|
+
padding: 1em;
|
34
|
+
background-color: #fff;
|
35
|
+
border-radius: 1em;
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
thead th.sortable {
|
40
|
+
cursor: pointer;
|
41
|
+
transition: background-color .25s ease-in-out;
|
42
|
+
-o-transition: background-color .25s ease-in-out;
|
43
|
+
-ms-transition: background-color .25s ease-in-out;
|
44
|
+
-moz-transition: background-color .25s ease-in-out;
|
45
|
+
-webkit-transition: background-color .25s ease-in-out;
|
46
|
+
|
47
|
+
&:hover, &.asc, &.desc {
|
48
|
+
background-color: #efd;
|
49
|
+
|
50
|
+
&:after {
|
51
|
+
opacity: 1;
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
&:after {
|
56
|
+
content: '\25BE';
|
57
|
+
display: block;
|
58
|
+
float: right;
|
59
|
+
opacity: .5;
|
60
|
+
vertical-align: middle;
|
61
|
+
}
|
62
|
+
|
63
|
+
&.desc:after {
|
64
|
+
transform: rotate(180deg);
|
65
|
+
-o-transform: rotate(180deg);
|
66
|
+
-ms-transform: rotate(180deg);
|
67
|
+
-moz-transform: rotate(180deg);
|
68
|
+
-webkit-transform: rotate(180deg);
|
69
|
+
}
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
&.loading {
|
74
|
+
table {
|
75
|
+
th, td {
|
76
|
+
-webkit-filter: blur(1.5px);
|
77
|
+
-moz-filter: blur(1.5px);
|
78
|
+
-ms-filter: blur(1.5px);
|
79
|
+
-o-filter: blur(1.5px);
|
80
|
+
filter: blur(1.5px);
|
81
|
+
}
|
82
|
+
|
83
|
+
.locker {
|
84
|
+
display: block;
|
85
|
+
}
|
86
|
+
}
|
87
|
+
}
|
88
|
+
}
|
metadata
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: osom-tables
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nikolay Nemshilov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-06-09 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Fancy ajax tables engine that fits rails infrastructure
|
14
|
+
email: nemshilov@gmail.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/osom-tables.rb
|
20
|
+
- lib/osom_tables/helper.rb
|
21
|
+
- lib/osom_tables/railtie.rb
|
22
|
+
- lib/osom_tables.rb
|
23
|
+
- vendor/assets/images/osom-tables-spinner.gif
|
24
|
+
- vendor/assets/javascripts/osom-tables.js
|
25
|
+
- vendor/assets/stylesheets/osom-tables.css.scss
|
26
|
+
- README.md
|
27
|
+
homepage: http://github.com/MadRabbit/osom-tables
|
28
|
+
licenses:
|
29
|
+
- MIT
|
30
|
+
metadata: {}
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
requirements: []
|
46
|
+
rubyforge_project:
|
47
|
+
rubygems_version: 2.0.2
|
48
|
+
signing_key:
|
49
|
+
specification_version: 4
|
50
|
+
summary: Fancy ajax tables in true rails style
|
51
|
+
test_files: []
|