king_views 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.
- 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
|