facades 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. data/.gitignore +1 -0
  2. data/.rbenv-gemsets +1 -0
  3. data/.rvmrc +1 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +12 -0
  6. data/Guardfile +19 -0
  7. data/README.md +115 -101
  8. data/Rakefile +8 -0
  9. data/app/assets/javascripts/facades/debug/grid.js +0 -0
  10. data/app/helpers/facades_helper.rb +1 -0
  11. data/config.ru +7 -0
  12. data/facades.gemspec +9 -2
  13. data/lib/facades/helpers/layout.rb +36 -73
  14. data/lib/facades/helpers/navigation.rb +182 -110
  15. data/lib/facades/helpers/{elements.rb → notifications.rb} +9 -36
  16. data/lib/facades/helpers.rb +6 -17
  17. data/lib/facades/patterns/tabs.rb +75 -0
  18. data/lib/facades/patterns.rb +7 -0
  19. data/lib/facades/{sass_ext → sass_extensions}/color.rb +5 -13
  20. data/lib/facades/sass_extensions/conversions.rb +27 -0
  21. data/lib/facades/sass_extensions/functions.rb +84 -0
  22. data/lib/facades/sass_extensions/icons.rb +66 -0
  23. data/lib/facades/sass_extensions.rb +21 -0
  24. data/lib/facades/support/compass/project/MIT-LICENSE.txt +20 -0
  25. data/lib/facades/support/compass/project/humans.txt +8 -0
  26. data/lib/facades/support/compass/project/index.html +45 -0
  27. data/lib/facades/support/compass/project/manifest.rb +18 -0
  28. data/lib/facades/support/compass/project/robots.txt +4 -0
  29. data/lib/facades/support/compass.rb +9 -0
  30. data/lib/facades/support/rails.rb +12 -15
  31. data/lib/facades/support/simple_form.rb +32 -0
  32. data/lib/facades/version.rb +1 -1
  33. data/lib/facades.rb +21 -44
  34. data/spec/internal/app/helpers/application_helper.rb +3 -0
  35. data/spec/internal/app/views/navigation/_multi_list.html.erb +11 -0
  36. data/spec/internal/app/views/navigation/_multi_option_list.html.erb +14 -0
  37. data/spec/internal/app/views/navigation/_single_list.html.erb +9 -0
  38. data/spec/internal/config/database.yml +3 -0
  39. data/spec/internal/config/routes.rb +3 -0
  40. data/spec/internal/db/schema.rb +3 -0
  41. data/spec/internal/log/.gitignore +1 -0
  42. data/spec/internal/public/favicon.ico +0 -0
  43. data/spec/spec_helper.rb +16 -6
  44. data/spec/unit/helpers/layout_spec.rb +4 -0
  45. data/spec/unit/helpers/navigation_spec.rb +384 -0
  46. data/spec/unit/helpers/notifications_spec.rb +4 -0
  47. data/spec/unit/patterns/tabs_spec.rb +58 -0
  48. data/src/icons/facades.yml +105 -0
  49. data/src/icons/font-awesome.yml +210 -0
  50. data/src/scss/facades/_buttons.scss +10 -0
  51. data/src/scss/facades/_config.scss +99 -0
  52. data/src/scss/facades/_debug.scss +8 -0
  53. data/src/scss/facades/_forms.scss +228 -0
  54. data/src/scss/facades/_global.scss +104 -0
  55. data/src/scss/facades/_icons.scss +61 -0
  56. data/src/scss/facades/_mixins.scss +115 -0
  57. data/src/scss/facades/_mobile.scss +3 -0
  58. data/src/scss/facades/_setup.scss +191 -0
  59. data/src/scss/facades/_typography.scss +220 -0
  60. data/src/scss/facades/buttons/_glossy.scss +29 -0
  61. data/src/scss/facades/buttons/_gradient.scss +36 -0
  62. data/src/scss/facades/buttons/_shared.scss +33 -0
  63. data/src/scss/facades/buttons/_simple.scss +28 -0
  64. data/src/scss/facades/icons/_classes.scss +37 -0
  65. data/src/scss/facades/icons/_legacy.scss +27 -0
  66. data/src/scss/facades/layout/_lists.scss +43 -0
  67. data/src/scss/facades/mixins/_gradients.scss +30 -0
  68. data/src/scss/facades/mixins/_rhythm.scss +37 -0
  69. data/src/scss/facades/mobile/_buttons.scss +97 -0
  70. data/src/scss/facades/mobile/_config.scss +30 -0
  71. data/src/scss/facades/mobile/_global.scss +81 -0
  72. data/src/scss/facades/mobile/_mixins.scss +49 -0
  73. data/src/scss/facades/mobile/_setup.scss +50 -0
  74. data/src/scss/facades/mobile/patterns/_navbar.scss +21 -0
  75. data/src/scss/facades/mobile/patterns/_panel.scss +37 -0
  76. data/src/scss/facades/mobile/patterns/_stage.scss +20 -0
  77. data/src/scss/facades/mobile/patterns/_toolbar.scss +25 -0
  78. data/src/scss/facades/mobile/themes/_apple.scss +17 -0
  79. data/src/scss/facades/patterns/_labels.scss +50 -0
  80. data/src/scss/facades/patterns/_navbar.scss +4 -0
  81. data/src/scss/facades/patterns/_notifications.scss +82 -0
  82. data/src/scss/facades/patterns/_pagination.scss +4 -0
  83. data/src/scss/facades/patterns/_pills.scss +50 -0
  84. data/src/scss/facades/patterns/_tabs.scss +83 -0
  85. data/src/scss/facades/patterns/_twipsy.scss +84 -0
  86. data/src/scss/facades/typography/_tables.scss +95 -0
  87. metadata +201 -58
  88. data/app/views/facades/_pagination.html.erb +0 -20
  89. data/lib/facades/builders/form/base.rb +0 -212
  90. data/lib/facades/builders/form/elements.rb +0 -112
  91. data/lib/facades/builders/form/helper.rb +0 -29
  92. data/lib/facades/builders/form.rb +0 -22
  93. data/lib/facades/builders/sprite.rb +0 -50
  94. data/lib/facades/builders/table.rb +0 -76
  95. data/lib/facades/debug/html.rb +0 -6
  96. data/lib/facades/helpers/builders.rb +0 -24
  97. data/lib/facades/helpers/mobile.rb +0 -57
  98. data/lib/facades/helpers/pagination.rb +0 -83
  99. data/lib/facades/helpers/utility.rb +0 -31
  100. data/lib/facades/sass_ext/form_elements.rb +0 -52
  101. data/lib/facades/sass_ext/funcs.rb +0 -33
  102. data/lib/facades/sass_ext.rb +0 -14
  103. data/lib/facades/stylesheets/facades/_common.scss +0 -7
  104. data/lib/facades/stylesheets/facades/_css3.scss +0 -93
  105. data/lib/facades/stylesheets/facades/_layout.scss +0 -5
  106. data/lib/facades/stylesheets/facades/_normalize.scss +0 -5
  107. data/lib/facades/stylesheets/facades/_setup.scss +0 -104
  108. data/lib/facades/stylesheets/facades/_typography.scss +0 -2
  109. data/lib/facades/stylesheets/facades/_ui.scss +0 -3
  110. data/lib/facades/stylesheets/facades/_utilities.scss +0 -32
  111. data/lib/facades/stylesheets/facades/layout/_dropdown-list.scss +0 -7
  112. data/lib/facades/stylesheets/facades/layout/_forms.scss +0 -53
  113. data/lib/facades/stylesheets/facades/layout/_grid.scss +0 -49
  114. data/lib/facades/stylesheets/facades/layout/_responsive_grid.scss +0 -164
  115. data/lib/facades/stylesheets/facades/setup/_forms.scss +0 -284
  116. data/lib/facades/stylesheets/facades/setup/_ie.scss +0 -12
  117. data/lib/facades/stylesheets/facades/setup/_reset.scss +0 -255
  118. data/lib/facades/stylesheets/facades/typography/_baseline.scss +0 -91
  119. data/lib/facades/stylesheets/facades/typography/_lists.scss +0 -34
  120. data/lib/facades/stylesheets/facades/typography/_shadow.scss +0 -8
  121. data/lib/facades/stylesheets/facades/ui/_buttons.scss +0 -34
  122. data/lib/facades/stylesheets/facades/ui/_flash-messages.scss +0 -29
  123. data/lib/facades/stylesheets/facades/ui/_tabbed.scss +0 -5
  124. data/lib/facades/stylesheets/facades/ui/_tool-tip.scss +0 -44
  125. data/lib/facades/stylesheets/facades/utilities/_clearfix.scss +0 -20
  126. data/lib/facades/stylesheets/facades/utilities/_color.scss +0 -7
  127. data/lib/facades/stylesheets/facades/utilities/_cursors.scss +0 -4
  128. data/lib/facades/support/serve.rb +0 -17
  129. data/lib/facades/support/tipsy.rb +0 -17
  130. data/spec/facades/helpers/elements_spec.rb +0 -86
  131. data/spec/facades/helpers/layout_helpers_spec.rb +0 -5
  132. data/spec/facades/helpers/navigation_spec.rb +0 -107
