card-mod-tabs 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|