tvdeyen-handles_sortable_columns 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YzQzYWI5MjU4OTg2YTIwM2NjNmQ5YjJiNjU3NWYyMWIyMzJlMTRmNQ==
5
+ data.tar.gz: !binary |-
6
+ YTUwNzkyY2ExZjRlOWU1MDI3MjJhYWZmNzIwMGQzODNhZGIyM2NjOA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NTljZmQ1ZjdhYTY1Yzc1MzJkZmM4MTAxYmRhZWExMmMyODRlZmYyODZjZWM5
10
+ OTFjZDE1OWNhODMyNDk2MjVjOWI0NmY3YzhlMmE1OGFiZDI5NTAyZGNjMTk4
11
+ OTFmM2IwOTFlY2I2ZDg4NTNhZGQ1MDQ5YTcwNjVkNTBjOTY1NzA=
12
+ data.tar.gz: !binary |-
13
+ YjFiYzdjODQ4MDM2ZWY5MDcxYjQyMDIwOWIwNTVkYzAzN2ZiM2Y3OWUzYzY3
14
+ MjgzZGI3NjQ0ZTkzMDAzYWMwZDZhNTdmMTE5OWMxOTE5MDg2MjFlMGZjMjY1
15
+ ZDNmODE1OTM2Zjg3MDA5ZTRiYWI2M2M0YjgyNzQ1N2M0ZjMwZmI=
@@ -0,0 +1,9 @@
1
+ # General Ruby, sorted by first letter.
2
+ .old*
3
+ *-old*
4
+ .ref*
5
+
6
+ # Project-specific.
7
+ /doc/
8
+ /pkg/
9
+ /.rvmrc
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010-2011 Alex Fortuna
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,140 @@
1
+ <head>
2
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
3
+ <link href="dev/github.css" rel="stylesheet" type="text/css" />
4
+ </head>
5
+
6
+ <h1 id="sortable-table-columns">Sortable Table Columns</h1>
7
+
8
+ <h2 id="introduction">Introduction</h2>
9
+
10
+ <p>A simple yet flexible Rails gem/plugin to quickly add sortable table columns to your controller and views.</p>
11
+
12
+ <h2 id="setup-rails-3">Setup (Rails 3)</h2>
13
+
14
+ <p>In your app’s <code>Gemfile</code>, add:</p>
15
+
16
+ <pre><code>gem "handles_sortable_columns"
17
+ </code></pre>
18
+
19
+ <p>To install the gem with RDoc/ri documentation, do a:</p>
20
+
21
+ <pre><code>$ gem install handles_sortable_columns
22
+ </code></pre>
23
+
24
+ <p>Otherwise, do a <code>bundle install</code>.</p>
25
+
26
+ <h2 id="setup-rails-2">Setup (Rails 2)</h2>
27
+
28
+ <p>In your app’s <code>config/environment.rb</code> add:</p>
29
+
30
+ <pre><code>config.gem "handles_sortable_columns"
31
+ </code></pre>
32
+
33
+ <p>To install the gem, do a:</p>
34
+
35
+ <pre><code>$ gem sources --add http://rubygems.org
36
+ $ gem install handles_sortable_columns
37
+ </code></pre>
38
+
39
+ <p>, or use <code>rake gems:install</code>.</p>
40
+
41
+ <h2 id="basic-usage">Basic Usage</h2>
42
+
43
+ <p>Activate the feature in your controller class:</p>
44
+
45
+ <pre><code>class MyController &lt; ApplicationController
46
+ handles_sortable_columns
47
+ ...
48
+ </code></pre>
49
+
50
+ <p>In a view, mark up sortable columns by using the <tt>sortable_column</tt> helper:</p>
51
+
52
+ <pre><code>&lt;%= sortable_column "Product" %&gt;
53
+ &lt;%= sortable_column "Price" %&gt;
54
+ </code></pre>
55
+
56
+ <p>In controller action, fetch and use the order clause according to current state of sortable columns:</p>
57
+
58
+ <pre><code>def index
59
+ order = sortable_column_order
60
+ @records = Article.order(order) # Rails 3.
61
+ @records = Article.all(:order =&gt; order) # Rails 2.
62
+ end
63
+ </code></pre>
64
+
65
+ <p>That’s it for basic usage. Production usage may require passing additional parameters to listed methods.</p>
66
+
67
+ <h2 id="production-usage">Production Usage</h2>
68
+
69
+ <p>Please take time to read the gem’s full <a href="http://rdoc.info/projects/dadooda/handles_sortable_columns">RDoc documentation</a>. This README has a limited coverage.</p>
70
+
71
+ <h3 id="configuration">Configuration</h3>
72
+
73
+ <p>Change names of GET parameters used for sorting and pagination:</p>
74
+
75
+ <pre><code>class MyController &lt; ApplicationController
76
+ handles_sortable_columns do |conf|
77
+ conf.sort_param = "s"
78
+ conf.page_param = "p"
79
+ end
80
+ ...
81
+ </code></pre>
82
+
83
+ <p>Change CSS class of all sortable column <code>&lt;a&gt;</code> tags:</p>
84
+
85
+ <pre><code>handles_sortable_columns do |conf|
86
+ conf.class = "SortableLink"
87
+ conf.indicator_class = {:asc =&gt; "AscSortableLink", :desc =&gt; "DescSortableLink"}
88
+ end
89
+ </code></pre>
90
+
91
+ <p>Change how text-based sort indicator looks like:</p>
92
+
93
+ <pre><code>handles_sortable_columns do |conf|
94
+ conf.indicator_text = {:asc =&gt; "[asc]", :desc =&gt; "[desc]"}
95
+ end
96
+ </code></pre>
97
+
98
+ <p>Disable text-based sort indicator completely:</p>
99
+
100
+ <pre><code>handles_sortable_columns do |conf|
101
+ conf.indicator_text = {}
102
+ end
103
+ </code></pre>
104
+
105
+ <h3 id="helper-options">Helper Options</h3>
106
+
107
+ <p>Explicitly specify column name:</p>
108
+
109
+ <pre><code>&lt;%= sortable_column "Highest Price", :column =&gt; "max_price" %&gt;
110
+ </code></pre>
111
+
112
+ <p>Specify CSS class for this particular link:</p>
113
+
114
+ <pre><code>&lt;%= sortable_column "Name", :class =&gt; "SortableLink" %&gt;
115
+ </code></pre>
116
+
117
+ <p>Specify sort direction on first click:</p>
118
+
119
+ <pre><code>&lt;%= sortable_column "Created At", :direction =&gt; :asc %&gt;
120
+ </code></pre>
121
+
122
+ <h3 id="fetching-sort-order">Fetching Sort Order</h3>
123
+
124
+ <p>To fetch sort order <strong>securely</strong>, with <strong>column name validation</strong>, <strong>default values</strong> and <strong>multiple sort criteria</strong>, use the block form of <code>sortable_column_order</code>:</p>
125
+
126
+ <pre><code>order = sortable_column_order do |column, direction|
127
+ case column
128
+ when "name"
129
+ "#{column} #{direction}"
130
+ when "created_at", "updated_at"
131
+ "#{column} #{direction}, name ASC"
132
+ else
133
+ "name ASC"
134
+ end
135
+ end
136
+ </code></pre>
137
+
138
+ <h2 id="feedback">Feedback</h2>
139
+
140
+ <p>Send bug reports, suggestions and criticisms through <a href="http://github.com/dadooda/handles_sortable_columns">project’s page on GitHub</a>.</p>
@@ -0,0 +1,137 @@
1
+
2
+ Sortable Table Columns
3
+ ======================
4
+
5
+
6
+ Introduction
7
+ ------------
8
+
9
+ A simple yet flexible Rails gem/plugin to quickly add sortable table columns to your controller and views.
10
+
11
+
12
+ Setup (Rails 3)
13
+ ---------------
14
+
15
+ In your app's `Gemfile`, add:
16
+
17
+ gem "handles_sortable_columns"
18
+
19
+ To install the gem with RDoc/ri documentation, do a:
20
+
21
+ $ gem install handles_sortable_columns
22
+
23
+ Otherwise, do a `bundle install`.
24
+
25
+
26
+ Setup (Rails 2)
27
+ ---------------
28
+
29
+ In your app's `config/environment.rb` add:
30
+
31
+ config.gem "handles_sortable_columns"
32
+
33
+ To install the gem, do a:
34
+
35
+ $ gem sources --add http://rubygems.org
36
+ $ gem install handles_sortable_columns
37
+
38
+ , or use `rake gems:install`.
39
+
40
+
41
+ Basic Usage
42
+ -----------
43
+
44
+ Activate the feature in your controller class:
45
+
46
+ class MyController < ApplicationController
47
+ handles_sortable_columns
48
+ ...
49
+
50
+ In a view, mark up sortable columns by using the <tt>sortable_column</tt> helper:
51
+
52
+ <%= sortable_column "Product" %>
53
+ <%= sortable_column "Price" %>
54
+
55
+ In controller action, fetch and use the order clause according to current state of sortable columns:
56
+
57
+ def index
58
+ order = sortable_column_order
59
+ @records = Article.order(order) # Rails 3.
60
+ @records = Article.all(:order => order) # Rails 2.
61
+ end
62
+
63
+ That's it for basic usage. Production usage may require passing additional parameters to listed methods.
64
+
65
+
66
+ Production Usage
67
+ ----------------
68
+
69
+ Please take time to read the gem's full [RDoc documentation](http://rdoc.info/projects/dadooda/handles_sortable_columns). This README has a limited coverage.
70
+
71
+
72
+ ### Configuration ###
73
+
74
+ Change names of GET parameters used for sorting and pagination:
75
+
76
+ class MyController < ApplicationController
77
+ handles_sortable_columns do |conf|
78
+ conf.sort_param = "s"
79
+ conf.page_param = "p"
80
+ end
81
+ ...
82
+
83
+ Change CSS class of all sortable column `<a>` tags:
84
+
85
+ handles_sortable_columns do |conf|
86
+ conf.class = "SortableLink"
87
+ conf.indicator_class = {:asc => "AscSortableLink", :desc => "DescSortableLink"}
88
+ end
89
+
90
+ Change how text-based sort indicator looks like:
91
+
92
+ handles_sortable_columns do |conf|
93
+ conf.indicator_text = {:asc => "[asc]", :desc => "[desc]"}
94
+ end
95
+
96
+ Disable text-based sort indicator completely:
97
+
98
+ handles_sortable_columns do |conf|
99
+ conf.indicator_text = {}
100
+ end
101
+
102
+
103
+ ### Helper Options ###
104
+
105
+ Explicitly specify column name:
106
+
107
+ <%= sortable_column "Highest Price", :column => "max_price" %>
108
+
109
+ Specify CSS class for this particular link:
110
+
111
+ <%= sortable_column "Name", :class => "SortableLink" %>
112
+
113
+ Specify sort direction on first click:
114
+
115
+ <%= sortable_column "Created At", :direction => :asc %>
116
+
117
+
118
+ ### Fetching Sort Order ###
119
+
120
+ To fetch sort order **securely**, with **column name validation**, **default values** and **multiple sort criteria**, use the block form of `sortable_column_order`:
121
+
122
+ order = sortable_column_order do |column, direction|
123
+ case column
124
+ when "name"
125
+ "#{column} #{direction}"
126
+ when "created_at", "updated_at"
127
+ "#{column} #{direction}, name ASC"
128
+ else
129
+ "name ASC"
130
+ end
131
+ end
132
+
133
+
134
+ Feedback
135
+ --------
136
+
137
+ Send bug reports, suggestions and criticisms through [project's page on GitHub](http://github.com/dadooda/handles_sortable_columns).
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/gem_helper'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+
8
+ Bundler::GemHelper.install_tasks
9
+
10
+ task :default => :build
11
+
12
+ begin
13
+ require 'rdoc/task'
14
+ rescue LoadError
15
+ require 'rdoc/rdoc'
16
+ require 'rake/rdoctask'
17
+ RDoc::Task = Rake::RDocTask
18
+ end
19
+
20
+ desc "Generate RDoc documentation"
21
+ Rake::RDocTask.new(:rdoc) do |rdoc|
22
+ rdoc.rdoc_dir = "doc"
23
+ rdoc.title = "Handles::SortableColumns"
24
+ rdoc.rdoc_files.include("lib/**/*.rb")
25
+ end
@@ -0,0 +1,5 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 1
4
+ :patch: 5
5
+ #:build: pre1
@@ -0,0 +1,41 @@
1
+
2
+ body{font:13.34px helvetica,arial,freesans,clean,sans-serif;}
3
+ body{width:920px;margin:0 auto;padding:0 15px;text-align:left;}
4
+
5
+ /* Это неважно работает, с виду погано. */
6
+ xbody{background-color:#f8f8f8;padding:.7em;}
7
+
8
+ /*
9
+ #readme div.plain,#readme div.wikistyle{background-color:#f8f8f8;padding:.7em;}
10
+ .site{width:920px;margin:0 auto;padding:0 15px;text-align:left;}
11
+ #readme{font:13.34px helvetica,arial,freesans,clean,sans-serif;}
12
+ #readme.announce{margin:1em 0;}
13
+ #readme span.name{font-size:140%;padding:.8em 0;}
14
+ #readme div.plain,#readme div.wikistyle{background-color:#f8f8f8;padding:.7em;}
15
+ #readme.announce div.plain,#readme.announce div.wikistyle{border:1px solid #e9e9e9;}
16
+ #readme.blob div.plain,#readme.blob div.wikistyle{border-top:none;}
17
+ #readme div.plain pre{font-family:'Bitstream Vera Sans Mono','Courier',monospace;font-size:85%;color:#444;}
18
+ */
19
+
20
+ h1,h2,h3,h4,h5,h6{border:0!important;}
21
+ h1{font-size:170%!important;border-top:4px solid #aaa!important;padding-top:.5em!important;margin-top:1.5em!important;}
22
+ h1:first-child{margin-top:0!important;padding-top:.25em!important;border-top:none!important;}
23
+ h2{font-size:150%!important;margin-top:1.5em!important;border-top:4px solid #e0e0e0!important;padding-top:.5em!important;}
24
+ h3{margin-top:1em!important;}
25
+ p{margin:1em 0!important;line-height:1.5em!important;}
26
+ ul{margin:1em 0 1em 2em!important;}
27
+ ol{margin:1em 0 1em 2em!important;}
28
+ ul ul,ul ol,ol ol,ol ul{margin-top:0!important;margin-bottom:0!important;}
29
+ blockquote{margin:1em 0!important;border-left:5px solid #ddd!important;padding-left:.6em!important;color:#555!important;}
30
+ dt{font-weight:bold!important;margin-left:1em!important;}
31
+ dd{margin-left:2em!important;margin-bottom:1em!important;}
32
+ table{margin:1em 0!important;}
33
+ table th{border-bottom:1px solid #bbb!important;padding:.2em 1em!important;}
34
+ table td{border-bottom:1px solid #ddd!important;padding:.2em 1em!important;}
35
+ pre{margin:1em 0!important;font-size:90%!important;background-color:#f8f8ff!important;border:1px solid #dedede!important;padding:.5em!important;line-height:1.5em!important;color:#444!important;overflow:auto!important;}
36
+ pre code{padding:0!important;font-size:100%!important;background-color:#f8f8ff!important;border:none!important;}
37
+ code{font-size:90%!important;background-color:#f8f8ff!important;color:#444!important;padding:0 .2em!important;border:1px solid #dedede!important;}
38
+ pre.console{margin:1em 0!important;font-size:90%!important;background-color:black!important;padding:.5em!important;line-height:1.5em!important;color:white!important;}
39
+ pre.console code{padding:0!important;font-size:100%!important;background-color:black!important;border:none!important;color:white!important;}
40
+ pre.console span{color:#888!important;}
41
+ pre.console span.command{color:yellow!important;}
@@ -0,0 +1,4 @@
1
+ <head>
2
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
3
+ <link href="dev/github.css" rel="stylesheet" type="text/css" />
4
+ </head>
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ # Rails plugin init.
2
+ require File.join(File.dirname(__FILE__), "lib/handles_sortable_columns")
@@ -0,0 +1,5 @@
1
+ module ActionController #:nodoc:
2
+ class Base #:nodoc:
3
+ include ::Handles::SortableColumns
4
+ end
5
+ end
@@ -0,0 +1,307 @@
1
+ module Handles #:nodoc:
2
+ # == Overview
3
+ #
4
+ # A sortable columns feature for your controller and views.
5
+ #
6
+ # == Basic Usage
7
+ #
8
+ # Activate the feature in your controller class:
9
+ #
10
+ # class MyController < ApplicationController
11
+ # handles_sortable_columns
12
+ # ...
13
+ #
14
+ # In a view, mark up sortable columns by using the <tt>sortable_column</tt> helper:
15
+ #
16
+ # <%= sortable_column "Product" %>
17
+ # <%= sortable_column "Price" % >
18
+ #
19
+ # In controller action, fetch and use the order clause according to current state of sortable columns:
20
+ #
21
+ # def index
22
+ # order = sortable_column_order
23
+ # @records = Article.order(order) # Rails 3.
24
+ # @records = Article.all(:order => order) # Rails 2.
25
+ # end
26
+ #
27
+ # That's it for basic usage. Production usage may require passing additional parameters to listed methods.
28
+ #
29
+ # See also:
30
+ # * MetaClassMethods#handles_sortable_columns
31
+ # * InstanceMethods#sortable_column_order
32
+ module SortableColumns
33
+ def self.included(owner) #:nodoc:
34
+ owner.extend MetaClassMethods
35
+ end
36
+
37
+ # Sortable columns configuration object. Passed to the block when you do a:
38
+ #
39
+ # handles_sortable_columns do |conf|
40
+ # ...
41
+ # end
42
+ class Config
43
+ # CSS class for link (regardless of sorted state). Default:
44
+ #
45
+ # SortableColumnLink
46
+ attr_accessor :link_class
47
+
48
+ # GET parameter name for page number. Default:
49
+ #
50
+ # page
51
+ attr_accessor :page_param
52
+
53
+ # GET parameter name for sort column and direction. Default:
54
+ #
55
+ # sort
56
+ attr_accessor :sort_param
57
+
58
+ # Default sort direction, if params[sort_param] is not given.
59
+ #
60
+ # default_sort_value
61
+ attr_accessor :default_sort_value
62
+
63
+ # Sort indicator text. If any of values are empty, indicator is not displayed. Default:
64
+ #
65
+ # {:asc => "&nbsp;&darr;&nbsp;", :desc => "&nbsp;&uarr;&nbsp;"}
66
+ attr_accessor :indicator_text
67
+
68
+ # Sort indicator class. Default:
69
+ #
70
+ # {:asc => "SortedAsc", :desc => "SortedDesc"}
71
+ attr_accessor :indicator_class
72
+
73
+ def initialize(attrs = {})
74
+ defaults = {
75
+ :link_class => "SortableColumnLink",
76
+ :indicator_class => {:asc => "SortedAsc", :desc => "SortedDesc"},
77
+ :indicator_text => {:asc => "&nbsp;&darr;&nbsp;", :desc => "&nbsp;&uarr;&nbsp;"},
78
+ :page_param => "page",
79
+ :sort_param => "sort",
80
+ :default_sort_value => nil
81
+ }
82
+
83
+ defaults.merge(attrs).each {|k, v| send("#{k}=", v)}
84
+ end
85
+
86
+ # Bracket access for convenience.
87
+ def [](key)
88
+ send(key)
89
+ end
90
+
91
+ # Bracket access for convenience.
92
+ def []=(key, value)
93
+ send("#{key}=", value)
94
+ end
95
+ end # Config
96
+
97
+ module MetaClassMethods
98
+ # Activate and optionally configure the sortable columns feature in your controller.
99
+ #
100
+ # class MyController < ApplicationController
101
+ # handles_sortable_columns
102
+ # ...
103
+ #
104
+ # With configuration:
105
+ #
106
+ # class MyController < ApplicationController
107
+ # handles_sortable_columns do |conf|
108
+ # conf.sort_param = "s"
109
+ # conf.page_param = "p"
110
+ # conf.indicator_text = {}
111
+ # ...
112
+ # end
113
+ # ...
114
+ #
115
+ # With filter options:
116
+ #
117
+ # class MyController < ApplicationController
118
+ # handles_sortable_columns(:only => [:index]) do |conf|
119
+ # ...
120
+ # end
121
+ # ...
122
+ #
123
+ # NOTE: <tt>conf</tt> is a Config object.
124
+ def handles_sortable_columns(fopts = {}, &block)
125
+ # Multiple activation protection.
126
+ if not self < InstanceMethods
127
+ include InstanceMethods
128
+ helper_method :sortable_column
129
+ end
130
+
131
+ # Process configuration at every activation.
132
+ before_filter(fopts) do |ac|
133
+ ac.instance_eval do
134
+ # NOTE: Can't `yield`, we're in a block already.
135
+ block.call(sortable_columns_config) if block
136
+ end
137
+ end
138
+ end
139
+ end # MetaClassMethods
140
+
141
+ module InstanceMethods
142
+ private
143
+
144
+ # Internal/advanced use only. Parse sortable column sort param into a Hash with predefined keys.
145
+ #
146
+ # parse_sortable_column_sort_param("name") # => {:column => "name", :direction => :asc}
147
+ # parse_sortable_column_sort_param("-name") # => {:column => "name", :direction => :desc}
148
+ # parse_sortable_column_sort_param("") # => {:column => nil, :direction => nil}
149
+ def parse_sortable_column_sort_param(sort) #:nodoc:
150
+ out = {:column => nil, :direction => nil}
151
+ if sort.to_s.strip.match /\A((?:-|))([^-]+)\z/
152
+ out[:direction] = $1.empty?? :asc : :desc
153
+ out[:column] = $2.strip
154
+ end
155
+ out
156
+ end
157
+
158
+ # Render a sortable column link.
159
+ #
160
+ # Options:
161
+ #
162
+ # * <tt>:column</tt> -- Column name. E.g. <tt>created_at</tt>.
163
+ # * <tt>:direction</tt> -- Sort direction on first click. <tt>:asc</tt> or <tt>:desc</tt>. Default is <tt>:asc</tt>.
164
+ # * <tt>:link_class</tt> -- CSS class for link, regardless of sorted state.
165
+ # * <tt>:link_style</tt> -- CSS style for link, regardless of sorted state.
166
+ #
167
+ # Examples:
168
+ #
169
+ # <%= sortable_column "Product" %>
170
+ # <%= sortable_column "Highest Price", :column => "max_price" %>
171
+ # <%= sortable_column "Name", :link_class => "SortableLink" %>
172
+ # <%= sortable_column "Created At", :direction => :asc %>
173
+ def sortable_column(title, options = {}) #:doc:
174
+ options = options.dup
175
+ o = {}
176
+ conf = {}
177
+ conf[k = :sort_param] = sortable_columns_config[k]
178
+ conf[k = :default_sort_value] = sortable_columns_config[k]
179
+ conf[k = :page_param] = sortable_columns_config[k]
180
+ conf[k = :indicator_text] = sortable_columns_config[k]
181
+ conf[k = :indicator_class] = sortable_columns_config[k]
182
+
183
+ #HELP sortable_column
184
+ o[k = :column] = options.delete(k) || sortable_column_title_to_name(title)
185
+ o[k = :direction] = options.delete(k).to_s.downcase =~ /\Adesc\z/ ? :desc : :asc
186
+ o[k = :link_class] = options.delete(k) || sortable_columns_config[k]
187
+ o[k = :link_style] = options.delete(k)
188
+ o[k = :link_style] = options.delete(k)
189
+ o[k = :route_proxy] = options.delete(k)
190
+ #HELP /sortable_column
191
+
192
+ raise "Unknown option(s): #{options.inspect}" if not options.empty?
193
+
194
+ # Parse sort param.
195
+ sort = params[conf[:sort_param]] || conf[:default_sort_value]
196
+ pp = parse_sortable_column_sort_param(sort)
197
+
198
+ css_class = []
199
+ if (s = o[:link_class]).present?
200
+ css_class << s
201
+ end
202
+
203
+ # If already sorted and indicator class defined, append it.
204
+ if pp[:column] == o[:column].to_s and (s = conf[:indicator_class][pp[:direction]]).present?
205
+ css_class << s
206
+ end
207
+
208
+ # Build link itself.
209
+ pcs = []
210
+
211
+ html_options = {}
212
+ html_options[:class] = css_class.join(" ") if css_class.present?
213
+ html_options[:style] = o[:link_style] if o[:link_style].present?
214
+
215
+ # Rails 3 / Rails 2 fork.
216
+ tpl = respond_to?(:view_context) ? view_context : @template
217
+
218
+ # Already sorted?
219
+ if pp[:column] == o[:column].to_s
220
+ if o[:route_proxy]
221
+ url = o[:route_proxy].send(:url_for, params.merge({conf[:sort_param] => [("-" if pp[:direction] == :asc), o[:column]].join, conf[:page_param] => 1}))
222
+ else
223
+ url = url_for(params.merge({conf[:sort_param] => [("-" if pp[:direction] == :asc), o[:column]].join, conf[:page_param] => 1}))
224
+ end
225
+ pcs << tpl.link_to(title, url, html_options) # Opposite sort order when clicked.
226
+
227
+ # Append indicator, if configured.
228
+ if (s = conf[:indicator_text][pp[:direction]]).present?
229
+ pcs << s
230
+ end
231
+ else
232
+ # Not sorted.
233
+ if o[:route_proxy]
234
+ url = o[:route_proxy].send(:url_for, params.merge({conf[:sort_param] => [("-" if o[:direction] != :asc), o[:column]].join, conf[:page_param] => 1}))
235
+ else
236
+ url = url_for(params.merge({conf[:sort_param] => [("-" if o[:direction] != :asc), o[:column]].join, conf[:page_param] => 1}))
237
+ end
238
+ pcs << tpl.link_to(title, url, html_options)
239
+ end
240
+
241
+ # For Rails 3 provide #html_safe.
242
+ (v = pcs.join).respond_to?(:html_safe) ? v.html_safe : v
243
+ end
244
+
245
+ # Compile SQL order clause according to current state of sortable columns.
246
+ #
247
+ # Basic (kickstart) usage:
248
+ #
249
+ # order = sortable_column_order
250
+ #
251
+ # <b>WARNING:</b> Basic usage is <b>not recommended</b> for production since it is potentially
252
+ # vulnerable to SQL injection!
253
+ #
254
+ # Production usage with multiple sort criteria, column name validation and defaults:
255
+ #
256
+ # order = sortable_column_order do |column, direction|
257
+ # case column
258
+ # when "name"
259
+ # "#{column} #{direction}"
260
+ # when "created_at", "updated_at"
261
+ # "#{column} #{direction}, name ASC"
262
+ # else
263
+ # "name ASC"
264
+ # end
265
+ # end
266
+ #
267
+ # Apply order:
268
+ #
269
+ # @records = Article.order(order) # Rails 3.
270
+ # @records = Article.all(:order => order) # Rails 2.
271
+ def sortable_column_order(&block)
272
+ conf = {}
273
+ conf[k = :sort_param] = sortable_columns_config[k]
274
+ conf[k = :default_sort_value] = sortable_columns_config[k]
275
+
276
+ # Parse sort param.
277
+ sort = params[conf[:sort_param]] || conf[:default_sort_value]
278
+ pp = parse_sortable_column_sort_param(sort)
279
+
280
+ order = if block
281
+ column, direction = pp[:column], pp[:direction]
282
+ yield(column, direction) # NOTE: Makes RDoc/ri look a little smarter.
283
+ else
284
+ # No block -- do a straight mapping.
285
+ if pp[:column]
286
+ [pp[:column], pp[:direction]].join(" ")
287
+ end
288
+ end
289
+
290
+ # Can be nil.
291
+ order
292
+ end
293
+
294
+ # Internal use only. Convert title to sortable column name.
295
+ #
296
+ # sortable_column_title_to_name("ProductName") # => "product_name"
297
+ def sortable_column_title_to_name(title) #:nodoc:
298
+ title.gsub(/(\s)(\S)/) {$2.upcase}.underscore
299
+ end
300
+
301
+ # Internal use only. Access/initialize feature's config.
302
+ def sortable_columns_config #:nodoc:
303
+ @sortable_columns_config ||= ::Handles::SortableColumns::Config.new
304
+ end
305
+ end # InstanceMethods
306
+ end # SortableColumns
307
+ end # Handles
@@ -0,0 +1,5 @@
1
+ # Rails gem init.
2
+
3
+ # NOTE: Rails 3 seems to require exact order.
4
+ require File.join(File.dirname(__FILE__), "handles/sortable_columns")
5
+ require File.join(File.dirname(__FILE__), "action_controller/base/handles_sortable_columns")
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "tvdeyen-handles_sortable_columns"
5
+ s.version = "0.1.5"
6
+ s.authors = ["Alex Fortuna", "Thomas von Deyen"]
7
+ s.summary = "Sortable Table Columns"
8
+ s.description = "Sortable Table Columns"
9
+ s.license = "MIT"
10
+ s.email = "tvdeyen@gmail.com"
11
+ s.extra_rdoc_files = [
12
+ "README.html",
13
+ "README.md"
14
+ ]
15
+ s.files = `git ls-files`.split("\n")
16
+ s.homepage = "https://github.com/tvdeyen/handles_sortable_columns"
17
+ s.require_paths = ["lib"]
18
+ end
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tvdeyen-handles_sortable_columns
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.5
5
+ platform: ruby
6
+ authors:
7
+ - Alex Fortuna
8
+ - Thomas von Deyen
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-03-27 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Sortable Table Columns
15
+ email: tvdeyen@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files:
19
+ - README.html
20
+ - README.md
21
+ files:
22
+ - .gitignore
23
+ - MIT-LICENSE
24
+ - README.html
25
+ - README.md
26
+ - Rakefile
27
+ - VERSION.yml
28
+ - dev/github.css
29
+ - dev/head.html
30
+ - init.rb
31
+ - lib/action_controller/base/handles_sortable_columns.rb
32
+ - lib/handles/sortable_columns.rb
33
+ - lib/handles_sortable_columns.rb
34
+ - tvdeyen-handles_sortable_columns.gemspec
35
+ homepage: https://github.com/tvdeyen/handles_sortable_columns
36
+ licenses:
37
+ - MIT
38
+ metadata: {}
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubyforge_project:
55
+ rubygems_version: 2.0.3
56
+ signing_key:
57
+ specification_version: 4
58
+ summary: Sortable Table Columns
59
+ test_files: []
60
+ has_rdoc: