card-mod-tabs 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/card/lazy_tab.rb +38 -0
- data/lib/card/tab.rb +84 -0
- data/set/abstract/tabs.rb +123 -0
- data/set/all/tabs/tab_panel.haml +7 -0
- data/set/all/tabs.rb +40 -0
- metadata +84 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fbab1a56eced219926dff1cb29690243bcb43e1443f313ad785e5e31c1233ed5
|
4
|
+
data.tar.gz: 91e2a11e56d5152a639a688005ce7db83448e4f1fb7cf4dc0621f98db21949f0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c18bf3d6456a8ef0395878881105b6c0a7c6e31fde66219712bdfbc006b59c32522c5425736339eaa2268a4cfca61d5e2f42f53407bcd65157dc18ba8d1f88be
|
7
|
+
data.tar.gz: 1aa5fe4827f8f8ef78060de52c42f498b5265fab04f74e2e15979aaffe495ccbae4098d254c5b1cb8b0716f12089cfdefdea89d267fe86ab9d090c8335c7e7cb
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Card
|
2
|
+
# lazy-loading tabs. Tab panel content doesn't load until tab is visited.
|
3
|
+
class LazyTab < Tab
|
4
|
+
def url
|
5
|
+
@url ||= (config_hash? && @config[:path]) || format.path(view: view)
|
6
|
+
end
|
7
|
+
|
8
|
+
def view
|
9
|
+
@view ||= (config_hash? && @config[:view]) || @config
|
10
|
+
end
|
11
|
+
|
12
|
+
def tab_button
|
13
|
+
if url
|
14
|
+
super
|
15
|
+
else
|
16
|
+
wrap_with(:li, label, role: "presentation")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def button_attrib
|
21
|
+
@button_attrib ||= super.merge("data-url" => url.html_safe)
|
22
|
+
end
|
23
|
+
|
24
|
+
def tab_button_link
|
25
|
+
add_class button_attrib, "load" unless active?
|
26
|
+
super
|
27
|
+
end
|
28
|
+
|
29
|
+
def content
|
30
|
+
@content ||= ""
|
31
|
+
end
|
32
|
+
|
33
|
+
def tab_pane args=nil, &block
|
34
|
+
@content = yield if active? && block_given?
|
35
|
+
super
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/card/tab.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
class Card
|
2
|
+
# tab object, handles tab configuration for view :tabs
|
3
|
+
class Tab
|
4
|
+
attr_reader :format, :name
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def tab_objects format, tab_hash, active_name, klass=nil
|
8
|
+
klass ||= Card::Tab
|
9
|
+
active_name = active active_name, tab_hash.keys
|
10
|
+
tab_hash.map do |name, config|
|
11
|
+
klass.new format, name, active_name, config
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def active requested, keys
|
18
|
+
r = requested.to_name
|
19
|
+
r && keys.find { |k| k.to_name == r } || keys.first
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
delegate :add_class, :wrap_with, :unique_id, :link_to, to: :format
|
24
|
+
|
25
|
+
def initialize format, name, active_name, config
|
26
|
+
@format = format
|
27
|
+
@name = name
|
28
|
+
@active_name = active_name
|
29
|
+
@config = config
|
30
|
+
end
|
31
|
+
|
32
|
+
def tab_button
|
33
|
+
add_class button_attrib, "active" if active?
|
34
|
+
wrap_with :li, tab_button_link,
|
35
|
+
role: :presentation,
|
36
|
+
class: "nav-item tab-li-#{name}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def tab_pane args=nil
|
40
|
+
pane_attr = { role: :tabpanel, id: tab_id }
|
41
|
+
pane_attr.merge! args if args.present?
|
42
|
+
add_class pane_attr, "tab-pane tab-pane-#{name}"
|
43
|
+
add_class pane_attr, "active" if active?
|
44
|
+
wrap_with :div, content, pane_attr
|
45
|
+
end
|
46
|
+
|
47
|
+
def button_attrib
|
48
|
+
@button_attrib ||= (config_hash? && @config[:button_attr]) || {}
|
49
|
+
end
|
50
|
+
|
51
|
+
def content
|
52
|
+
@content ||= config_hash? ? @config[:content] : @config
|
53
|
+
end
|
54
|
+
|
55
|
+
def label
|
56
|
+
@label ||= (config_hash? && @config[:title]) || name
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def config_hash?
|
62
|
+
@config.is_a? Hash
|
63
|
+
end
|
64
|
+
|
65
|
+
def tab_button_link
|
66
|
+
add_class button_attrib, "nav-link"
|
67
|
+
|
68
|
+
link_to label, button_attrib.merge(
|
69
|
+
path: "##{tab_id}",
|
70
|
+
role: "tab",
|
71
|
+
"data-toggle" => "tab",
|
72
|
+
"data-tab-name" => name
|
73
|
+
)
|
74
|
+
end
|
75
|
+
|
76
|
+
def tab_id
|
77
|
+
@tab_id ||= "#{unique_id}-#{name.to_name.safe_key}"
|
78
|
+
end
|
79
|
+
|
80
|
+
def active?
|
81
|
+
name == @active_name
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
include_set Abstract::BsBadge
|
2
|
+
|
3
|
+
format :html do
|
4
|
+
view :tabs, cache: :never do
|
5
|
+
tabs tab_map, default_tab, load: :lazy do
|
6
|
+
_render! "#{default_tab}_tab"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def tab_map
|
11
|
+
@tab_map ||= generate_tab_map
|
12
|
+
end
|
13
|
+
|
14
|
+
def generate_tab_map
|
15
|
+
options = tab_options
|
16
|
+
tab_list.each_with_object({}) do |codename, hash|
|
17
|
+
hash[codename] = {
|
18
|
+
view: "#{codename}_tab",
|
19
|
+
title: tab_title(codename, options[codename])
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def tab_list
|
25
|
+
[]
|
26
|
+
end
|
27
|
+
|
28
|
+
def tab_options
|
29
|
+
{}
|
30
|
+
end
|
31
|
+
|
32
|
+
def one_line_tab?
|
33
|
+
false
|
34
|
+
end
|
35
|
+
|
36
|
+
def default_tab
|
37
|
+
tab_from_params || tab_map.keys.first
|
38
|
+
end
|
39
|
+
|
40
|
+
def tab_from_params
|
41
|
+
return unless Env.params[:tab]
|
42
|
+
Env.params[:tab].to_sym
|
43
|
+
end
|
44
|
+
|
45
|
+
def tab_wrap
|
46
|
+
bs_layout do
|
47
|
+
row 12 do
|
48
|
+
col output(yield), class: "padding-top-10"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def tab_url tab
|
54
|
+
path tab: tab
|
55
|
+
end
|
56
|
+
|
57
|
+
def tab_title fieldcode, opts={}
|
58
|
+
opts ||= {}
|
59
|
+
parts = tab_title_parts fieldcode, opts
|
60
|
+
info = tab_title_info parts[:icon], parts[:count]
|
61
|
+
wrapped_tab_title parts[:label], info
|
62
|
+
end
|
63
|
+
|
64
|
+
def tab_title_info icon, count
|
65
|
+
if count
|
66
|
+
tab_count_badge count, icon
|
67
|
+
else
|
68
|
+
icon || tab_space
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def tab_space
|
73
|
+
one_line_tab? ? :nil : " "
|
74
|
+
end
|
75
|
+
|
76
|
+
def tab_count_badge count, icon_tag
|
77
|
+
klass = nil
|
78
|
+
if count.is_a? Card
|
79
|
+
klass = css_classes count.safe_set_keys
|
80
|
+
count = count.try(:cached_count) || count.count
|
81
|
+
end
|
82
|
+
tab_badge count, icon_tag, klass: klass
|
83
|
+
end
|
84
|
+
|
85
|
+
def tab_title_parts fieldcode, opts
|
86
|
+
%i[count icon label].each_with_object({}) do |part, hash|
|
87
|
+
hash[part] = opts.key?(part) ? opts[part] : send("tab_title_#{part}", fieldcode)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def tab_title_count fieldcode
|
92
|
+
field_card = card.fetch fieldcode, new: {}
|
93
|
+
field_card if field_card.respond_to? :count
|
94
|
+
end
|
95
|
+
|
96
|
+
def tab_title_icon fieldcode
|
97
|
+
tab_icon_tag fieldcode
|
98
|
+
end
|
99
|
+
|
100
|
+
def tab_title_label fieldcode
|
101
|
+
fieldcode.cardname.vary :plural
|
102
|
+
end
|
103
|
+
|
104
|
+
def wrapped_tab_title label, info=nil
|
105
|
+
wrap_with :div, class: "tab-title text-center #{'one-line-tab' if one_line_tab?}" do
|
106
|
+
[wrapped_tab_title_info(info),
|
107
|
+
wrap_with(:span, label, class: "count-label")].compact
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def wrapped_tab_title_info info
|
112
|
+
info ||= tab_space
|
113
|
+
return unless info
|
114
|
+
|
115
|
+
klass = css_classes "count-number", "clearfix"
|
116
|
+
wrap_with :span, info, class: klass
|
117
|
+
end
|
118
|
+
|
119
|
+
# TODO: handle mapped icon tagging in decko
|
120
|
+
def tab_icon_tag key
|
121
|
+
try :mapped_icon_tag, key
|
122
|
+
end
|
123
|
+
end
|
data/set/all/tabs.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
format :html do
|
2
|
+
# @param tab_hash [Hash] keys are the tab names
|
3
|
+
# Each value can be either a String or a Hash.
|
4
|
+
# If a Hash can contain the following keys:
|
5
|
+
# :title - the label to appear in the clickable tab nav.
|
6
|
+
# if title is not specified, the key is used
|
7
|
+
# :content - body of tab pane
|
8
|
+
# :button_attr - attributes for button link in tab nav.
|
9
|
+
#
|
10
|
+
# If using lazy loading (see :load below), the following options also apply
|
11
|
+
# :path - explicit path to use for tab pane
|
12
|
+
# :view - card view from which to auto-construct path (if missing, uses key)
|
13
|
+
#
|
14
|
+
# If the value is a String, it is treated as the tab content for static tabs and
|
15
|
+
# the view for lazy tabs
|
16
|
+
#
|
17
|
+
# @param active_name [String] label of the tab that should be active at the
|
18
|
+
#
|
19
|
+
# @param [Hash] args options
|
20
|
+
# @option args [String] :tab_type ('tabs') use pills or tabs
|
21
|
+
# @option args [Hash] :panel_attr html args used for the panel div
|
22
|
+
# @option args [Hash] :pane_attr html args used for the pane div
|
23
|
+
# @option args [Hash] :load. `:lazy` for lazy-loading tabs
|
24
|
+
#
|
25
|
+
# @param [Block] block content of the active tab (for lazy-loading)
|
26
|
+
# beginning (default is the first)
|
27
|
+
#
|
28
|
+
# @return [HTML] bootstrap tabs element with all content preloaded
|
29
|
+
def tabs tab_hash, active_name=nil, args={}, &block
|
30
|
+
klass = args[:load] == :lazy ? Card::LazyTab : Card::Tab
|
31
|
+
args.reverse_merge!(
|
32
|
+
panel_attr: {},
|
33
|
+
pane_attr: {},
|
34
|
+
tab_type: "tabs",
|
35
|
+
block: block,
|
36
|
+
tab_objects: Card::Tab.tab_objects(self, tab_hash, active_name, klass)
|
37
|
+
)
|
38
|
+
haml :tab_panel, args
|
39
|
+
end
|
40
|
+
end
|
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: card-mod-tabs
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.14.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ethan McCutchen
|
8
|
+
- Philipp Kühl
|
9
|
+
- Gerry Gleason
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2021-12-22 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: card
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - '='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.104.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - '='
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: 1.104.0
|
29
|
+
- !ruby/object:Gem::Dependency
|
30
|
+
name: card-mod-bootstrap
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - '='
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: 0.14.0
|
36
|
+
type: :runtime
|
37
|
+
prerelease: false
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - '='
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 0.14.0
|
43
|
+
description: ''
|
44
|
+
email:
|
45
|
+
- info@decko.org
|
46
|
+
executables: []
|
47
|
+
extensions: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- lib/card/lazy_tab.rb
|
51
|
+
- lib/card/tab.rb
|
52
|
+
- set/abstract/tabs.rb
|
53
|
+
- set/all/tabs.rb
|
54
|
+
- set/all/tabs/tab_panel.haml
|
55
|
+
homepage: https://decko.org
|
56
|
+
licenses:
|
57
|
+
- GPL-3.0
|
58
|
+
metadata:
|
59
|
+
source_code_uri: https://github.com/decko-commons/decko
|
60
|
+
homepage_uri: https://decko.org
|
61
|
+
bug_tracker_uri: https://github.com/decko-commons/decko/issues
|
62
|
+
wiki_uri: https://decko.org
|
63
|
+
documentation_url: http://docs.decko.org/
|
64
|
+
card-mod: tabs
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options: []
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '2.5'
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
requirements: []
|
80
|
+
rubygems_version: 3.2.15
|
81
|
+
signing_key:
|
82
|
+
specification_version: 4
|
83
|
+
summary: tabs
|
84
|
+
test_files: []
|