@@ -1,136 +1,208 @@
1
1
  module Facades
2
2
  module Helpers
3
- ##
4
- #
5
- # Convenience helpers for building navigation lists, and defining 'on' states.
6
- #
7
3
  module Navigation
8
4
 
9
5
  ##
6
+ # Constructs a navigation list containing
7
+ # a variable number of list items and links.
10
8
  #
11
- # Creates a link wrapped in a list item, to be used within a list-based navigation.
12
- #
13
- # @param [String] text The text used within the link
14
- # @param [String] path The url used as the link's +href+ attribute
15
- # @param [Hash] attrs Hash of attributes to be applied to the link. This format is the same as Rail's +link_to+ helper
16
- # @option attrs [String] :active_class The class to use if this link is 'active'. Defaults to "on"
17
- # @option attrs [Proc] :proc A callback which, when called, determines the active state of the link
18
- # @option attrs [Regex] :matcher A regular expression to be matched against +path+
19
- # @param [Symbol] wrapper The html tag to be used as the wrapper. Defaults to +:li+
20
- #
21
- # @example Create a list item link to any page
22
- # nav_link('Home Page', '/home') #=> <li><a href="/home">Home Page</a>
23
- #
24
- # @example 'Active state' functionality for the current page
25
- # nav_link('Current Page', '/current_url') #=> <li class="on"><a href="/current_url" class="on">Current Page</a></li>
26
- #
27
- def nav_link(text, path, attrs = {}, wrapper = :li, &block)
28
-
29
- if block_given?
30
- return sub_nav_link(text, path, attrs, wrapper, :ol, &block)
31
- end
32
-
33
- link_attrs = update_link_attrs(path, attrs)
34
- wrapper_attrs = link_attrs.delete(:wrapper)
35
- child_link = link_to(text, path, link_attrs)
36
- built = (wrapper === false ? child_link : content_tag(wrapper, child_link, wrapper_attrs))
37
- built = built.html_safe if built.respond_to?(:html_safe)
38
- built
9
+ def nav(options = {}, &block)
10
+ Navigator.new(self, options).render(&block)
39
11
  end
