king_views 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +84 -0
- data/Rakefile +31 -0
- data/VERSION +1 -0
- data/init.rb +3 -0
- data/king_form/MIT-LICENSE +20 -0
- data/king_form/README.rdoc +64 -0
- data/king_form/Rakefile +23 -0
- data/king_form/init.rb +1 -0
- data/king_form/lib/king_form.rb +19 -0
- data/king_form/lib/king_form/builder/base.rb +238 -0
- data/king_form/lib/king_form/builder/definition_list.rb +119 -0
- data/king_form/lib/king_form/builder/form_fields.rb +333 -0
- data/king_form/lib/king_form/builder/form_fields_overrides.rb +146 -0
- data/king_form/lib/king_form/builder/labeled.rb +116 -0
- data/king_form/lib/king_form/helper.rb +97 -0
- data/king_form/lib/king_form/nested_form_helper.rb +61 -0
- data/king_form/lib/king_form/overrides.rb +25 -0
- data/king_form/tasks/king_forms_tasks.rake +4 -0
- data/king_form/test/king_forms_test.rb +8 -0
- data/king_form/test/test_helper.rb +3 -0
- data/king_format/MIT-LICENSE +20 -0
- data/king_format/README.rdoc +20 -0
- data/king_format/Rakefile +23 -0
- data/king_format/init.rb +1 -0
- data/king_format/lib/helpers/date_helper.rb +25 -0
- data/king_format/lib/helpers/formatting_helper.rb +108 -0
- data/king_format/lib/helpers/money_helper.rb +63 -0
- data/king_format/lib/king_format.rb +14 -0
- data/king_format/lib/model_mixins/has_date_fields.rb +42 -0
- data/king_format/lib/model_mixins/has_money_fields.rb +42 -0
- data/king_format/lib/model_mixins/has_percent_fields.rb +34 -0
- data/king_format/tasks/king_format_tasks.rake +4 -0
- data/king_format/test/king_format_test.rb +8 -0
- data/king_format/test/test_helper.rb +3 -0
- data/king_list/MIT-LICENSE +20 -0
- data/king_list/README.rdoc +21 -0
- data/king_list/Rakefile +23 -0
- data/king_list/init.rb +1 -0
- data/king_list/lib/king_list.rb +18 -0
- data/king_list/lib/king_list/app_helper.rb +30 -0
- data/king_list/lib/king_list/builder/show.rb +71 -0
- data/king_list/lib/king_list/builder/table.rb +166 -0
- data/king_list/lib/king_list/list_helper.rb +329 -0
- data/king_list/lib/king_list/overrides.rb +6 -0
- data/king_list/tasks/king_list_tasks.rake +4 -0
- data/king_list/test/king_list_test.rb +8 -0
- data/king_list/test/test_helper.rb +3 -0
- data/king_views.gemspec +85 -0
- metadata +110 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 [name of plugin creator]
|
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,21 @@
|
|
1
|
+
= KingList
|
2
|
+
|
3
|
+
King List provides helpers to be used in table listings and detail views.
|
4
|
+
It has function for action icons, buttons, actions links and icons with hidden
|
5
|
+
forms used to simulate PUT or DELETE requests
|
6
|
+
|
7
|
+
== Example
|
8
|
+
Please read the files in lib/ for further documentation and examples
|
9
|
+
|
10
|
+
A tabled view
|
11
|
+
- table_for(@object) do
|
12
|
+
= t.column :firstname
|
13
|
+
= t.column :lastname, :sorting=>false
|
14
|
+
|
15
|
+
A definition list view
|
16
|
+
- dl_for current_object do |f|
|
17
|
+
= f.show :creator
|
18
|
+
= f.show :created_at
|
19
|
+
= f.show :updated_at
|
20
|
+
|
21
|
+
Copyright (c) 2009 Georg Leciejewski, released under the MIT license
|
data/king_list/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the king_list plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.libs << 'test'
|
12
|
+
t.pattern = 'test/**/*_test.rb'
|
13
|
+
t.verbose = true
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'Generate documentation for the king_list plugin.'
|
17
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
18
|
+
rdoc.rdoc_dir = 'rdoc'
|
19
|
+
rdoc.title = 'KingList'
|
20
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
21
|
+
rdoc.rdoc_files.include('README')
|
22
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
23
|
+
end
|
data/king_list/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/lib/king_list"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# KingList
|
2
|
+
# You need:
|
3
|
+
# KingFormat Plugin for the table helper
|
4
|
+
# - haml
|
5
|
+
# - I18n
|
6
|
+
$LOAD_PATH << File.expand_path(File.dirname(__FILE__))
|
7
|
+
require "king_list/overrides"
|
8
|
+
require "king_list/list_helper"
|
9
|
+
require "king_list/app_helper"
|
10
|
+
require "king_list/builder/table"
|
11
|
+
require "king_list/builder/show"
|
12
|
+
|
13
|
+
|
14
|
+
# extend AC with our helper module
|
15
|
+
ActionController::Base.helper KingList::ListHelper
|
16
|
+
|
17
|
+
# Helper Functions used in application controller, which should be extracted a little more
|
18
|
+
ActionController::Base.helper KingList::AppHelper
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module KingList
|
2
|
+
# Functions in here are only used by the table helper. Those should be moved
|
3
|
+
# to a more general place or an own king view helper
|
4
|
+
module AppHelper
|
5
|
+
# Returns the "real" (in URL visible) parameters of the current URL. That means all but the keys "action" and "controller"
|
6
|
+
def visible_params
|
7
|
+
@visible_params ||= params.dup.delete_if{|key,value| [:action, :controller].include?(key.to_sym)}
|
8
|
+
end
|
9
|
+
|
10
|
+
# Change some params of the current URL (and preserve all others)
|
11
|
+
# Example:
|
12
|
+
# If the current URL is
|
13
|
+
# /clients?filter[letter]=T&filter[tags]=abc&mode=cards
|
14
|
+
# and you call:
|
15
|
+
# change_params(:mode => 'list')
|
16
|
+
# The result is:
|
17
|
+
# => /clients?filter[letter]=T&filter[tags]=abc&mode=list
|
18
|
+
#
|
19
|
+
# Attention, this method uses deep_merge, so it works recursive.
|
20
|
+
# See this example: If you call
|
21
|
+
# change_params(:filter => { :letter => 'S' })
|
22
|
+
# you get
|
23
|
+
# => /clients?filter[letter]=S&filter[tags]=abc&mode=list
|
24
|
+
# Beware that filter[tags] is NOT removed!
|
25
|
+
def change_params(options={})
|
26
|
+
visible_params.deep_merge(options)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module KingList
|
2
|
+
module Builder
|
3
|
+
class Show
|
4
|
+
|
5
|
+
def initialize(object_name, object, template)
|
6
|
+
@object_name = object_name
|
7
|
+
@object = object
|
8
|
+
@template = template
|
9
|
+
end
|
10
|
+
|
11
|
+
#
|
12
|
+
# ==== Parameter
|
13
|
+
# field_name<Symbol>:: The name of the field for the current object
|
14
|
+
# options<Hash{:Symbol=>String}>:: A bunch of options to customize the output
|
15
|
+
#
|
16
|
+
# ==== Options hash:
|
17
|
+
# :object => record. If not set the current_current is used
|
18
|
+
# :value => cell content (if not set, it will be determined by object.field_name)
|
19
|
+
# :link => if set, the value is placed in a link_to
|
20
|
+
# :caption => text for dt-tag. If not set, the title is created automaticaly
|
21
|
+
#
|
22
|
+
# === Example haml
|
23
|
+
# = f.show :created_at
|
24
|
+
# = f.show :caption => 'Calculated', :value => 39.80
|
25
|
+
#
|
26
|
+
# valid html options will be applied to both dt and dd
|
27
|
+
# options[:class] =>will be applied to dt and dd
|
28
|
+
#
|
29
|
+
# TODO:
|
30
|
+
# rename :caption to :title .. if it does not conflict
|
31
|
+
def show(field_name, options={})
|
32
|
+
if field_name.is_a?(Hash) && options.empty? # Short call without field_name
|
33
|
+
options = field_name
|
34
|
+
field_name = nil
|
35
|
+
|
36
|
+
# Value and caption are needed
|
37
|
+
raise ArgumentError unless options.has_key?(:caption)
|
38
|
+
raise ArgumentError unless options.has_key?(:value)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Use given object or current_record as default
|
42
|
+
if options.has_key?(:object)
|
43
|
+
object = options.delete(:object)
|
44
|
+
else
|
45
|
+
object = @object
|
46
|
+
end
|
47
|
+
|
48
|
+
# Use given caption or translate column title
|
49
|
+
caption = options.delete(:caption) || object.class.human_attribute_name(field_name.to_s)
|
50
|
+
|
51
|
+
# Use given value or take formatted value as default
|
52
|
+
value = options.delete(:value) || @template.formatted_value(object, field_name) || ' '
|
53
|
+
|
54
|
+
# if link option is set, then link to this object
|
55
|
+
if link = options.delete(:link)
|
56
|
+
value = @template.link_to(value, link)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Against HTML validity warnings
|
60
|
+
caption = ' ' if caption.blank?
|
61
|
+
value = ' ' if value.blank?
|
62
|
+
|
63
|
+
@template.capture_haml do
|
64
|
+
@template.haml_tag :dt, caption, options
|
65
|
+
@template.haml_tag :dd, value, options
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end #class
|
70
|
+
end # module
|
71
|
+
end # module
|
@@ -0,0 +1,166 @@
|
|
1
|
+
module KingList
|
2
|
+
module Builder
|
3
|
+
class Table
|
4
|
+
|
5
|
+
attr_accessor :mode, :current_record, :current_column_number, :number_of_columns, :sorting
|
6
|
+
|
7
|
+
def initialize(template, collection, &block)
|
8
|
+
@template = template
|
9
|
+
@collection = collection
|
10
|
+
end
|
11
|
+
|
12
|
+
def start_row(data)
|
13
|
+
self.current_column_number = 0
|
14
|
+
self.current_record = data
|
15
|
+
end
|
16
|
+
|
17
|
+
# Build a column for a table
|
18
|
+
#
|
19
|
+
# ==== Parameter
|
20
|
+
# field_name<Symbol>:: Name of the object attribute (db column) to show in this column
|
21
|
+
# options<Hash{Hash, Symbol=>String}>:: A bunch of options to customize the th, td or content of the column
|
22
|
+
#
|
23
|
+
# ==== Options hash:
|
24
|
+
# :object => The record to use. If not set the current_object is used
|
25
|
+
# :value => cell content (if not set, it will be determined by calling field_name on object/current_record) => @client.name
|
26
|
+
# :link => if set, the value is wrapped in a link_to with the given link (if TRUE, the current object is used)
|
27
|
+
# :row_link => if set, the value is wrapped in a link_to with the given link (if TRUE, the current object is used)
|
28
|
+
# :title => text for column title. If not set, the title is created automaticaly
|
29
|
+
# :sort_fields => optional fields for order_by (if the column field does not exist in the database)
|
30
|
+
# :sorting => false to prevent sorting on this column
|
31
|
+
# :th_options{Symbol=>String}:: options for the <th>
|
32
|
+
# :class:: the class to set on the th
|
33
|
+
# :td_options{Symbol=>String}:: options for the <td>
|
34
|
+
# :class:: the class to set on the th
|
35
|
+
# :align => classes used for alignment. Values are :left or :right
|
36
|
+
def column(field_name, options = {})
|
37
|
+
options = options.deep_clone # for not changing outer variable
|
38
|
+
th_options = options[:th_options] || {}
|
39
|
+
td_options = options[:td_options] || {}
|
40
|
+
|
41
|
+
# Use given object from options (or current_record as default)
|
42
|
+
object = options.has_key?(:object) ? options.delete(:object) : current_record
|
43
|
+
|
44
|
+
# Cell alignment
|
45
|
+
align = options.delete(:align)
|
46
|
+
(th_options[:class] ||= '') << " #{align}" if align == :right
|
47
|
+
(td_options[:class] ||= '') << " #{align}" if align == :right
|
48
|
+
|
49
|
+
self.current_column_number += 1
|
50
|
+
|
51
|
+
case mode
|
52
|
+
when :counter
|
53
|
+
self.number_of_columns ||= 0
|
54
|
+
self.number_of_columns += 1
|
55
|
+
nil
|
56
|
+
|
57
|
+
when :header
|
58
|
+
# Take option or translate column title
|
59
|
+
title_text = options[:title] || object.class.human_attribute_name(field_name.to_s)
|
60
|
+
|
61
|
+
# whole table has sorting enabled and current column has NOT :sorting=>false
|
62
|
+
# => put sorting link into header
|
63
|
+
if sorting && (options.delete(:sorting) != false)
|
64
|
+
# Use given sort_fields or try to detect them automatic
|
65
|
+
sort_fields = options.delete(:sort_fields) || object.class.table_name + '.' + field_name.to_s
|
66
|
+
# Convert to comma separated string if it is an array
|
67
|
+
sort_fields = sort_fields.join(',') if sort_fields.is_a?(Array)
|
68
|
+
# Swap ASC/DESC on every click of the same column title
|
69
|
+
sort = (@template.params[:sort] == "ASC") ? 'DESC' : 'ASC'
|
70
|
+
# Now build the title
|
71
|
+
title = @template.link_to(title_text, @template.change_params(:sort_by => sort_fields, :sort => sort))
|
72
|
+
# if current sorting use class for css up/down image
|
73
|
+
if @template.params[:sort_by] == sort_fields
|
74
|
+
(th_options[:class] ||= '') << ( sort=='DESC' ? ' sortup' : ' sortdown')
|
75
|
+
end
|
76
|
+
else
|
77
|
+
# otherwise just plain text (no sorting link)
|
78
|
+
title = title_text
|
79
|
+
end
|
80
|
+
#mark the first and last columns with css classes
|
81
|
+
if self.current_column_number == 1
|
82
|
+
(th_options[:class] ||= '') << ' first'
|
83
|
+
elsif self.current_column_number == self.number_of_columns
|
84
|
+
(th_options[:class] ||= '') << ' last'
|
85
|
+
end
|
86
|
+
@template.capture_haml do
|
87
|
+
@template.haml_tag(:th, title.to_s, th_options)
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
when :content
|
92
|
+
# Use given value (or formatted value as default)
|
93
|
+
value = options.delete(:value) || @template.formatted_value(object, field_name, value)
|
94
|
+
|
95
|
+
# If link option is set, then link to this
|
96
|
+
#
|
97
|
+
# ===Example
|
98
|
+
#
|
99
|
+
# :link => true : uses current object show link
|
100
|
+
#
|
101
|
+
# :link => nil or blank no linking
|
102
|
+
#
|
103
|
+
if link = options.delete(:link)
|
104
|
+
#link to current_oject if true given
|
105
|
+
link = object if link == true
|
106
|
+
if (!value.blank?) && (!link.blank?) #link and linked text is present
|
107
|
+
value = @template.link_to(value, link)
|
108
|
+
else #leave col text empty
|
109
|
+
value = ''
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# If row_link option is set, then link to the current object
|
114
|
+
if row_link = options.delete(:row_link)
|
115
|
+
row_link = object if row_link == true
|
116
|
+
value = @template.link_to(value, row_link) unless value.blank?
|
117
|
+
|
118
|
+
# Set a css class for the <td>, so it can be found via JavaScript
|
119
|
+
# and an onclick-event can be installed (TODO)
|
120
|
+
td_options.merge!(:class => 'row_link')
|
121
|
+
end
|
122
|
+
@template.capture_haml do
|
123
|
+
@template.haml_tag(:td, value.to_s, td_options)
|
124
|
+
end
|
125
|
+
# @template.haml_concat
|
126
|
+
end # case mode
|
127
|
+
end
|
128
|
+
|
129
|
+
#build a table column which holds action links (edit/del/show/..) for each record
|
130
|
+
#is used for table listings ex. on index pages
|
131
|
+
#get a block containing multiple #action_
|
132
|
+
# ===Example haml
|
133
|
+
# - t.action_column do
|
134
|
+
# = action_icon :edit, edit_path(person)
|
135
|
+
# = action_icon :delete, destroy_path(person)
|
136
|
+
def action_column(options={}, &block)
|
137
|
+
self.current_column_number += 1
|
138
|
+
|
139
|
+
case mode
|
140
|
+
when :counter
|
141
|
+
self.number_of_columns ||= 0
|
142
|
+
self.number_of_columns += 1
|
143
|
+
nil
|
144
|
+
when :header
|
145
|
+
options = { :align => :left }
|
146
|
+
if self.current_column_number == 1
|
147
|
+
options[:class] = 'first'
|
148
|
+
elsif self.current_column_number == self.number_of_columns
|
149
|
+
options[:class] = 'last'
|
150
|
+
end
|
151
|
+
|
152
|
+
@template.haml_tag :th, options do
|
153
|
+
@template.haml_concat I18n.t(:'link.actions')
|
154
|
+
end
|
155
|
+
when :content
|
156
|
+
@template.haml_tag :td, :class => 'actions' do
|
157
|
+
@template.haml_tag :ul, :class => 'actions' do
|
158
|
+
@template.haml_concat @template.capture_haml(&block)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
end #TableBuilder
|
165
|
+
end # module
|
166
|
+
end # module
|
@@ -0,0 +1,329 @@
|
|
1
|
+
module KingList
|
2
|
+
# The List Helper aides in lists anddetail views by providing helpers for:
|
3
|
+
# tables, action icons, action buttons and action links, definition list helper
|
4
|
+
module ListHelper
|
5
|
+
|
6
|
+
# Build a definition list(dl/dt/dd) for a collection
|
7
|
+
# Usage examples:
|
8
|
+
# - dl_for(client)
|
9
|
+
# - dl_for(:client, my_client_object)
|
10
|
+
# === Example haml
|
11
|
+
# - dl_for(current_object) do |f|
|
12
|
+
# - f.show :first_name
|
13
|
+
# - f.show :last_name
|
14
|
+
#
|
15
|
+
# => <dl>
|
16
|
+
# <dt>Firstname</dt>
|
17
|
+
# <dd>Otto</dd>
|
18
|
+
# <dt>Lastname</dt>
|
19
|
+
# <dd>Bismark</dd>
|
20
|
+
# </dl>
|
21
|
+
#
|
22
|
+
# Parameters are like "form_for"
|
23
|
+
def dl_for(record_or_name, *args)
|
24
|
+
raise ArgumentError, "Missing block" unless block_given?
|
25
|
+
|
26
|
+
options = args.extract_options!
|
27
|
+
case record_or_name
|
28
|
+
when String, Symbol
|
29
|
+
object_name = record_or_name
|
30
|
+
object = args.first
|
31
|
+
else
|
32
|
+
object = record_or_name
|
33
|
+
object_name = ActionController::RecordIdentifier.singular_class_name(object)
|
34
|
+
end
|
35
|
+
|
36
|
+
haml_tag :dl, options do
|
37
|
+
yield KingList::Builder::Show.new(object_name, object, @template)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Create a section
|
42
|
+
# A section is a group of related object information and
|
43
|
+
# generates a fieldset with optional legend
|
44
|
+
#
|
45
|
+
# === Example haml
|
46
|
+
# - section :caption => _('legend.user.details'), :class => 'my_css_class' do
|
47
|
+
# %p= "This is the content"
|
48
|
+
#
|
49
|
+
# => # <fieldset>
|
50
|
+
# <legend>User Details</legend>
|
51
|
+
# <p>This is the content</p>
|
52
|
+
# </fieldset>
|
53
|
+
#
|
54
|
+
def section(options = {}, &block)
|
55
|
+
# Short form of usage
|
56
|
+
if options.is_a?(String)
|
57
|
+
caption = options
|
58
|
+
options = {}
|
59
|
+
end
|
60
|
+
|
61
|
+
caption ||= options.delete(:caption)
|
62
|
+
|
63
|
+
@template.haml_tag :fieldset, options do
|
64
|
+
@template.haml_tag :legend, caption unless caption.blank?
|
65
|
+
@template.haml_concat @template.capture_haml(&block)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Create a div for form actions
|
70
|
+
def actions(options = {}, &block)
|
71
|
+
@template.haml_tag :div, options.merge(:class => 'form_actions') do
|
72
|
+
@template.haml_concat @template.capture_haml(&block)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Build a table-tag for a collection
|
77
|
+
#
|
78
|
+
# Available option keys:
|
79
|
+
# :sorting => Enable/Disable sorting for ALL columns (default is true)
|
80
|
+
#
|
81
|
+
# === Usage example:
|
82
|
+
#
|
83
|
+
# Header linking for all, default
|
84
|
+
# - table_for(@users) do |t, user|
|
85
|
+
# - t.column :name # with sorting
|
86
|
+
# - t.column :email # with sorting
|
87
|
+
#
|
88
|
+
# Header linking for all, but exclude individual columns from sorting:
|
89
|
+
# - table_for(@users)do |t, user|
|
90
|
+
# - t.column :name, :sorting => false # without sorting
|
91
|
+
# - t.column :last_name # with sorting
|
92
|
+
#
|
93
|
+
# NO header linking for all columns:
|
94
|
+
# - table_for(@users, :sorting => false) do |t, user|
|
95
|
+
# - t.column :name # without sorting
|
96
|
+
# - t.column :email # without sorting
|
97
|
+
#
|
98
|
+
# No header linking for all, but allow sorting for individual columns:
|
99
|
+
# - table_for(@users, :sorting => false) do |t, user|
|
100
|
+
# - t.column :name, :sorting => true # with sorting
|
101
|
+
# - t.column :last_name # without sorting
|
102
|
+
#
|
103
|
+
def table_for(collection, options={}, html_options={}, &block)
|
104
|
+
return if collection.nil? || collection.empty?
|
105
|
+
|
106
|
+
builder = KingList::Builder::Table.new(@template, collection)
|
107
|
+
# extract options
|
108
|
+
builder.sorting = options.delete(:sorting) != false # default => true
|
109
|
+
|
110
|
+
# First step: Yield the block just for counting the columns
|
111
|
+
builder.mode = :counter
|
112
|
+
builder.start_row(collection.first)
|
113
|
+
yield(builder, builder.current_record)
|
114
|
+
|
115
|
+
haml_tag :table, { :summary => '' }.merge(html_options) do
|
116
|
+
# Build header row
|
117
|
+
haml_tag :thead do
|
118
|
+
haml_tag :tr do
|
119
|
+
builder.mode = :header
|
120
|
+
builder.start_row(collection.first)
|
121
|
+
yield(builder, builder.current_record)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# TODO: Build footer here
|
126
|
+
# haml_tag :tfoot do
|
127
|
+
# end
|
128
|
+
|
129
|
+
haml_tag :tbody do
|
130
|
+
builder.mode = :content
|
131
|
+
# Build content row for each collection item
|
132
|
+
collection.each do |c|
|
133
|
+
tr_options = {}
|
134
|
+
# zebra styling
|
135
|
+
tr_options[:class] = @template.cycle('odd','even')
|
136
|
+
|
137
|
+
haml_tag :tr, tr_options do
|
138
|
+
builder.start_row(c)
|
139
|
+
yield(builder, builder.current_record)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Show a list of options as ul / li list.
|
148
|
+
# Each actions li gets a special class so image replacement can be done via css
|
149
|
+
# ==== Example
|
150
|
+
# - action_group do
|
151
|
+
# = action_icon :edit, edit_object_path(client)
|
152
|
+
# = action_icon :invoice_add, new_client_invoice_path(client), :title => 'New Invoice'
|
153
|
+
# = action_text t(:'web_templates.new'), new_object_path,{},{ :class=>'btn_add'}
|
154
|
+
# # <ul class="actions">
|
155
|
+
# <li class="button delete">
|
156
|
+
# <a href="delete/id">delete</a>
|
157
|
+
def action_group(caption=nil, options={}, &block)
|
158
|
+
if caption && !caption.empty?
|
159
|
+
haml_tag :span, caption, { :class => 'caption' }
|
160
|
+
end
|
161
|
+
|
162
|
+
options[:class] ||= 'actions'
|
163
|
+
haml_tag :ul, options do
|
164
|
+
haml_concat capture_haml(&block)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# Renders a <li> with a link shown as icon
|
169
|
+
# The link text is hidden via css image replacement and only an icon is shown
|
170
|
+
#
|
171
|
+
# ==== Example
|
172
|
+
# action_icon :show, show_user(user), :title => "Show User details"
|
173
|
+
# => <li class="show"><a href="/users/show" title="Show User details"><span>show</span></a></li>
|
174
|
+
# ==== Parameter
|
175
|
+
# name<String>:: The name of the action which is taken in the translated title,
|
176
|
+
# and li class (if no custom class is present in li_options )
|
177
|
+
# li_options<Hash{Symbol=>String}>:: Options for the li-element
|
178
|
+
# link_options<Hash>:: Options passed on to rails link_to method #
|
179
|
+
# html_options<Hash>:: Options passed on to rails link_to method
|
180
|
+
# ==== Options li_options
|
181
|
+
# :title - the html title tag for the li
|
182
|
+
# :class - the html class tag for the li
|
183
|
+
def action_icon(name, link_options={}, li_options={}, html_options={})
|
184
|
+
li_options[:title] ||= case name
|
185
|
+
# Some known names with their titles
|
186
|
+
when :edit then t(:'link.edit')
|
187
|
+
when :pdf then t(:'link.pdf')
|
188
|
+
when :show then t(:'link.show')
|
189
|
+
when :delete then t(:'link.delete')
|
190
|
+
when :copy then t(:'link.copy')
|
191
|
+
when :comment then t(:'link.comment')
|
192
|
+
when :send_email then t(:'link.send_email')
|
193
|
+
end
|
194
|
+
(li_options[:class] ||= '') << " icon #{name}"
|
195
|
+
|
196
|
+
action :icon, name, link_options, li_options, html_options
|
197
|
+
end
|
198
|
+
|
199
|
+
# Renders a <li> with a link shown as text
|
200
|
+
# You can set html options for both the li and the a tag
|
201
|
+
#
|
202
|
+
#===Example haml
|
203
|
+
# action_text _('link.user.edit'), edit_object_path
|
204
|
+
# action_text _('link.user.edit'), edit_object_path, {li html options}, {a html options :class=>'supercssclass'}
|
205
|
+
#
|
206
|
+
# => <li>
|
207
|
+
# <a href="/users/edit/12">
|
208
|
+
# link.user.edit
|
209
|
+
# </a>
|
210
|
+
# </li>
|
211
|
+
#
|
212
|
+
def action_text(title, link_options, li_options={}, html_options={})
|
213
|
+
# Prepare the css-class for the <li>
|
214
|
+
li_options[:class] ||= ''
|
215
|
+
li_options[:class] << ' active' if li_options.delete(:active)
|
216
|
+
|
217
|
+
#kill class attribute if still empty
|
218
|
+
li_options.delete(:class) if li_options[:class].empty?
|
219
|
+
action :text, title, link_options, li_options, html_options
|
220
|
+
end
|
221
|
+
|
222
|
+
# Renders a <li> with a button that will submit a form to a given url.
|
223
|
+
# This allows to make POST/PUT/DELETE request instead of using a link which triggers a GET.
|
224
|
+
#
|
225
|
+
# The button tags name attribute will be set to the <tt>name</tt> paramter followed by
|
226
|
+
# either the <tt>:id</tt> url_for_options value or a <tt>:number</tt> option either is
|
227
|
+
# available.
|
228
|
+
#
|
229
|
+
# ==== Parameters
|
230
|
+
# fieldname<String>:: the name attribute of the hidden form field f.ex. 'status' or 'invoice[status]'
|
231
|
+
# options<Hash>:: a couple of options explained further on
|
232
|
+
#
|
233
|
+
# ==== Options
|
234
|
+
# :method<Symbol>::form request method: :post / :put / :delete
|
235
|
+
# :url<String>:: The url the form is submitted to
|
236
|
+
# :title<String>::Button title and text
|
237
|
+
# :value<String>::the hidden field value
|
238
|
+
# :class<String>::button class
|
239
|
+
#
|
240
|
+
# ==== Example
|
241
|
+
# = action_button 'order_status', {:value=>'open', :title=> "Change Status to open", :method => :put}
|
242
|
+
#
|
243
|
+
#
|
244
|
+
# ==== Returns
|
245
|
+
# <form>
|
246
|
+
# <div>
|
247
|
+
# <input type="hidden" value="put" name="_method"/>
|
248
|
+
# <input type="hidden" value="939f3c1dc225bcaa2e5c2bd88910537901dc19d6" name="authenticity_token"/>
|
249
|
+
# <input type="hidden" value="open" name="order_status"/>
|
250
|
+
# <button type='submit' class="some_class" title="Change Status to open">Change Status to open</button>
|
251
|
+
# </div>
|
252
|
+
# </form>
|
253
|
+
#
|
254
|
+
def action_button(fieldname, options)
|
255
|
+
@template.capture_haml do
|
256
|
+
haml_tag :li, :class=>'form_btn' do
|
257
|
+
haml_concat mini_action_form(fieldname, options)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
def action_link(fieldname, options)
|
262
|
+
haml_concat mini_action_form(fieldname, options)
|
263
|
+
end
|
264
|
+
|
265
|
+
def mini_action_form(fieldname, options)
|
266
|
+
method_tag = ''
|
267
|
+
if (method = options.delete(:method)) && %w{put delete}.include?(method.to_s)
|
268
|
+
method_tag = tag('input', :type => 'hidden', :name => '_method', :value => method.to_s)
|
269
|
+
end
|
270
|
+
|
271
|
+
form_method = method.to_s == 'get' ? 'get' : 'post'
|
272
|
+
|
273
|
+
request_token_tag = ''
|
274
|
+
if form_method == 'post' && protect_against_forgery?
|
275
|
+
request_token_tag = tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token)
|
276
|
+
end
|
277
|
+
|
278
|
+
hidden_tag = ''
|
279
|
+
hidden_tag = tag(:input, :type => "hidden", :name =>fieldname, :value => options[:value]) unless options[:value].blank?
|
280
|
+
|
281
|
+
"<form method=\"#{form_method}\" action=\"#{escape_once options[:url]}\"><div>" +
|
282
|
+
method_tag +
|
283
|
+
request_token_tag +
|
284
|
+
hidden_tag +
|
285
|
+
"<button type='submit' name='submit' title='#{options[:title]}' class='#{options[:class]}'><span>#{options[:title]}</span></button>" +
|
286
|
+
"</div></form>"
|
287
|
+
end
|
288
|
+
|
289
|
+
# Renders a <ol> for a given collection and yields the block for every item
|
290
|
+
# Options:
|
291
|
+
# :descending: if true, numbering is reversed (defaults to false)
|
292
|
+
def ordered_list_for(collection, options={}, &block)
|
293
|
+
if collection.nil? || collection.empty?
|
294
|
+
haml_tag :p, _('list.empty')
|
295
|
+
return
|
296
|
+
end
|
297
|
+
|
298
|
+
descending = options.delete(:descending)
|
299
|
+
|
300
|
+
haml_tag :ol, options do
|
301
|
+
collection.each_with_index do |c,i|
|
302
|
+
li_options = {}
|
303
|
+
li_options[:class] = @template.cycle('odd','even')
|
304
|
+
li_options[:value] = collection.length - i if descending
|
305
|
+
haml_tag :li, li_options do
|
306
|
+
yield(c)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
private
|
313
|
+
|
314
|
+
# Internal method used by action_text, action_button and action_icon
|
315
|
+
# Directly returns a haml string into the template
|
316
|
+
def action(kind, name_or_title, link_options, li_options={}, html_options={})
|
317
|
+
@template.capture_haml do
|
318
|
+
haml_tag :li, li_options do
|
319
|
+
case kind
|
320
|
+
when :icon then haml_concat link_to('', link_options, html_options)
|
321
|
+
when :text then haml_concat link_to(name_or_title, link_options, html_options)
|
322
|
+
when :button then haml_concat button_to(name_or_title, link_options)
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
end #ListHelper
|
329
|
+
end#module
|