facades 0.1.0 → 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.
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