navigasmic 0.5.6 → 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/LICENSE +7 -1
- data/lib/generators/navigasmic/install/POST_INSTALL +6 -0
- data/lib/generators/navigasmic/install/install_generator.rb +17 -0
- data/lib/generators/navigasmic/install/templates/initializer.rb +145 -0
- data/lib/navigasmic.rb +5 -146
- data/lib/navigasmic/builders/crumb_builder.rb +20 -0
- data/lib/navigasmic/builders/list_builder.rb +90 -0
- data/lib/navigasmic/builders/map_builder.rb +77 -0
- data/lib/navigasmic/core/builders.rb +109 -0
- data/lib/navigasmic/core/configuration.rb +38 -0
- data/lib/navigasmic/core/item.rb +66 -0
- data/lib/navigasmic/rails.rb +2 -0
- data/lib/navigasmic/rails/engine.rb +9 -0
- data/lib/navigasmic/rails/view_helpers.rb +18 -0
- data/lib/navigasmic/version.rb +3 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +13 -0
- data/spec/dummy/app/controllers/blog/links_controller.rb +7 -0
- data/spec/dummy/app/controllers/blog/posts_controller.rb +7 -0
- data/spec/dummy/app/views/application/welcome.html.erb +4 -0
- data/spec/dummy/app/views/application/welcome.xml.builder +2 -0
- data/spec/dummy/app/views/blog/links/index.html +4 -0
- data/spec/dummy/app/views/blog/links/show.html +4 -0
- data/spec/dummy/app/views/blog/posts/index.html +4 -0
- data/spec/dummy/app/views/blog/posts/show.html +4 -0
- data/spec/dummy/app/views/layouts/_navigation.html.erb +73 -0
- data/spec/dummy/app/views/layouts/application.html.erb +40 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +57 -0
- data/spec/dummy/config/boot.rb +9 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/evergreen.rb +47 -0
- data/spec/dummy/config/initializers/additional_navigasmic.rb +14 -0
- data/spec/dummy/config/initializers/navigasmic.rb +145 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +68 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/bootstrap.min.css +9 -0
- data/spec/dummy/public/bootstrap.min.js +6 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/jquery.min.js +2 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/spec_helper.rb +39 -0
- metadata +139 -63
- data/.document +0 -5
- data/README.textile +0 -276
- data/Rakefile +0 -57
- data/VERSION +0 -1
- data/lib/builders/html_builder.rb +0 -69
- data/lib/builders/xml_builder.rb +0 -51
- data/navigasmic.gemspec +0 -49
- data/test/navigasmic_test.rb +0 -7
- data/test/test_helper.rb +0 -10
data/LICENSE
CHANGED
@@ -1,4 +1,10 @@
|
|
1
|
-
|
1
|
+
Navigasmic is a semantic way to build beautifully simple navigation
|
2
|
+
structures in Rails.
|
3
|
+
|
4
|
+
Documentation and other useful information can be found at
|
5
|
+
https://github.com/jejacks0n/navigasmic
|
6
|
+
|
7
|
+
Copyright (c) 2011 Jeremy Jackson
|
2
8
|
|
3
9
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
10
|
a copy of this software and associated documentation files (the
|
@@ -0,0 +1,6 @@
|
|
1
|
+
+============================================================================+
|
2
|
+
Congratulations! Navigasmic was successfully installed. Documentation and more
|
3
|
+
can be found at: https://github.com/jejacks0n/navigasmic
|
4
|
+
|
5
|
+
You should start defining some navigation in config/initializers/navigasmic.rb
|
6
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Navigasmic
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path('../', __FILE__)
|
5
|
+
|
6
|
+
desc "Installs the Navigasmic initializer into your application."
|
7
|
+
|
8
|
+
def copy_initializer
|
9
|
+
copy_file 'templates/initializer.rb', 'config/initializers/navigasmic.rb'
|
10
|
+
end
|
11
|
+
|
12
|
+
def display_readme
|
13
|
+
readme 'POST_INSTALL' if behavior == :invoke
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
Navigasmic.setup do |config|
|
2
|
+
|
3
|
+
# Defining Navigation Structures:
|
4
|
+
#
|
5
|
+
# You can begin by defining your navigation structures here. You can also define them directly in the view if you'd
|
6
|
+
# like, but it's recommended to eventually move them here to clean help up your views. You can read about Navigasmic
|
7
|
+
# at https://github.com/jejacks0n/navigasmic
|
8
|
+
#
|
9
|
+
# When you're defining navigation here, it's basically the same as if you were doing it in the view but the scope is
|
10
|
+
# different. It's important to understand that -- and use procs where you want things to execute in the view scope.
|
11
|
+
#
|
12
|
+
# Once you've defined some navigation structures and configured your builders you can render navigation in your views
|
13
|
+
# using the `semantic_navigation` view helper. You can also use the same syntax to define your navigation structures
|
14
|
+
# in your views, and eventually move them here (it's handy to prototype navigation/css by putting them in the views
|
15
|
+
# first).
|
16
|
+
#
|
17
|
+
# <%= semantic_navigation :primary %>
|
18
|
+
#
|
19
|
+
# You can optionally provided a :builder and :config option to the semantic_navigation view helper.
|
20
|
+
#
|
21
|
+
# <%= semantic_navigation :primary, config: :blockquote %>
|
22
|
+
# <%= semantic_navigation :primary, builder: Navigasmic::Builder::MapBuilder %>
|
23
|
+
#
|
24
|
+
# When defining navigation in your views just pass it a block (the same as here basically).
|
25
|
+
#
|
26
|
+
# <%= semantic_navigation :primary do |n| %>
|
27
|
+
# <% n.item 'About Me' %>
|
28
|
+
# <% end %>
|
29
|
+
#
|
30
|
+
# Here's a basic example:
|
31
|
+
config.semantic_navigation :primary do |n|
|
32
|
+
|
33
|
+
n.item 'Home', '/'
|
34
|
+
|
35
|
+
# Groups and Items:
|
36
|
+
#
|
37
|
+
# You can create a structure using `group`, and `item`. You can nest items inside groups or items. In the
|
38
|
+
# following example, the "Articles" item will always highlight on the blog/posts controller, and the nested article
|
39
|
+
# items will only highlight when on those specific pages. The "Links" item will be disabled unless the user is
|
40
|
+
# logged in.
|
41
|
+
#
|
42
|
+
#n.group 'Blog' do
|
43
|
+
# n.item 'Articles', controller: '/blog/posts' do
|
44
|
+
# n.item 'First Article', '/blog/posts/1'
|
45
|
+
# n.item 'Second Article', '/blog/posts/2', map: {changefreq: 'weekly'}
|
46
|
+
# end
|
47
|
+
# n.item 'Links', controller: '/blog/links', disabled_if: proc{ !logged_in? }
|
48
|
+
#end
|
49
|
+
#
|
50
|
+
# You can hide specific specific items or groups. Here we specify that the "About" section of navigation should
|
51
|
+
# only be displayed if the user is logged in.
|
52
|
+
#
|
53
|
+
#n.group 'About', hidden_unless: proc{ logged_in? } do
|
54
|
+
# n.item 'About Me', class: 'featured', link_html: {class: 'about-me'}
|
55
|
+
#end
|
56
|
+
#
|
57
|
+
# Scoping:
|
58
|
+
#
|
59
|
+
# Scoping is different than in the view here, so we've provided some nice things for you to get around that. In
|
60
|
+
# the above example we just provide '/' as what the home page is, but that may not be correct. You can also access
|
61
|
+
# the path helpers, using a proc, or by proxying them through the navigation object. Any method called on the
|
62
|
+
# navigation scope will be called within the view scope.
|
63
|
+
#
|
64
|
+
#n.item 'Home', proc{ root_path }
|
65
|
+
#n.item 'Home', n.root_path
|
66
|
+
#
|
67
|
+
# This proxy behavior can be used for I18n as well.
|
68
|
+
#
|
69
|
+
#n.item n.t('hello'), '/'
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
# Setting the Default Builder:
|
75
|
+
#
|
76
|
+
# By default the Navigasmic::Builder::ListBuilder is used unless otherwise specified.
|
77
|
+
#
|
78
|
+
# You can change this here:
|
79
|
+
#config.default_builder = MyCustomBuilder
|
80
|
+
|
81
|
+
|
82
|
+
# Configuring Builders:
|
83
|
+
#
|
84
|
+
# You can change various builder options here by specifying the builder you want to configure and the options you
|
85
|
+
# want to change.
|
86
|
+
#
|
87
|
+
# Changing the default ListBuilder options:
|
88
|
+
config.builder Navigasmic::Builder::ListBuilder do |builder|
|
89
|
+
builder.wrapper_class = 'semantic-navigation'
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
# Naming Builder Configurations:
|
94
|
+
#
|
95
|
+
# If you want to define a named configuration for a builder, just provide a hash with the name, and the builder to
|
96
|
+
# configure. The named configurations can then be used during rendering by specifying a `:config => :bootstrap`
|
97
|
+
# option to the `semantic_navigation` view helper.
|
98
|
+
#
|
99
|
+
# A Twitter Bootstrap configuration:
|
100
|
+
#
|
101
|
+
# Example usage:
|
102
|
+
#
|
103
|
+
# <%= semantic_navigation :primary, config: :bootstrap, class: 'nav-pills' %>
|
104
|
+
#
|
105
|
+
# Or to create a full navigation bar using twitter bootstrap you could use the following in your view:
|
106
|
+
# <div class="navbar">
|
107
|
+
# <div class="navbar-inner">
|
108
|
+
# <a class="brand" href="/">Title</a>
|
109
|
+
# <%= semantic_navigation :primary, config: :bootstrap %>
|
110
|
+
# </div>
|
111
|
+
# </div>
|
112
|
+
config.builder bootstrap: Navigasmic::Builder::ListBuilder do |builder|
|
113
|
+
|
114
|
+
# Set the nav and nav-pills css (you can also use 'nav nav-tabs') -- or remove them if you're using this inside a
|
115
|
+
# navbar.
|
116
|
+
builder.wrapper_class = 'nav nav-pills'
|
117
|
+
|
118
|
+
# Set the classed for items that have nested items, and that are nested items.
|
119
|
+
builder.has_nested_class = 'dropdown'
|
120
|
+
builder.is_nested_class = 'dropdown-menu'
|
121
|
+
|
122
|
+
# For dropdowns to work you'll need to include the bootstrap dropdown js
|
123
|
+
# For groups, we adjust the markup so they'll be clickable and be picked up by the javascript.
|
124
|
+
builder.label_generator = proc do |label, has_link, has_nested|
|
125
|
+
if !has_nested || has_link
|
126
|
+
"<span>#{label}</span>"
|
127
|
+
else
|
128
|
+
link_to("#{label}<b class='caret'></b>".html_safe, '#', class: 'dropdown-toggle', data: {toggle: 'dropdown'})
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# For items, we adjust the links so they're '#', and do the same as for groups. This allows us to use more complex
|
133
|
+
# highlighting rules for dropdowns.
|
134
|
+
builder.link_generator = proc do |label, link, options, has_nested|
|
135
|
+
if has_nested
|
136
|
+
link = '#'
|
137
|
+
label << "<b class='caret'></b>"
|
138
|
+
options.merge!(class: 'dropdown-toggle', data: {toggle: 'dropdown'})
|
139
|
+
end
|
140
|
+
link_to(label, link, options)
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
data/lib/navigasmic.rb
CHANGED
@@ -1,147 +1,6 @@
|
|
1
|
-
|
2
|
-
require '
|
3
|
-
require 'builders/xml_builder'
|
1
|
+
require 'navigasmic/version'
|
2
|
+
require 'navigasmic/rails'
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
#
|
9
|
-
# Example Usage:
|
10
|
-
#
|
11
|
-
# <% semantic_navigation :primary, :html => {:class => 'primary'} do |n| %>
|
12
|
-
# <%= n.item 'Blog Posts', :link => {:controller => 'posts'} %>
|
13
|
-
# <% end %>
|
14
|
-
#
|
15
|
-
# <% semantic_navigation :primary, :builder => MyCustomBuilder do |n| %>
|
16
|
-
# <%= n.group 'My Thoughts' do %>
|
17
|
-
# <%= n.item 'Blog Posts', :link => {:controller => 'posts'} %>
|
18
|
-
# <% end %>
|
19
|
-
# <% end %>
|
20
|
-
#
|
21
|
-
# <% semantic_navigation :primary do |n| %>
|
22
|
-
# <%= n.group 'My Thoughts' do %>
|
23
|
-
# <%= n.item 'Blog Posts', :link => {:controller => 'posts'} do %>
|
24
|
-
# <ul>
|
25
|
-
# <%= n.item 'Recent Posts', :link => {:controller => 'posts', :action => 'recent'} %>
|
26
|
-
# </ul>
|
27
|
-
# <% end %>
|
28
|
-
# <% end %>
|
29
|
-
# <% end %>
|
30
|
-
module SemanticNavigationHelper
|
31
|
-
|
32
|
-
@@builder = ::Navigasmic::HtmlNavigationBuilder
|
33
|
-
mattr_accessor :builder
|
34
|
-
|
35
|
-
def semantic_navigation(name, *args, &proc)
|
36
|
-
raise ArgumentError, "Missing block" unless block_given?
|
37
|
-
|
38
|
-
options = args.extract_options!
|
39
|
-
|
40
|
-
options[:html] ||= {}
|
41
|
-
options[:html][:class] = add_html_class(options[:html][:class], 'semantic-navigation')
|
42
|
-
options[:html][:id] ||= name.to_s.underscore unless options[:html].has_key?(:id)
|
43
|
-
|
44
|
-
builder = options.delete(:builder) || @@builder
|
45
|
-
builder.new(self, name, options, &proc)
|
46
|
-
end
|
47
|
-
|
48
|
-
def add_html_class(classnames, classname)
|
49
|
-
out = (classnames.is_a?(String) ? classnames.split(' ') : []) << classname
|
50
|
-
out.join(' ')
|
51
|
-
end
|
52
|
-
|
53
|
-
end
|
54
|
-
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
class NavigationItem
|
61
|
-
|
62
|
-
attr_accessor :label, :link
|
63
|
-
|
64
|
-
def initialize(label, options = {}, template = nil)
|
65
|
-
@label = label
|
66
|
-
|
67
|
-
if options[:link]
|
68
|
-
@link = options[:link]
|
69
|
-
elsif template.present?
|
70
|
-
method = "#{label.to_s.underscore.gsub(/\s/, '_')}_path"
|
71
|
-
@link = template.send(method) if template.respond_to? method
|
72
|
-
end
|
73
|
-
@link ||= {}
|
74
|
-
|
75
|
-
@disabled_conditions = options[:disabled_if] || proc { false }
|
76
|
-
@visible = options[:hidden_unless].nil? ? true : options[:hidden_unless].is_a?(Proc) ? template.instance_eval(&options[:hidden_unless]) : options[:hidden_unless]
|
77
|
-
|
78
|
-
options[:highlights_on] = [options[:highlights_on]] if options[:highlights_on].kind_of?(Hash) || options[:highlights_on].kind_of?(String)
|
79
|
-
@highlights_on = options[:highlights_on] || []
|
80
|
-
|
81
|
-
if link?
|
82
|
-
if @link.is_a?(Proc)
|
83
|
-
@highlights_on << template.instance_eval(&@link)
|
84
|
-
else
|
85
|
-
@highlights_on << @link if link?
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
def link?
|
91
|
-
@link && !@link.blank?
|
92
|
-
end
|
93
|
-
|
94
|
-
def disabled?
|
95
|
-
@disabled_conditions.call
|
96
|
-
end
|
97
|
-
|
98
|
-
def hidden?
|
99
|
-
!@visible
|
100
|
-
end
|
101
|
-
|
102
|
-
def highlighted?(path, params = {}, template = nil)
|
103
|
-
params = clean_unwanted_keys(params)
|
104
|
-
result = false
|
105
|
-
|
106
|
-
@highlights_on.each do |highlight|
|
107
|
-
highlighted = true
|
108
|
-
|
109
|
-
case highlight
|
110
|
-
when String
|
111
|
-
highlighted &= path == highlight
|
112
|
-
when Proc
|
113
|
-
h = template.instance_eval(&highlight)
|
114
|
-
raise 'proc highlighting rules must evaluate to TrueClass or FalseClass' unless (h.is_a?(TrueClass) || h.is_a?(FalseClass))
|
115
|
-
highlighted &= h
|
116
|
-
when Regexp
|
117
|
-
highlighted &= path.match(highlight)
|
118
|
-
when Hash
|
119
|
-
h = clean_unwanted_keys(highlight)
|
120
|
-
h.each_key do |key|
|
121
|
-
h_key = h[key].to_s.dup
|
122
|
-
h_key.gsub!(/^\//, '') if key == :controller
|
123
|
-
highlighted &= h_key == params[key].to_s
|
124
|
-
end
|
125
|
-
else
|
126
|
-
raise 'highlighting rules should be a String, Proc, Regexp or a Hash'
|
127
|
-
end
|
128
|
-
|
129
|
-
result |= highlighted
|
130
|
-
end
|
131
|
-
|
132
|
-
return result
|
133
|
-
end
|
134
|
-
|
135
|
-
private
|
136
|
-
|
137
|
-
# removes unwanted keys from a Hash and returns a new hash
|
138
|
-
def clean_unwanted_keys(hash)
|
139
|
-
ignored_keys = [:only_path, :use_route]
|
140
|
-
hash.dup.delete_if { |key, value| ignored_keys.include?(key) }
|
141
|
-
end
|
142
|
-
|
143
|
-
end
|
144
|
-
|
145
|
-
end
|
146
|
-
|
147
|
-
ActionController::Base.helper Navigasmic::SemanticNavigationHelper
|
4
|
+
require 'navigasmic/core/builders'
|
5
|
+
require 'navigasmic/core/configuration'
|
6
|
+
require 'navigasmic/core/item'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Navigasmic::Builder
|
2
|
+
class CrumbBuilder < Base
|
3
|
+
class Configuration < Base::Configuration
|
4
|
+
end
|
5
|
+
|
6
|
+
def initialize(context, name, options, &block)
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def render
|
11
|
+
end
|
12
|
+
|
13
|
+
def group(label = nil, options = {}, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def item(label, *args, &block)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Navigasmic::Builder
|
2
|
+
class ListBuilder < Base
|
3
|
+
class Configuration < Base::Configuration
|
4
|
+
|
5
|
+
attr_accessor :wrapper_class, :has_nested_class, :is_nested_class, :disabled_class, :highlighted_class
|
6
|
+
attr_accessor :wrapper_tag, :group_tag, :item_tag
|
7
|
+
attr_accessor :link_generator, :label_generator
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
# which keys (for other builder) should be removed from options
|
11
|
+
@excluded_keys = [:map]
|
12
|
+
|
13
|
+
# tag configurations
|
14
|
+
@wrapper_tag = :ul
|
15
|
+
@group_tag = :ul
|
16
|
+
@item_tag = :li
|
17
|
+
|
18
|
+
# class configurations
|
19
|
+
@wrapper_class = 'semantic-navigation'
|
20
|
+
@has_nested_class = 'has-nested'
|
21
|
+
@is_nested_class = 'is-nested'
|
22
|
+
@disabled_class = 'disabled'
|
23
|
+
@highlighted_class = 'active'
|
24
|
+
|
25
|
+
# generator callbacks
|
26
|
+
@link_generator = proc{ |label, link, options, is_nested| link_to(label, link, options.delete(:link_html)) }
|
27
|
+
@label_generator = proc{ |label, is_linked, is_nested| "<span>#{label}</span>" }
|
28
|
+
|
29
|
+
super
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(context, name, options, &block)
|
34
|
+
super
|
35
|
+
@options[:id] ||= name.to_s.underscore unless @options.has_key?(:id)
|
36
|
+
@options[:class] = merge_classes!(@options, @config.wrapper_class)
|
37
|
+
end
|
38
|
+
|
39
|
+
def render
|
40
|
+
content_tag(@config.wrapper_tag, capture(&@definition), @options)
|
41
|
+
end
|
42
|
+
|
43
|
+
def group(label = nil, options = {}, &block)
|
44
|
+
raise ArgumentError, "Missing block for group" unless block_given?
|
45
|
+
return '' unless visible?(options)
|
46
|
+
|
47
|
+
concat(structure_for(label, false, options, &block))
|
48
|
+
end
|
49
|
+
|
50
|
+
def item(label, *args, &block)
|
51
|
+
options = args.extract_options!
|
52
|
+
options = flatten_and_eval_options(options)
|
53
|
+
return '' unless visible?(options)
|
54
|
+
|
55
|
+
item = Navigasmic::Item.new(self, label, extract_and_determine_link(label, options, *args), options)
|
56
|
+
|
57
|
+
merge_classes!(options, @config.disabled_class) if item.disabled?
|
58
|
+
merge_classes!(options, @config.highlighted_class) if item.highlights_on?(@context.request.path, @context.params)
|
59
|
+
|
60
|
+
concat(structure_for(label, item.link? ? item.link : false, options, &block))
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def structure_for(label, link = false, options = {}, &block)
|
66
|
+
label = label_for(label, link, block_given?, options)
|
67
|
+
|
68
|
+
content = ''
|
69
|
+
if block_given?
|
70
|
+
merge_classes!(options, @config.has_nested_class)
|
71
|
+
content = content_tag(@config.group_tag, capture(&block), {class: @config.is_nested_class})
|
72
|
+
end
|
73
|
+
|
74
|
+
content_tag(@config.item_tag, "#{label}#{content}".html_safe, options)
|
75
|
+
end
|
76
|
+
|
77
|
+
def label_for(label, link, is_nested = false, options = {})
|
78
|
+
if label.present?
|
79
|
+
label = @context.instance_exec(label, !!link, is_nested, &@config.label_generator).html_safe
|
80
|
+
end
|
81
|
+
label = @context.instance_exec(label, link, options.delete(:link_html) || {}, is_nested, &@config.link_generator).html_safe if link
|
82
|
+
label
|
83
|
+
end
|
84
|
+
|
85
|
+
def merge_classes!(hash, classname)
|
86
|
+
hash[:class] = (hash[:class] ? "#{hash[:class]} " : '') << classname
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|