40
- alias :nav_link_to :nav_link
41
12
 
42
- def sub_nav_link(text, path, attrs = {}, wrapper = :li, container = :ol, &block)
43
- wrapper_attrs = attrs.delete(:wrapper)
44
- link_attrs = update_link_attrs(path, attrs.merge(:wrapper => (attrs.delete(:item) || {}) ))
45
- parent_link = nav_link_to(text, path, attrs, false)
46
- child_links = content_tag(container, capture(&block), wrapper_attrs)
47
- content_tag(wrapper, (parent_link << child_links), wrapper_attrs)
48
- end
49
- private :sub_nav_link
13
+ alias :navigation :nav
50
14
 
51
15
  ##
16
+ # Similar to link_to, but adds the class 'active' if the link's href is in an active state.
17
+ # If the options :proc, or :matcher is passed, they are used to determine active state. If not the current
18
+ # request.path is used.
52
19
  #
53
- # Creates a navigational list format, including a parent list / wrapper. Useful for nested list navigation
54
- # @param [String] text The text used within the link
55
- # @param [String] path The url used as the link's +href+ attribute
56
- # @param [Hash] attrs Hash of attributes to be applied to the link. This format is the same as Rail's +link_to+ helper
57
- # @option attrs [String] :active_class The class to use if this link is 'active'. Defaults to "on"
58
- # @option attrs [Proc] :proc A callback which, when called, determines the active state of the link
59
- # @option attrs [Regex] :matcher A regular expression to be matched against +path+
60
- # @param [Symbol] wrapper The html tag to be used as the wrapper. Defaults to +:li+
61
- # @param [Symbol] container The element that will be used as a container for the nested list
62
- # @param [Block] &block A block containing the content of the nested items
63
- #
64
- # @example Create a nested list navigation
65
- # nav do
66
- # nav_link('About Page', '/about')
67
- # end
68
- # @example
69
- # <ol>
70
- # <li><a href="/home">Home Page</a>
71
- # <ol>
72
- # <li><a href="/about">Sub Page</a></li>
73
- # </ol>
74
- # </li>
75
- # </ol>
76
- #
77
- def nav(container = :ol, html_attrs = {}, heading = nil, &block)
78
-
79
- wrapper_attrs = html_attrs.delete(:wrapper) || {}
80
-
81
- built = if Facades.enable_html5
82
- inner = content_tag(container, capture(&block), wrapper_attrs)
83
- inner = (content_tag(:h3, heading) << inner) unless heading.nil?
84
- content_tag(:nav, html_attrs) do
85
- inner
86
- end
87
- else
88
- content_tag(container, capture(&block), html_attrs)
20
+ def nav_link(text, href, options = {})
21
+ options.merge!(:path => request.path)
22
+ wrapper = options.delete(:wrapper)
23
+ link = NavigationLink.new(text, href, options)
24
+ current = link.active?
25
+ link.options = Navigator.merge_html_classes('active', link.options) if current
26
+
27
+ if wrapper
28
+ if wrapper.is_a?(Hash)
29
+ wrap_attrs = wrapper
30
+ wrapper = wrap_attrs.delete(:tag) || :li
31
+ else
32
+ wrap_attrs = {}
33
+ end
34
+ wrap_attrs = Navigator.merge_html_classes('active', wrap_attrs) if current
35
+ return content_tag(wrapper, link_to(link.text, link.href, link.options), wrap_attrs)
89
36
  end
