storefront 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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