storefront 0.2.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 (59) hide show
  1. data/Rakefile +76 -0
  2. data/init.rb +1 -0
  3. data/lib/storefront.rb +21 -0
  4. data/lib/storefront/dashboard.rb +184 -0
  5. data/lib/storefront/form.rb +65 -0
  6. data/lib/storefront/form/elements.rb +101 -0
  7. data/lib/storefront/form/errors.rb +57 -0
  8. data/lib/storefront/form/fields.rb +420 -0
  9. data/lib/storefront/form/hints.rb +18 -0
  10. data/lib/storefront/form/inputs.rb +254 -0
  11. data/lib/storefront/form/labels.rb +81 -0
  12. data/lib/storefront/form/model.rb +84 -0
  13. data/lib/storefront/helpers/attribute_helper.rb +60 -0
  14. data/lib/storefront/helpers/body_helper.rb +18 -0
  15. data/lib/storefront/helpers/browser_helper.rb +54 -0
  16. data/lib/storefront/helpers/cache_helper.rb +25 -0
  17. data/lib/storefront/helpers/collection_helper.rb +14 -0
  18. data/lib/storefront/helpers/component_helper.rb +35 -0
  19. data/lib/storefront/helpers/dashboard_helper.rb +37 -0
  20. data/lib/storefront/helpers/debug_helper.rb +11 -0
  21. data/lib/storefront/helpers/definition_list_helper.rb +29 -0
  22. data/lib/storefront/helpers/error_helper.rb +11 -0
  23. data/lib/storefront/helpers/flash_helper.rb +14 -0
  24. data/lib/storefront/helpers/form_helper.rb +8 -0
  25. data/lib/storefront/helpers/format_helper.rb +59 -0
  26. data/lib/storefront/helpers/head_helper.rb +229 -0
  27. data/lib/storefront/helpers/image_helper.rb +54 -0
  28. data/lib/storefront/helpers/list_helper.rb +47 -0
  29. data/lib/storefront/helpers/locale_helper.rb +175 -0
  30. data/lib/storefront/helpers/open_graph_helper.rb +5 -0
  31. data/lib/storefront/helpers/page_helper.rb +73 -0
  32. data/lib/storefront/helpers/presenter_helper.rb +5 -0
  33. data/lib/storefront/helpers/request_helper.rb +66 -0
  34. data/lib/storefront/helpers/semantic/location_helper.rb +18 -0
  35. data/lib/storefront/helpers/semantic/time_helper.rb +14 -0
  36. data/lib/storefront/helpers/sidebar_helper.rb +27 -0
  37. data/lib/storefront/helpers/system_helper.rb +18 -0
  38. data/lib/storefront/helpers/table_helper.rb +38 -0
  39. data/lib/storefront/helpers/time_helper.rb +20 -0
  40. data/lib/storefront/helpers/url_helper.rb +32 -0
  41. data/lib/storefront/helpers/user_helper.rb +15 -0
  42. data/lib/storefront/helpers/widget_helper.rb +10 -0
  43. data/lib/storefront/helpers/workflow_helper.rb +50 -0
  44. data/lib/storefront/microdata/address.rb +7 -0
  45. data/lib/storefront/microdata/event.rb +13 -0
  46. data/lib/storefront/microdata/geo.rb +7 -0
  47. data/lib/storefront/microdata/organization.rb +7 -0
  48. data/lib/storefront/microdata/person.rb +7 -0
  49. data/lib/storefront/microformat/event.rb +7 -0
  50. data/lib/storefront/microformat/person.rb +7 -0
  51. data/lib/storefront/railtie.rb +28 -0
  52. data/lib/storefront/table.rb +191 -0
  53. data/rails/init.rb +1 -0
  54. data/test/form_helper_test.rb +5 -0
  55. data/test/support/mock_controller.rb +15 -0
  56. data/test/support/mock_response.rb +14 -0
  57. data/test/support/models.rb +0 -0
  58. data/test/test_helper.rb +34 -0
  59. metadata +111 -0