90
- built = built.html_safe if built.respond_to?(:html_safe)
91
- built
92
37
 
38
+ link_to(link.text, link.href, link.options)
93
39
  end
94
40
 
95
- private
96
-
97
- # @private
98
- def update_link_attrs(path, attrs)
41
+ class Navigator
42
+ attr_reader :view, :path
43
+ attr_accessor :options, :nested, :links
99
44
 
100
- proc = attrs.delete(:proc) || false
101
- regex = attrs.delete(:matcher) || false
102
- klasses = attrs.delete(:class).try(:split, ' ')
103
- on_class = attrs.delete(:active_class) || "on"
104
- wrapper_attrs = attrs.delete(:wrapper) || {}
105
- wklasses = wrapper_attrs[:class].try(:split, ' ')
45
+ def initialize(tpl, options = {}, nested = false)
46
+ @view, @options, @nested, @links = tpl, options, nested, []
47
+ @path = view.request.path
48
+ end
106
49
 
107
- klasses ||= []
108
- wklasses ||= []
50
+ delegate :content_tag, :concat, :link_to, :to => :view
109
51
 
110
- matcher = (proc || regex || request.path.to_s)
111
- cpath = request.path.to_s.sub("/","")
112
- lpath = path.to_s.sub("/","")
52
+ ##
53
+ # Renders the resulting html list, wrapped in a <nav> tag.
54
+ #
55
+ def render(&block)
56
+ wrap_attrs = options.delete(:wrapper) || :ul
57
+ heading = options.delete(:heading)
58
+
59
+ unless wrap_attrs.is_a?(Hash)
60
+ wrapper = wrap_attrs
61
+ wrap_attrs = {}
62
+ else
63
+ wrapper = wrap_attrs.delete(:tag) || :ul
64
+ end
65
+
66
+ @wrapper_attrs = wrap_attrs
67
+ @wrapper = wrapper
68
+
69
+ output = content_tag(wrapper, view.capture(self, &block), options)
70
+ return output if nested?
71
+
72
+ if heading
73
+ heading = generate_heading(heading)
74
+ output = heading << output
75
+ end
76
+ content_tag(:nav, output, wrap_attrs)
77
+
78
+ end
113
79
 
