osom-tables 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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
+
@@ -0,0 +1,6 @@
1
+ #
2
+ # Just a gem hook
3
+ #
4
+ require 'osom_tables'
5
+ require 'osom_tables/helper'
6
+ require 'osom_tables/railtie' if defined?(Rails)
@@ -0,0 +1,3 @@
1
+ module OsomTables
2
+ VERSION = '1.0.0'
3
+ end
@@ -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
@@ -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: []