@@ -0,0 +1,18 @@
1
+ module Storefront
2
+ module BodyHelper
3
+ def body_id(string)
4
+ @body_id = string
5
+ end
6
+
7
+ def body_class(string)
8
+ @body_class = string
9
+ end
10
+
11
+ def body_attributes(options = {})
12
+ options[:class] = @body_class if @body_class
13
+ options[:id] = @body_id if @body_id
14
+
15
+ options
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,54 @@
1
+ module Storefront
2
+ module BrowserHelper
3
+ # check the current browser (via user agent) for the following:
4
+ # :mozilla / :firefox
5
+ # :ie6
6
+ # :ie7
7
+ # :ie
8
+ # :iphone
9
+ # :safari
10
+ def browser_is? name
11
+ name = name.to_s.strip
12
+
13
+ return true if browser_name == name
14
+ return true if (name == 'mozilla' or name == "firefox") && browser_name == 'gecko'
15
+ return true if name == 'ie6' && browser_name.index('ie6')
16
+ return true if name == 'ie7' && browser_name.index('ie7')
17
+ return true if name == 'ie' && browser_name.index('ie')
18
+ return true if name == 'iphone' && browser_name == 'iphone'
19
+ return true if name == 'webkit' && browser_name == 'safari'
20
+ end
21
+
22
+ # find the current browser name
23
+ def browser_name
24
+ @browser_name ||= begin
25
+ ua = request.user_agent.to_s.downcase
26
+ if ua.index('msie') && !ua.index('opera') && !ua.index('webtv')
27
+ 'ie'+ua[ua.index('msie')+5].chr
28
+ elsif ua.index('gecko/')
29
+ 'gecko'
30
+ elsif ua.index('opera')
31
+ 'opera'
32
+ elsif ua.index('konqueror')
33
+ 'konqueror'
34
+ elsif ua.index('iphone')
35
+ 'iphone'
36
+ elsif ua.index('applewebkit/')
37
+ 'safari'
38
+ elsif ua.index('mozilla/')
39
+ 'gecko'
40
+ else
41
+ ""
42
+ end
43
+ end
44
+ end
45
+
46
+ def ip_address
47
+ request.env['REMOTE_ADDR']
48
+ end
49
+
50
+ def user_agent
51
+ request.user_agent
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,25 @@
1
+ module Storefront
2
+ module CacheHelper
3
+ def optional_cache(key, &block)
4
+ cache(key, &block) unless session[:disable_caching]
5
+ end
6
+
7
+ def conditional_cache(key, options = {}, &block)
8
+ condition = true
9
+ condition = false if options.has_key?(:if) && options[:if] != true
10
+ if condition
11
+ cache(key, &block)
12
+ else
13
+ haml_concat capture_haml(&block)
14
+ end
15
+ end
16
+
17
+ def set_cache_buster
18
+ if request.xhr?
19
+ response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate"
20
+ response.headers["Pragma"] = "no-cache"
21
+ response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT"
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,14 @@
1
+ module Storefront
2
+ module CollectionHelper
3
+ def collection_class(index, length)
4
+ length = length.length if length.is_a?(::Array)
5
+ if index == 0
6
+ "first"
7
+ elsif index == length - 1
8
+ "last"
9
+ else
10
+ nil
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,35 @@
1
+ module Storefront
2
+ # Encapsulates common browser hacks
3
+ module ComponentHelper
4
+ def component_image_tag
5
+ capture_haml do
6
+ haml_tag :span
7
+ haml_concat image_tag()
8
+ end
9
+ end
10
+
11
+ def popup_button(label, path, message, subtitle, submit = nil, kind = :group)
12
+ link_to "<span>#{label}</span>", path, :class => "delete", "data-message" => message, "data-subtitle" => subtitle, "data-model" => kind.to_s, "data-submit" => submit.to_s
13
+ end
14
+
15
+ def component_button(*args, &block)
16
+ options = args.extract_options!
17
+ button_options = options.delete(:button_options) || {}
18
+
19
+ if block_given?
20
+ content = capture(&block)
21
+ else
22
+ label = args.shift
23
+ path = args.shift
24
+ content = link_to(label, path, button_options)
25
+ end
26
+
27
+ capture_haml do
28
+ haml_tag :button, options.merge(:class => ["button", options[:class]].compact.uniq.join(" ")) do
29
+ haml_concat content
30
+ haml_tag :span
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,37 @@
1
+ module Storefront
2
+ module DashboardHelper
3
+ def dashboard_for(*args, &block)
4
+ record = args.shift
5
+ options = args.extract_options!
6
+ condition = extract_condition!(options)
7
+ @dashboard_record = record
8
+ concat(capture(&block)) if record && condition != false
9
+ @dashboard_record = nil
10
+ end
11
+
12
+ def dashboard(key, locals = {})
13
+ render :partial => key, :locals => locals.reverse_merge(:figures => [])
14
+ end
15
+
16
+ def figure(*names, &block)
17
+ locals = names.extract_options!
18
+ condition = extract_condition!(locals)
19
+
20
+ if condition != false
21
+ locals.reverse_merge(:locale => nil)
22
+ locals.merge!(:yielded_content => capture(&block)) if block_given?
23
+ result = capture_haml do
24
+ names.each do |name|
25
+ haml_concat render(:partial => "shared/dashboard/#{name}", :locals => locals)
26
+ end
27
+ end
28
+ end
29
+
30
+ result
31
+ end
32
+
33
+ def report_for(record_or_key, hash, options = {}, &block)
34
+ Semantic::Dashboard.new(self, record_or_key, hash, options, &block).content
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,11 @@
1
+ module Storefront
2
+ module DebugHelper
3
+ def inspecting?
4
+ params[:inspect] == "true"
5
+ end
6
+
7
+ def editing?
8
+ params[:edit] == "true"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,29 @@
1
+ module Storefront
2
+ module DefinitionListHelper
3
+ def term(key, value, options = {})
4
+ return if value.blank?
5
+ condition = extract_condition!(options)
6
+
7
+ if condition != false
8
+ result = capture_haml do
9
+ haml_tag :tr, :class => "term" do
10
+ text = key.is_a?(String) ? key : t("widgets.details.#{key}")
11
+ haml_tag :td, text.gsub(/:?$/, ":"), :class => "key first"
12
+ haml_tag :td, value, :class => "value"
13
+ end
14
+ end
15
+ end
16
+
17
+ result
18
+ end
19
+
20
+ def terms(&block)
21
+ capture_haml do
22
+ haml_tag :dl do
23
+ yield
24
+ end
25
+ end
26
+ end
27
+ alias definition_list terms
28
+ end
29
+ end
@@ -0,0 +1,11 @@
1
+ module Storefront
2
+ module ErrorHelper
3
+ def render_not_found(exception)
4
+ Exceptional::Catcher.handle_with_controller(exception, self, request) if defined?(::Exceptional)
5
+ logger.error(exception)
6
+ puts exception.inspect
7
+ puts exception.backtrace.join("\n")
8
+ render :template => "/error/404.html", :status => 404, :layout => false
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ module Storefront
2
+ module FlashHelper
3
+ def render_flash
4
+ flash_to_render = [:success, :failure, :notice, :error]
5
+ flash.select { |type, _| flash_to_render.include?(type) }.map do |type, content|
6
+ content_tag(:output, content, :class => "flash-#{type}")
7
+ end.join
8
+ end
9
+
10
+ def flash?
11
+ flash.present?
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,8 @@
1
+ module Storefront
2
+ module FormHelper
3
+ def form_for(*args, &block)
4
+ Storefront::Form.new(self, *args, &block).content
5
+ end
6
+ end
7
+ end
8
+
@@ -0,0 +1,59 @@
1
+ module Storefront
2
+ module FormatHelper
3
+ def rendered_text(string)
4
+ string.to_s.
5
+ gsub(/<\/?[^>]*>/, '').
6
+ gsub(/\n/, " ").
7
+ gsub("\r", " ").
8
+ squeeze(" ").
9
+ gsub(/\"/, "&Prime;"). # convert quotes to inches
10
+ gsub(/\'/, "&prime;"). # single quote to feet
11
+ gsub(/\$0?0*\.(\d+)/, "\\1&cent;").html_safe
12
+ end
13
+
14
+ def format_money(value)
15
+ value.present? ? ("$" + number_with_precision(value.to_s.gsub("$", ""), :precision => 2)) : nil
16
+ end
17
+
18
+ def format_percent(value)
19
+ value.present? ? (number_with_precision(value.to_s.gsub("%", ""), :precision => 0) + "%") : nil
20
+ end
21
+
22
+ def sanitize(text)
23
+ text.gsub(/<\/?[^>]*>/, '').gsub(/\n/, " ").gsub("\r", " ").squeeze(" ")
24
+ end
25
+
26
+ def n(value)
27
+ if value.respond_to?(:nan?) && value.nan?
28
+ 0
29
+ else
30
+ value
31
+ end
32
+ end
33
+
34
+ def s(string, default = "N/A")
35
+ string.present? ? string : default
36
+ end
37
+
38
+ def num(num, default = "N/A")
39
+ result = number_with_precision(num, :precision => 1)
40
+ result.blank? ? default : result
41
+ end
42
+
43
+ def money(value)
44
+ value ? value.to_s.gsub(/^\$?/, "$") : "$0"
45
+ end
46
+
47
+ def read_binary_file(path)
48
+ File.open(path, 'rb') {|f| f.read }
49
+ end
50
+
51
+ def encoded_contents(path)
52
+ Base64.encode64(read_binary_file(path)).gsub(/\n/, '')
53
+ end
54
+
55
+ def font_face_data_uri(path)
56
+ "url(\"data:font/truetype;base64,#{encoded_contents(path)}\")"
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,229 @@
1
+ module Storefront
2
+ module HeadHelper
3
+ def meta_for(post)
4
+ result = ""
5
+ unless post.title.blank?
6
+ result << title(post.title)
7
+ result << "\n"
8
+ end
9
+ unless post.tags.blank?
10
+ result << keywords(post.tags.join(", "))
11
+ result << "\n"
12
+ end
13
+ unless post.description.blank?
14
+ result << description(post.description)
15
+ result << "\n"
16
+ end
17
+ result
18
+ end
19
+
20
+ def meta(options = {})
21
+ title(options[:title]) if options.has_key?(:title)
22
+ description(options[:description]) if options.has_key?(:description)
23
+ keywords(options[:keywords]) if options.has_key?(:keywords)
24
+ copyright(options[:copyright]) if options.has_key?(:copyright)
25
+ end
26
+
27
+ def meta_tags(*args)
28
+ options = args.extract_options!
29
+ site = options[:site] || args.first
30
+ result = title_tag(site, options[:title])
31
+ result << "\n"
32
+ result << content_type_tag
33
+ result << "\n"
34
+ result << description_tag(options[:description])
35
+ result << "\n"
36
+ result << keywords_tag(options[:keywords])
37
+ result << "\n"
38
+ result << copyright_tag(options[:copyright])
39
+ result
40
+ end
41
+
42
+ # country
43
+ # classification
44
+ # author
45
+ # apple-mobile-web-app-capable
46
+ # apple-touch-fullscreen
47
+ # google-analytics
48
+ # Revisit-After
49
+ # category
50
+ def meta_tag(name, content = '')
51
+ tag(:meta, :name => name, :content => content)
52
+ end
53
+
54
+ def title(string)
55
+ @content_for_title = string
56
+ end
57
+
58
+ def title_tag(*args)
59
+ options = args.extract_options!
60
+
61
+ site = options[:site] || args.first
62
+ # Prefix (leading space)
63
+ if options[:prefix]
64
+ prefix = options[:prefix]
65
+ elsif options[:prefix] === false
66
+ prefix = ''
67
+ else
68
+ prefix = ' '
69
+ end
70
+
71
+ # Separator
72
+ unless options[:separator].blank?
73
+ separator = options[:separator]
74
+ else
75
+ separator = '|'
76
+ end
77
+
78
+ # Suffix (trailing space)
79
+ if options[:suffix]
80
+ suffix = options[:suffix]
81
+ elsif options[:suffix] === false
82
+ suffix = ''
83
+ else
84
+ suffix = ' '
85
+ end
86
+
87
+ # Title
88
+ title = @content_for_title
89
+ if options[:lowercase] === true
90
+ title = title.downcase unless title.blank?
91
+ end
92
+
93
+ # title
94
+ if title.blank?
95
+ result = content_tag :title, site
96
+ else
97
+ title = normalize_title(title)
98
+ title = [site] + title
99
+ title.reverse! unless options[:reverse] === false
100
+ sep = prefix + separator + suffix
101
+ result = content_tag(:title, title.join(sep))
102
+ end
103
+ result
104
+ end
105
+
106
+ def description(string)
107
+ @content_for_description = string
108
+ end
109
+
110
+ def description_tag(default='')
111
+ content = normalize_description(@content_for_description || default)
112
+ tag(:meta, :name => :description, :content => content) unless content.blank?
113
+ end
114
+
115
+ def keywords(string)
116
+ @content_for_keywords = string
117
+ end
118
+
119
+ def keywords_tag(default = '')
120
+ content = normalize_keywords(@content_for_keywords || default)
121
+ tag(:meta, :name => :keywords, :content => content) unless content.blank?
122
+ end
123
+
124
+ def copyright(string)
125
+ @content_for_copyright = string
126
+ end
127
+
128
+ def copyright_tag(default='')
129
+ content = @content_for_copyright || default
130
+ tag(:meta, :name => :copyright, :content => content) unless content.blank?
131
+ end
132
+
133
+ def robots(*args)
134
+ content_for(:robots, args.join(", "))
135
+ end
136
+
137
+ def robots_tag(*args)
138
+ options = args.extract_options!
139
+
140
+ noindex_name = tags[:noindex].is_a?(String) ? tags[:noindex] : 'robots'
141
+ nofollow_name = tags[:nofollow].is_a?(String) ? tags[:nofollow] : 'robots'
142
+
143
+ if noindex_name == nofollow_name
144
+ content = [(tags[:noindex] ? 'noindex' : nil), (tags[:nofollow] ? 'nofollow' : nil)].compact.join(', ')
145
+ unless content.blank?
146
+ result << "\n"
147
+ result << tag(:meta, :name => noindex_name, :content => content)
148
+ end
149
+ else
150
+ if tags[:noindex]
151
+ result << "\n"
152
+ result << tag(:meta, :name => noindex_name, :content => 'noindex')
153
+ end
154
+ if tags[:nofollow]
155
+ result << "\n"
156
+ result << tag(:meta, :name => nofollow_name, :content => 'nofollow')
157
+ end
158
+ end
159
+ # canonical
160
+ unless tags[:canonical].blank?
161
+ result << "\n"
162
+ result << tag(:link, :rel => :canonical, :href => tags[:canonical])
163
+ end
164
+
165
+ return result
166
+ end
167
+
168
+ def copyright(from)
169
+ now = Time.now.year
170
+ now.eql?(from) ? now : "#{from} - #{now}"
171
+ end
172
+
173
+ # Apple
174
+ # http://developer.apple.com/safari/library/documentation/AppleApplications/Reference/SafariHTMLRef/Articles/MetaTags.html
175
+
176
+ # Facebook (and opengraph)
177
+ # http://developers.facebook.com/docs/opengraph#types
178
+
179
+ # http://wiki.developers.facebook.com/index.php/Facebook_Share/Specifying_Meta_Tags
180
+ def snapshot_tag(href)
181
+ tag(:link, :rel => "image_src", :href => href)
182
+ end
183
+
184
+ # http://wiki.developers.facebook.com/index.php/Facebook_Share/Specifying_Meta_Tags
185
+ def medium(type)
186
+ tag(:meta, :name => :medium, :content => type)
187
+ end
188
+
189
+ def classification(type)
190
+ tag(:meta, :name => "og:type", :content => type)
191
+ end
192
+
193
+ def content_type_tag(type = "text/html", charset = "UTF-8")
194
+ meta_tag("Content-Type", "#{type}; charset=#{charset}")
195
+ end
196
+
197
+ def search_link_tag(href, title)
198
+ link_tag({:rel => "search", :type => "application/opensearchdescription+xml", :href => href, :title => title})
199
+ end
200
+
201
+ def favicon_link_tag(favicon = "/favicon.ico")
202
+ link_tag({:rel => "shortcut icon", :href => favicon, :type => "image/x-icon"})
203
+ end
204
+
205
+ def link_tag(options = {})
206
+ tag(:link, options)
207
+ end
208
+
209
+ private
210
+
211
+ def normalize_title(title)
212
+ if title.is_a? String
213
+ title = [title]
214
+ end
215
+ title.map { |t| h(strip_tags(t)) }
216
+ end
217
+
218
+ def normalize_description(description)
219
+ return '' unless description
220
+ truncate(strip_tags(description).gsub(/\s+/, ' '), :length => 200)
221
+ end
222
+
223
+ def normalize_keywords(keywords)
224
+ return '' unless keywords
225
+ keywords = keywords.flatten.join(', ') if keywords.is_a?(Array)
226
+ strip_tags(keywords).mb_chars.downcase
227
+ end
228
+ end
229
+ end