114
- active = case matcher
115
- when Proc then proc.call(path)
116
- when Regexp then request.path.match(regex)
117
- when String then (cpath == lpath || cpath.match(/#{lpath}\/\w/i))
118
- else raise 'Proc, Regexp or String required... passed #{matcher.class}.'
80
+ ##
81
+ # Constructs a link wrapped in a list item for use
82
+ # within a navigation list.
83
+ #
84
+ def link(text, href, link_opts = {}, &block)
85
+
86
+ wrap_attrs = link_opts.delete(:wrapper) || {}
87
+ link_opts.merge!(:path => path)
88
+ link = NavigationLink.new(text, href, link_opts)
89
+ links << link
90
+
91
+ if link.active?
92
+ wrap_attrs = merge_html_classes("active", wrap_attrs)
93
+ link.options = merge_html_classes("active", link.options)
94
+ end
95
+
96
+ if block_given?
97
+ subnav = Navigator.new(view, wrap_attrs, true)
98
+ inner = subnav.render(&block)
99
+ unless subnav.links.empty?
100
+ output = link_to(link.text, link.href, link.options) << inner
101
+ content_tag(:li, output, wrap_attrs)
102
+ else
103
+ content_tag(:li, link_to(link.text, link.href, link.options), wrap_attrs)
104
+ end
105
+ else
106
+ content_tag(:li, link_to(link.text, link.href, link.options), wrap_attrs)
107
+ end
119
108
  end
120
109
 
121
- if active === true
122
- klasses << on_class
123
- wklasses << on_class
110
+ class << self
111
+
112
+ ##
113
+ # Takes an options array and adds any additional
114
+ # classes passed to args. If a :class key exists, it
115
+ # is updated. If not, it is added unless the result is
116
+ # an empty string.
117
+ #
118
+ def merge_html_classes(*args)
119
+ opts = args.extract_options!
120
+ klasses = (opts.delete(:class) || "").split(" ")
121
+ klasses = [klasses, args].flatten.compact.reject{ |c| c.to_s.blank? }.join(" ")
122
+ (klasses.blank? ? opts : opts.merge(:class => klasses))
123
+ end
124
+
124
125
  end
126
+
127
+ private
125
128
 
126
- attrs.merge!(:class => klasses.join(" ")) unless klasses.compact.empty?
127
- wrapper_attrs.merge!(:class => wklasses.join(" ")) unless wklasses.compact.empty?
129
+ ##
130
+ # To be valid, a <nav> should have a heading of some sort.
131
+ # When passed via options, this generates the proper tag
132
+ #
133
+ def generate_heading(opts)
134
+ if opts.is_a?(Hash)
135
+ heading_tag = opts.delete(:tag)
136
+ heading_text = opts.delete(:text)
137
+ else
138
+ heading_text = opts
139
+ end
140
+ heading_tag ||= :h3
141
+ content_tag(heading_tag, heading_text)
142
+ end
143
+
144
+ def merge_html_classes(*args) #:nodoc:
145
+ Navigator.merge_html_classes(*args)
146
+ end
147
+
148
+ ##
149
+ # Determines if the current navigation set
150
+ # is nested within another.
151
+ #
152
+ def nested?
153
+ @nested == true
154
+ end
128
155
 
129
- attrs.merge!(:wrapper => wrapper_attrs)
130
- attrs
131
156
  end
132
-
133
- end
157
+
158
+ class NavigationLink
159
+ attr_accessor :href, :text, :options
160
+ attr_reader :matcher
161
+
162
+ def initialize(text, href, options)
163
+ @href, @text, @options = href, text, options
164
+ @matcher = (options.delete(:proc) || options.delete(:matcher))
165
+ curr_path = options.delete(:path)
166
+ @matcher ||= curr_path
167
+ end
168
+
169
+ ##
170
+ # Checks the link's href against either a proc,
171
+ # regexp, or current request.path depending on
172
+ # the options provided. Returns true if there is
173
+ # a match, false if not.
174
+ #
175
+ def active?
176
+ return matcher.call(href) if matcher.is_a?(Proc)
177
+ return ( (href =~ matcher).to_i >= 1 ) if matcher.is_a?(Regexp)
178
+
179
+ match_path = normalize_path(matcher)
180
+ href_path = normalize_path(href)
181
+
182
+ return false if href_path.blank? && !match_path.blank?
183
+
184
+ if key = options.delete(:match)
185
+ path_matcher = case key.to_s
186
+ when 'exact' then match_path.match(%r{^/?#{href_path}/?$}i)
187
+ when 'after' then match_path.match(%r{/?#{href_path}/?(.*)$}i)
188
+ when 'before' then match_path.match(%r{#{href_path}/?$}i)
189
+ end
190
+ else
191
+ path_matcher = match_path.match(/#{href_path}\/.*/i)
192
+ end
193
+ !!(match_path == href_path || path_matcher)
194
+ end
195
+
196
+ private
197
+
198
+ def normalize_path(path)
199
+ path.split("/").reject{ |part| part.blank? }.compact.join("/")
200
+ end
201
+
202
+ end
203
+
204
+ end # Navigation
134
205
 
135
- end
136
- end
206
+ end # Helpers
207
+
208
+ end # Facades
@@ -1,34 +1,6 @@
1
1
  module Facades
2
2
  module Helpers
3
- ##
4
- #
5
- # Generates misc html elements that aren't included in Rails core, or are custom.
6
- #
7
- module Elements
8
-
9
- ##
10
- # Generates a "button" link tag. Simply a convenience method to skip adding 'class="button"' and also adds an +icon+ option
11
- # @see Motr::Forms::Builder#button For form related buttons
12
- #
13
- # @param [String] txt The link text
14
- # @param [String] path The link href
15
- # @param [Types] Name Description
16
- #
17
- # @example Create a plain link.button
18
- # button_link('Blog', '/blog') #=> <a href="/blog" class="button">Blog</a>
19
- # @example Create a link.button with icon
20
- # button_link('Blog', '/blog', :icon => 'blog_image.png') #=> <a href="/blog" class="button"><img src="/images/blog_image.png" alt="Blog" /> Blog</a>
21
-
22
- def button_link(txt, path, attrs = {}, incl_span = false)
23
- image = attrs.delete(:icon)
24
- klasses = (attrs.delete(:class) || "").split(" ")
25
- klasses << 'button'
26
- klasses = klasses.uniq.compact
27
- content = ""
28
- content << image_tag(image) unless image.nil?
29
- content << (incl_span ? "<span>#{txt}</span>" : txt)
30
- link_to content.html_safe, path, attrs.merge(:class => klasses.join(" "))
31
- end
3
+ module Notifications
32
4
 
33
5
  ##
34
6
  #
@@ -50,29 +22,30 @@ module Facades
50
22
  #
51
23
  #
52
24
  def flash_messages(attrs = {})
53
-
25
+
54
26
  return if flash.nil? or flash.empty?
55
-
27
+
56
28
  wrapper = attrs.delete(:wrapper) || :div
57
29
  closer = attrs.delete(:closer)
58
30
  unless closer === false
59
- closer ||= "<span>X</span>"
31
+ closer ||= "<span class='close'>x</span>"
60
32
  end
61
33
  klasses = (attrs.delete(:class) || "").split(" ")
62
34
  klasses << "flash-message"
63
35
  content = ""
64
-
36
+
65
37
  flash.each do |key, value|
38
+ next if value === true or value.to_s == 'true' # fix awkward devise message
39
+ klasses << "notification"
66
40
  klasses << "flash-message-#{key.to_s.underscore}"
67
41
  msg_attrs = attrs.merge(:class => [key.to_s, klasses].flatten.join(' '))
68
42
  content.concat content_tag(wrapper, "#{value} #{closer}".html_safe, msg_attrs).html_safe
69
43
  end
70
-
44
+
71
45
  content.html_safe
72
-
46
+
73
47
  end
74
48
 
75
49
  end
76
-
77
50
  end
78
51
  end
@@ -1,23 +1,12 @@
1
+ require 'action_view'
1
2
  require 'facades/helpers/layout'
2
3
  require 'facades/helpers/navigation'
3
- require 'facades/helpers/elements'
4
- require 'facades/helpers/pagination'
5
- require 'facades/helpers/utility'
6
- require 'facades/helpers/builders'
7
- require 'facades/helpers/mobile'
4
+ require 'facades/helpers/notifications'
8
5
 
9
6
  module Facades
10
- module Helpers
11
- extend ActiveSupport::Concern
12
-
13
- included do
14
- include Facades::Helpers::Layout
15
- include Facades::Helpers::Navigation
16
- include Facades::Helpers::Elements
17
- include Facades::Helpers::Utility
18
- include Facades::Helpers::Builders
19
- include Facades::Helpers::Mobile
20
- end
21
-
7
+ module Helpers
8
+ include Facades::Helpers::Layout
9
+ include Facades::Helpers::Navigation
10
+ include Facades::Helpers::Notifications
22
11
  end
23
12
  end
@@ -0,0 +1,75 @@
1
+ module Facades
2
+ module Patterns
3
+ ##
4
+ # Generates a tabbed container including
5
+ # a navigation as well as the tab's "panes"
6
+ #
7
+ module Tabs
8
+
9
+ def tabbed(options = {}, &block)
10
+ TabBuilder.new(self, options).render(&block)
11
+ end
12
+
13
+ class TabBuilder
14
+ attr_reader :view
15
+ attr_accessor :options, :tabs
16
+
17
+ def initialize(tpl, options = {})
18
+ @view, @options, @tabs = tpl, options, []
19
+ end
20
+
21
+ delegate :content_tag, :concat, :link_to, :capture, :to => :view
22
+
23
+ ##
24
+ # Renders the resulting tab area
25
+ # including a list navigation.
26
+ #
27
+ def render(&block)
28
+ klasses = options.delete(:class) || ""
29
+ options.merge!(:class => klasses.split(" ").push("tabbed").join(" "))
30
+ rendered = view.capture(self, &block)
31
+ output = content_tag(:ul, { :class =>'tab-navigation' }) do
32
+ tabs.each_with_index do |tab, ind|
33
+ link_opts = ( ind == 0 ? { :class => 'active' } : {} )
34
+ concat content_tag(:li, link_to(tab.title, "##{tab.tab_id}"), link_opts)
35
+ end
36
+ end
37
+ output << rendered
38
+ concat content_tag(:div, output, options)
39
+ end
40
+
41
+ ##
42
+ # Adds a new panel to the tabbed area.
43
+ # @param [String] title The text to be used in the navigation link.
44
+ # @param [Hash] options A hash of html attributes to be added to the tab panel.
45
+ #
46
+ def panel(title, options = {}, &block)
47
+ panel = TabPanel.new(title, options)
48
+ tabs << panel
49
+ concat content_tag(:section, capture(&block), panel.options)
50
+ end
51
+
52
+ end
53
+
54
+ class TabPanel
55
+ attr_accessor :options, :title
56
+
57
+ def initialize(title, options = {})
58
+ @title, @options = title, options
59
+ @options.merge!(:id => tab_id)
60
+ klasses = @options.delete(:class) || ""
61
+ @options.merge!(:class => klasses.split(" ").push("tab").join(" "))
62
+ end
63
+
64
+ def tab_id
65
+ return options[:id] if options[:id]
66
+ value = title.mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/n, '').to_s
67
+ value.gsub(/[']+/, '').gsub(/\W+/, ' ').strip.downcase.gsub(" ", "_")
68
+ end
69
+
70
+ end
71
+
72
+
73
+ end # Tabs
74
+ end # Patterns
75
+ end # Facades
@@ -0,0 +1,7 @@
1
+ require 'facades/patterns/tabs'
2
+
3
+ module Facades
4
+ module Patterns
5
+ include Facades::Patterns::Tabs
6
+ end
7
+ end
@@ -1,5 +1,5 @@
1
1
  module Facades
2
- module SassExt
2
+ module SassExtensions
3
3
  module Color
4
4
 
5
5
  # Check the luminance of color. This differs from lightness as it returns the actual values as 'light' and 'dark'
@@ -8,7 +8,7 @@ module Facades
8
8
  result = ((color.red * 299) + (color.green * 587) + (color.blue * 114) / 1000)
9
9
  Sass::Script::String.new( result >= 160 ? 'light' : 'dark')
10
10
  end
11
-
11
+
12
12
  # Tint a color by mixing it with white
13
13
  def tint(color, dilution = Sass::Script::Number.new(50))
14
14
  assert_type color, :Color
@@ -25,14 +25,6 @@ module Facades
25
25
  mix(color, black, Sass::Script::Number.new(100 - dilution.value))
26
26
  end
27
27
 
28
- # Converts a rgba to hex string, via compass ie_hex_str
29
- def rgba_to_hex(color)
30
- assert_type color, :Color
31
- alpha = (color.alpha * 255).round
32
- alphastr = alpha.to_s(16).rjust(2, '0')
33
- Sass::Script::String.new("##{alphastr}#{color.send(:hex_str)[1..-1]}".upcase)
34
- end
35
-
36
- end
37
- end
38
- end
28
+ end # Color
29
+ end # SassExtensions
30
+ end # Facades
@@ -0,0 +1,27 @@
1
+ ##
2
+ # Extensions to sass's unit conversion and manipulation
3
+ # functionality.
4
+ #
5
+ module Facades
6
+ module SassExtensions
7
+ module Conversions
8
+
9
+ ##
10
+ # Removes any unit values (px/em/rem etc)
11
+ # from a number leaving just the numeric
12
+ # representation.
13
+ #
14
+ # @example Use unitless line heights
15
+ # line-height:numeric(1em) #=> line-height:1
16
+ #
17
+ def numeric(value)
18
+ assert_type value, :Number
19
+ return value if value.unitless?
20
+ value = value.to_s.gsub(value.unit_str, '')
21
+ value = value.to_f.denominator > 1 ? value.to_f : value.to_i
22
+ Sass::Script::Number.new(value)
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,84 @@
1
+ ##
2
+ # Misc functions to assist development.
3
+ #
4
+ module Facades
5
+ module SassExtensions
6
+ module Functions
7
+
8
+ ##
9
+ # Compact via compass
10
+ # Compacts a sass list removing any nil or empty items.
11
+ # @see http://compass-style.org
12
+ #
13
+ def compact(*args)
14
+ sep = :comma
15
+ if args.size == 1 && args.first.is_a?(Sass::Script::List)
16
+ list = args.first
17
+ args = list.value
18
+ sep = list.separator
19
+ end
20
+ Sass::Script::List.new(args.reject{|a| !a.to_bool}, sep)
21
+ end
22
+
23
+
24
+ ##
25
+ # Creates a selector including all
26
+ # fields of a particular type. Helpful to
27
+ # target text-like inputs etc.
28
+ #
29
+ def input_types(*args)
30
+ Sass::Script::String.new(args.collect do |type|
31
+ send(:"#{type}_input_types")
32
+ end.flatten.compact.join(", "))
33
+ end
34
+
35
+ ##
36
+ # Takes a value or values and prepends them to an existing list.
37
+ #
38
+ def prepend(*args)
39
+ existing = args.first
40
+ unless args.first.is_a?(Sass::Script::List)
41
+ raise Sass::SyntaxError, "The first argument to 'unshift' must be a list"
42
+ end
43
+ existing = existing.value
44
+ args.each{ |arg| existing.unshift(arg) }
45
+ Sass::Script::List.new(args, :comma)
46
+ end
47
+
48
+
49
+ private
50
+
51
+ ##
52
+ # Returns all input types
53
+ #
54
+ def all_input_types
55
+ [boolean_input_types, button_input_types, text_input_types].flatten
56
+ end
57
+
58
+ ##
59
+ # Returns an array of boolean input types (radio/checkbox)
60
+ #
61
+ def boolean_input_types
62
+ ["input[type=radio]", "input[type=checkbox]"]
63
+ end
64
+
65
+ ##
66
+ # Returns an array of button style input types
67
+ #
68
+ def button_input_types
69
+ ["button", "input[type=button]", "input[type=submit]", "input[type=reset]"]
70
+ end
71
+
72
+ ##
73
+ # Returns an array of text style input types
74
+ #
75
+ def text_input_types
76
+ %w{email password text number search tel time url datetime date datetime-local week month}.collect do |type|
77
+ "input[type=#{type}]"
78
+ end
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+ end