fluffery 0.0.1

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.
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .DS_Store
6
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in fluffery.gemspec
4
+ gemspec
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "fluffery/version"
4
+
5
+ Gem::Specification.new do |s|
6
+
7
+ s.name = "fluffery"
8
+ s.version = Fluffery::VERSION
9
+ s.platform = Gem::Platform::RUBY
10
+ s.authors = ["kurb media"]
11
+ s.date = %q{2011-03-10}
12
+ s.email = %q{info@kurbmedia.com}
13
+ s.homepage = %q{http://github.com/kurbmedia/fluffery}
14
+ s.licenses = ["MIT"]
15
+ s.summary = %q{ummm.. Adds misc fluffery to yer apps.}
16
+ s.description = %q{Random fluffage for Rails applications.}
17
+
18
+ s.rubyforge_project = "fluffery"
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
23
+ s.require_paths = ["lib"]
24
+
25
+ s.add_development_dependency(%q<rails>, ["~> 3.0.0"])
26
+ s.add_development_dependency(%q<actionpack>, ["~> 3.0.0"])
27
+ s.add_development_dependency(%q<rspec>, ["~> 2.3"])
28
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
29
+
30
+
31
+ end
@@ -0,0 +1,21 @@
1
+ module Fluffery
2
+
3
+ autoload :Config, 'fluffery/config'
4
+
5
+ module Forms
6
+ autoload :Builder, 'fluffery/forms/builder'
7
+ autoload :Utilities, 'fluffery/forms/utilities'
8
+ end
9
+
10
+ module Helpers
11
+ autoload :Navigation, 'fluffery/helpers/navigation'
12
+ autoload :PageVariables, 'fluffery/helpers/page_variables'
13
+ autoload :Elements, 'fluffery/helpers/elements'
14
+ autoload :Includes, 'fluffery/helpers/includes'
15
+ end
16
+
17
+ module Utils
18
+ autoload :Internal, 'fluffery/utils/internal'
19
+ end
20
+
21
+ end
@@ -0,0 +1,29 @@
1
+ module Fluffery
2
+
3
+ class Config
4
+
5
+ def self.forms
6
+ @forms ||= {
7
+ :error_class => 'field_with_errors',
8
+ :message_error_class => 'errors_for_field',
9
+ :error_template => %{
10
+ <span class="<%= error_class %>">
11
+ <%= html_tag %>
12
+ <span class="<%= message_error_class %>"><%= [messages].flatten.join(",") %></span>
13
+ </span>
14
+ }
15
+ }
16
+ end
17
+
18
+ def self.dom
19
+ @dom ||= {}
20
+ end
21
+
22
+ def initialize
23
+ yield Fluffery::Config if block_given?
24
+ end
25
+
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,142 @@
1
+ module Fluffery
2
+ module Forms
3
+
4
+ class Builder < ActionView::Helpers::FormBuilder
5
+
6
+ include Fluffery::Forms::Utilities
7
+
8
+ # Access the template object
9
+ attr_accessor :template
10
+
11
+ # Sets up options custom to our form builder.
12
+ # It also overrides the default error proc so we can use something more custom.
13
+ #
14
+ def initialize(object_name, object, template, options, proc)
15
+ without_error_proc do
16
+ super(object_name, object, template, options, proc)
17
+ end
18
+ end
19
+
20
+ # Creates a html button tag for use in forms instead of the default input submit.
21
+ # Uses a span to wrap the content so it can be styled with css.
22
+ #
23
+ def button(value = nil, options = {})
24
+ value, options = nil, value if value.is_a?(Hash)
25
+ value ||= submit_default_value
26
+
27
+ options = confirm_or_disable(options)
28
+ options = Fluffery::Utils::Internal.merge_html_classes(options, 'button')
29
+
30
+ content_tag(:button, options.reverse_merge!({ "type" => "submit", "name" => "commit" })) do
31
+ content_tag(:span, value.to_s)
32
+ end
33
+
34
+ end
35
+
36
+ # Custom label tag including an asterisk if the field is required.
37
+ #
38
+ def label(method, text = nil, options = {}, &block)
39
+
40
+ options, text = text, nil if text.is_a?(Hash)
41
+ text ||= method.to_s.humanize
42
+ options.stringify_keys!
43
+
44
+ options.reverse_merge!('transform' => :titleize) unless option_exists?(options['transform'])
45
+ text.send(options['transform'].to_sym)
46
+ options.delete('transform')
47
+
48
+ # Check to see if :required is set on a label, or if the attribute/method has a validator that require it exists.
49
+ # If so, add a * to the label.
50
+ text = "#{text} <abbr title='Required'>*</abbr>".html_safe if validator.attribute_required?(method, options)
51
+ super(method, text, options, &block)
52
+
53
+ end
54
+
55
+ def email_field(method, options = {})
56
+ render_with_fluff(method, options) do
57
+ super(method, options.merge!('type' => 'email'))
58
+ end
59
+ end
60
+
61
+ # Renders the default date_select but with an error wrapping if
62
+ # the method in question has errors
63
+ #
64
+ def date_select(method, options = {}, html_options = {})
65
+ render_with_fluff(method, options, html_options) do
66
+ super(method, options, html_options)
67
+ end
68
+ end
69
+
70
+ # HTML5 Number field, again, falls back to text in unsupportive browsers.
71
+ #
72
+ def number_field(method, range, options = {})
73
+ options, range = range, nil if range.is_a?(Hash)
74
+ options.stringify_keys!
75
+ unless range.nil?
76
+ range = (range.is_a?(Range)) ? range.to_a : range
77
+ options.merge!('min' => range.first, 'max' => range.last)
78
+ end
79
+
80
+ render_with_fluff(method, options) do
81
+ super(method, options.merge!('type' => 'number'))
82
+ end
83
+
84
+ end
85
+
86
+ def password_field(method, options = {})
87
+ render_with_fluff(method, options) do
88
+ super(method, options)
89
+ end
90
+ end
91
+
92
+ def select(method, choices, options = {}, html_options = {})
93
+ render_with_fluff(method, options, html_options) do
94
+ @template.select(@object_name, method, choices, options, html_options)
95
+ end
96
+ end
97
+
98
+ def state_select(method, options = {}, html_options = {})
99
+
100
+ state_options = [['Please Select',nil]]
101
+ state_options << ['International', (int || 'International')] if int = options.delete(:international)
102
+ [
103
+ ['Alabama', "AL"],['Alaska', "AK"],['Arizona', "AZ"],['Arkansas', "AR"],['California', "CA"],['Colorado', "CO"],
104
+ ['Connecticut', "CT"],['District of Columbia', "DC"],['Delaware', "DE"],['Florida', "FL"],['Georgia', "GA"],
105
+ ['Hawaii', "HI"],['Idaho', "ID"],['Illinois', "IL"],['Indiana', "IN"],['Iowa', "IA"],['Kansas', "KS"],['Kentucky', "KY"],
106
+ ['Louisiana', "LA"],['Maine', "ME"],['Maryland', "MD"],['Massachusetts', "MA"],['Michigan', "MI"],['Minnesota', "MN"],
107
+ ['Mississippi', "MS"],['Missouri', "MO"],['Montana', "MT"],['Nebraska', "NE"],['Nevada', "NV"],['New Hampshire', "NH"],
108
+ ['New Jersey', "NJ"],['New Mexico', "NM"],['New York', "NY"],['North Carolina', "NC"],['North Dakota', "ND"],
109
+ ['Ohio', "OH"],['Oklahoma', "OK"],['Oregon', "OR"],['Pennsylvania', "PA"],['Rhode Island', "RI"],['South Carolina', "SC"],
110
+ ['South Dakota', "SD"],['Tennessee', "TN"],['Texas', "TX"],['Utah', "UT"],['Vermont', "VT"],['Virginia', "VA"],['Washington', "WA"],
111
+ ['West Virginia', "WV"],['Wisconsin', "WI"],['Wyoming', "WY"]
112
+ ].each do |state|
113
+ should_abbr = options.delete(:abbreviate)
114
+ state_options << (should_abbr ? state : [state.first, state.first])
115
+ end
116
+
117
+ select(method, @template.options_for_select(state_options, @object.try(:state)), options, html_options)
118
+
119
+ end
120
+
121
+ def text_field(method, options = {})
122
+ render_with_fluff(method, options) do
123
+ super(method, options)
124
+ end
125
+ end
126
+
127
+ def text_area(method, options = {})
128
+ render_with_fluff(method, options) do
129
+ super(method, options)
130
+ end
131
+ end
132
+
133
+ def url_field(method, options = {})
134
+ render_with_fluff(method, options) do
135
+ super(method, options.merge!('type' => 'url'))
136
+ end
137
+ end
138
+
139
+ end
140
+
141
+ end
142
+ end
@@ -0,0 +1,89 @@
1
+ require 'erb'
2
+ require 'fluffery/forms/validation/base'
3
+
4
+ module Fluffery
5
+ module Forms
6
+
7
+ module Utilities
8
+
9
+ # Simply shortening calls to content_tag since it is a method of @template
10
+ #
11
+ def content_tag(tag, content, options = {}, escape = true, &block)
12
+ @template.content_tag(tag, content, options, escape, &block)
13
+ end
14
+
15
+ # Adds data-confirm, or data-disable-with if set.
16
+ #
17
+ def confirm_or_disable(options)
18
+ options.stringify_keys!
19
+ options.merge!("data-disable-with" => options["disable_with"]) if options.delete("disable_with")
20
+ options.merge!("data-confirm" => options["confirm"]) if options.delete("confirm")
21
+ options
22
+ end
23
+
24
+ # Allows us to call something like f.error_console to log form errors
25
+ # to a javascript console such as firebug
26
+ #
27
+ def error_console
28
+ "<script type=\"text/javascript\" charset=\"utf-8\">
29
+ //<![CDATA[
30
+ try{ console.log(\"#{@template.escape_javascript(@object.errors.inspect)}\")}catch(e){}
31
+ //]]>
32
+ </script>".html_safe
33
+ end
34
+
35
+ # Quick helper to see if an option is nil, blank, or false
36
+ #
37
+ def option_exists?(opt)
38
+ !(opt.nil? || opt.to_s.blank? || opt.to_s === "false")
39
+ end
40
+
41
+ # Generate additional options on our fields.
42
+ # 1. If a field has errors, wrap it with the defined error template.
43
+ # 2. Also add our error class to the field itself.
44
+ #
45
+ def render_with_fluff(method, options, html_options = nil, &block)
46
+ _options = html_options.nil? ? options : html_options
47
+ _options = validator.add_html_attributes(method, _options)
48
+ # If no errors, simply return.
49
+ unless validator.errors_for?(method)
50
+ return block.call
51
+ end
52
+
53
+ configs = Fluffery::Config.forms
54
+ template = configs[:error_template]
55
+ error_class = configs[:error_class]
56
+ _options = Fluffery::Utils::Internal.merge_html_classes(_options, error_class)
57
+ options = _options if html_options.nil?
58
+
59
+ # Capture the original html tag with any updated options.
60
+ html_tag = block.call
61
+ return html_tag if template.nil? or template.blank?
62
+
63
+ renderer = ERB.new(template)
64
+ messages = @object.errors[method.to_sym]
65
+ message_error_class = configs[:message_error_class]
66
+ renderer.result(
67
+ OpenStruct.new(configs.merge!(:messages => messages)).send(:binding)
68
+ ).to_s.html_safe
69
+
70
+ end
71
+
72
+ def validator
73
+ @validator ||= Fluffery::Forms::Validation::Base.new(@object)
74
+ end
75
+
76
+ # Override the default error proc for our forms, making sure to
77
+ # set it back when we are finished to avoid compatibility issues.
78
+ #
79
+ def without_error_proc
80
+ default_proc = ActionView::Base.field_error_proc
81
+ ActionView::Base.field_error_proc, proc = lambda{ |html_tag, instance| html_tag }
82
+ yield
83
+ ActionView::Base.field_error_proc = default_proc
84
+ end
85
+
86
+ end
87
+
88
+ end
89
+ end
@@ -0,0 +1,178 @@
1
+ module Fluffery
2
+ module Forms
3
+ module Validation
4
+
5
+ class Base
6
+
7
+ require 'fluffery/forms/validation/validators'
8
+
9
+ attr_accessor :object
10
+
11
+ def initialize(form_object)
12
+ @object = form_object
13
+ end
14
+
15
+ def add_html_attributes(attribute, options)
16
+ options = Presence.create(attribute, options) if attribute_required?(attribute)
17
+ matcher = attribute_format_validator(attribute)
18
+ options = Pattern.create(attribute, options, matcher) unless matcher.nil?
19
+ options.reverse_merge!(default_messages_for(attribute))
20
+ options
21
+ end
22
+
23
+ # Checks to see if the particular attribute is required, used primarily on labels.
24
+ #
25
+ def attribute_required?(attribute, options = nil)
26
+ options.stringify_keys! if options.is_a?(Hash)
27
+ unless options.nil?
28
+ return true if options.has_key?('required') and options['required'] === true
29
+ end
30
+ valid_items = validators_for(attribute).find do |validator|
31
+ ([:presence, :inclusion].include?(validator.kind)) &&
32
+ (validator.options.present? ? options_require_validation?(validator.options) : true)
33
+ end
34
+ !valid_items.nil?
35
+ end
36
+
37
+ # Checks to see if a particular attribute contains a Regex format validator
38
+ #
39
+ def attribute_format_validator(attribute)
40
+ format_validator = validators_for(attribute).detect{ |v| v.kind == :format }
41
+ return nil unless !format_validator.nil?
42
+ return nil unless format_validator.options.has_key?(:with) && format_validator.options[:with].is_a?(Regexp)
43
+ matcher = format_validator.options[:with]
44
+ end
45
+
46
+ # Looks up the default error message so it may be used in our data-message attribute
47
+ #
48
+ def default_messages_for(attribute)
49
+ validators = validators_for(attribute)
50
+ return {} if validators.empty?
51
+ message_data = validators.inject({}) do |hash, validator|
52
+ message = validator.options.has_key?(:message) ? validator.options[:message] : MessageBuilder.message_for(@object, attribute, validator)
53
+ hash.merge!(validator.kind.to_s => message)
54
+ end
55
+ attr_hash = {'data-validation-messages' => CGI::escape(message_data.to_json) }
56
+
57
+ # Create a list of data-validates-* attrs on the field so we can catch them with javascript
58
+ # Skip presence and format because they have their own valid HTML5 attrs.
59
+ #
60
+ validators.reject{ |v| v.kind.to_s.match(/(presence|format)/i) }.each{ |v| attr_hash.merge!("data-validates-#{v.kind.to_s}" => 'true') }
61
+
62
+ attr_hash
63
+
64
+ end
65
+
66
+ # Checks to see if the particular attribute has errors
67
+ #
68
+ def errors_for?(method)
69
+ !(@object.nil? || @object.errors.empty? || !@object.errors.key?(method.to_sym) || [@object.errors[method.to_sym]].flatten.empty?)
70
+ end
71
+
72
+ # Checks to see if the validation is required
73
+ # Courtesy Justin French and Formtastic
74
+ #
75
+ def options_require_validation?(options)
76
+ allow_blank = options[:allow_blank]
77
+ return !allow_blank unless allow_blank.nil?
78
+ if_condition = !options[:if].nil?
79
+ condition = if_condition ? options[:if] : options[:unless]
80
+
81
+ condition = if condition.respond_to?(:call)
82
+ condition.call(@object)
83
+ elsif condition.is_a?(::Symbol) && @object.respond_to?(condition)
84
+ @object.send(condition)
85
+ else
86
+ condition
87
+ end
88
+
89
+ if_condition ? !!condition : !condition
90
+ end
91
+
92
+ # Finds all existing validations for the current object and method
93
+ #
94
+ def validators_for(attribute)
95
+ return [] unless !@object.nil? and @object.class.respond_to?(:validators_on)
96
+ attribute = attribute.to_s.sub(/_id$/, '').to_sym
97
+ validators = @object.class.validators_on(attribute).uniq
98
+ end
99
+
100
+ def validators_for?(method)
101
+ !validators_for(method).empty?
102
+ end
103
+
104
+ end
105
+
106
+ class MessageBuilder
107
+ def self.message_for(object, attribute, validator)
108
+ message = self.get_validation_message(validator)
109
+ message = self.defaults(validator.kind) unless message.match(/translation missing/i).nil?
110
+ message
111
+ end
112
+
113
+ private
114
+
115
+ def self.defaults(validator)
116
+ {
117
+ :presence => "required",
118
+ :format => 'invalid',
119
+ :length => "wrong length",
120
+ :numericality => "not a number",
121
+ :uniqueness => 'taken',
122
+ :confirmation => 'required',
123
+ :acceptance => 'required',
124
+ :inclusion => 'invalid',
125
+ :exclusion => 'invalid'
126
+ }[validator]
127
+ end
128
+
129
+ def self.get_validation_message(validator)
130
+ key = {
131
+ :presence => "blank",
132
+ :format => 'invalid',
133
+ :length => self.length_options(validator.options),
134
+ :numericality => self.numericality_options(validator.options),
135
+ :uniqueness => 'taken',
136
+ :confirmation => 'confirmation',
137
+ :acceptance => 'accepted',
138
+ :inclusion => 'inclusion',
139
+ :exclusion => 'exclusion'
140
+ }[validator.kind]
141
+ key.is_a?(Array) ? I18n.translate("errors.messages.#{key.first}").sub("%{#{:count}}", key.last.to_s) : I18n.translate("errors.messages.#{key}")
142
+ end
143
+
144
+ def self.length_options(opts)
145
+ if count = opts[:is]
146
+ ["wrong_length", count]
147
+ elsif count = opts[:minimum]
148
+ ["too_short", count]
149
+ elsif count = opts[:maximum]
150
+ ["too_long", count]
151
+ end
152
+ end
153
+
154
+ def self.numericality_options(opts)
155
+ if opts[:only_integer]
156
+ 'not_a_number'
157
+ elsif count = opts[:greater_than]
158
+ ['greater_than', count]
159
+ elsif count = opts[:greater_than_or_equal_to]
160
+ ['greater_than_or_equal_to', count]
161
+ elsif count = opts[:less_than]
162
+ ['less_than', count]
163
+ elsif count = opts[:less_than_or_equal_to]
164
+ ['less_than_or_equal_to', count]
165
+ elsif opts[:odd]
166
+ 'odd'
167
+ elsif opts[:even]
168
+ 'even'
169
+ else
170
+ 'not_a_number'
171
+ end
172
+ end
173
+
174
+ end
175
+
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,21 @@
1
+ module Fluffery
2
+ module Forms
3
+ module Validation
4
+
5
+ class Presence < Fluffery::Forms::Validation::Base
6
+ def self.create(attribute ,options)
7
+ options.merge!('required' => 'required') unless options.has_key?('required') && options['required'] === false
8
+ options
9
+ end
10
+ end
11
+
12
+ class Pattern < Fluffery::Forms::Validation::Base
13
+ def self.create(attribute, options, matcher)
14
+ options.reverse_merge!('pattern' => matcher.inspect) unless matcher.nil?
15
+ options
16
+ end
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,57 @@
1
+ module Fluffery
2
+ module Helpers
3
+
4
+ module Elements
5
+
6
+ # Simply overriding the default form_for to add additional html options/attributes.
7
+ def form_for(record_or_name_or_array, *args, &block)
8
+
9
+ options = args.last.is_a?(Hash) ? args.pop : {}
10
+ options[:html] ||= {}
11
+
12
+ # Add support for the 'ajax' uploader.
13
+ options[:html].merge!('data-remote-uploadable' => true) if options.delete(:remote_upload)
14
+ # Add support for javascript validation.
15
+ options[:html].merge!('data-js-validatable' => true) if options.delete(:validate)
16
+
17
+ args = (args << options)
18
+ super(record_or_name_or_array, *args, &block)
19
+
20
+ end
21
+
22
+ # Creates a common format for CSS buttons
23
+ # Example: button_link('Blog', '/blog') yields <a href="/blog" class="button"><span>Blog</span></a>
24
+
25
+ def button_link(txt, path, attrs = {})
26
+ inline_classes = attrs.has_key?(:class) ? "#{attrs[:class]} " : ""
27
+ link_to "<span>#{txt}</span>".html_safe, path, attrs.merge({ :class => "#{inline_classes}button" })
28
+ end
29
+
30
+ # Outputs all flash messages. This allows you to call <%= flash_messages %> once in your
31
+ # application's layout file. The output is a div with the class flash_message, and the type used. It also renders
32
+ # a "close" tag, which can be overridden or set to "". By default this is a span containing 'X'
33
+ #
34
+ # <div class="flash_message error">
35
+ # Your error message from flash[:error]
36
+ # <span>X</span>
37
+ # </div>
38
+ #
39
+ #
40
+ def flash_messages(attrs = {})
41
+ wrapper = attrs.delete(:wrapper) || :div
42
+ closer = attrs.delete(:close) || "<span>X</span>"
43
+ classes = (attrs.key?(:class)) ? attrs[:class].split(' ') : []
44
+ classes << "flash_message"
45
+ content = ""
46
+ flash.each_key do |k|
47
+ classes << "flash_message_#{k.to_s.underscore}"
48
+ msg_attrs = attrs.merge(:class => [k.to_s, classes].flatten.join(' '))
49
+ content.concat content_tag(wrapper, "#{flash[k]} #{closer}".html_safe, msg_attrs).html_safe
50
+ end
51
+ content.html_safe
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,20 @@
1
+ module Fluffery
2
+ module Helpers
3
+
4
+ module Includes
5
+
6
+ # Wraps output in IE conditional tags, the condition should be specified in the same
7
+ # format as it would in the conditional itself. For example:
8
+ # ie_conditional('lte IE 8') yields [if lte IE 8]
9
+ #
10
+ def ie_conditional(condition, &block)
11
+ output = ["<!--[if #{condition}]>"]
12
+ output << capture(&block)
13
+ output << "<![endif]-->"
14
+ output.join("\n").html_safe
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,47 @@
1
+ module Fluffery
2
+ module Helpers
3
+ module Navigation
4
+
5
+ # Creates a navigation link (by default a list item) that has the class 'on' if we are on that particular page or a
6
+ # page beneath it.
7
+ # Example: nav_link_to('Blog', 'blog') will have the class of 'on' should we be on /blog or /blog/some_path
8
+
9
+ def nav_link_to(txt, path, attrs = {}, wrapper = :li)
10
+
11
+ path_validation = false
12
+ path_validation = attrs.has_key?(:proc) ? attrs[:proc].call(path) : (request.path == path || request.path.match(/#{path}\/.*/i))
13
+ path_validation = request.path.match(/#{attrs[:matcher].gsub("_path", path)}/i) if attrs.has_key?(:matcher)
14
+ attrs.delete(:proc)
15
+ attrs.delete(:matcher)
16
+
17
+ wrapper_attrs = attrs.delete(:wrapper)
18
+ attrs, wrapper_attrs = merge_html_classes(attrs, path_validation), merge_html_classes(wrapper_attrs, path_validation)
19
+
20
+ return_val = link_to_unless(path_validation, txt, path, attrs) do
21
+ link_to(txt, path, attrs)
22
+ end
23
+
24
+ (wrapper.eql? false) ? return_val : content_tag(wrapper, return_val, wrapper_attrs)
25
+
26
+ end
27
+
28
+ # Creates a nested navigation block, generally used for lists/nested lists.
29
+ def navigation(txt, path, attrs = {}, options = {}, &block)
30
+ options.reverse_merge!(:container => :ol, :wrapper => :li)
31
+ navigation_content = content_tag(options[:container], capture(&block))
32
+ wrapper_attrs = attrs.delete(:wrapper)
33
+ parent_link = nav_link_to(txt, path, attrs, false)
34
+ content_tag(options[:wrapper], "#{parent_link}\n#{navigation_content}".html_safe, (wrapper_attrs || {}))
35
+ end
36
+
37
+ private
38
+
39
+ def merge_html_classes(attrs, add_on = false)
40
+ attrs ||= {}
41
+ Fluffery::Utils::Internal.merge_html_classes(attrs, 'on') if add_on
42
+ attrs
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,51 @@
1
+ module Fluffery
2
+ module Helpers
3
+
4
+ module PageVariables
5
+
6
+ def page_default(param, data = nil)
7
+ create_variable("helpful_#{param}", data) unless data.nil? or data.blank?
8
+ end
9
+
10
+ def page_id(content = nil)
11
+ create_internal_variable(:helpful_page_id, content) and return unless content.nil?
12
+ return retrieve_variable(:helpful_page_id) if content_for?(:helpful_page_id)
13
+ cname = controller.class.to_s.gsub(/controller$/i,'').underscore.split("/").join('_')
14
+ aname = controller.action_name
15
+ "#{cname}_#{aname}"
16
+ end
17
+
18
+ def page_title(content = nil)
19
+ (content.nil?) ? retrieve_variable(:helpful_page_title) : create_internal_variable(:helpful_page_title, content)
20
+ end
21
+
22
+ def keywords(content = nil)
23
+ (content.nil?) ? retrieve_variable(:helpful_keywords) : create_internal_variable(:helpful_keywords, content)
24
+ end
25
+
26
+ def description(content = nil)
27
+ (content.nil?) ? retrieve_variable(:helpful_description) : create_internal_variable(:helpful_description, content)
28
+ end
29
+
30
+ def create_variable(var, content, new_method = true)
31
+ content_for(var.to_sym) do
32
+ content
33
+ end
34
+ self.class_eval{ define_method("#{var.to_s}"){ retrieve_variable(var.to_sym) } } if new_method
35
+ return ""
36
+ end
37
+
38
+ private
39
+
40
+ def create_internal_variable(var, content)
41
+ create_variable(var, content, false)
42
+ end
43
+
44
+ def retrieve_variable(var)
45
+ (content_for?(var.to_sym) ? content_for(var.to_sym) : "")
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,14 @@
1
+ module Fluffery
2
+ class Railtie < Rails::Railtie
3
+
4
+ initializer :after_initialize do
5
+ # Configure ActionView with any addons.
6
+ ActionView::Base.send :include, Fluffery::Helpers::Navigation
7
+ ActionView::Base.send :include, Fluffery::Helpers::PageVariables
8
+ ActionView::Base.send :include, Fluffery::Helpers::Elements
9
+ ActionView::Base.send :include, Fluffery::Helpers::Includes
10
+ ActionView::Base.send :default_form_builder=, Fluffery::Forms::Builder
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ module Fluffery
2
+ module Utils
3
+
4
+ class Configurator
5
+
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,19 @@
1
+ module Fluffery
2
+ module Utils
3
+
4
+ class Internal
5
+
6
+ # Merge any new classes with existing html classes
7
+ #
8
+ def self.merge_html_classes(options, classes)
9
+ classes = [classes].flatten
10
+ options.stringify_keys!
11
+ return options.merge!('class' => classes.join(' ')) unless options.has_key?('class')
12
+ old_classes = options['class'].split(' ')
13
+ options.merge!('class' => [classes, old_classes].flatten.join(' '))
14
+ end
15
+
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ module Fluffery
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluffery
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - kurb media
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-03-10 00:00:00 -05:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rails
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ~>
23
+ - !ruby/object:Gem::Version
24
+ version: 3.0.0
25
+ type: :development
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: actionpack
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ~>
34
+ - !ruby/object:Gem::Version
35
+ version: 3.0.0
36
+ type: :development
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: rspec
40
+ prerelease: false
41
+ requirement: &id003 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: "2.3"
47
+ type: :development
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
50
+ name: bundler
51
+ prerelease: false
52
+ requirement: &id004 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ~>
56
+ - !ruby/object:Gem::Version
57
+ version: 1.0.0
58
+ type: :development
59
+ version_requirements: *id004
60
+ description: Random fluffage for Rails applications.
61
+ email: info@kurbmedia.com
62
+ executables: []
63
+
64
+ extensions: []
65
+
66
+ extra_rdoc_files: []
67
+
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - Rakefile
72
+ - fluffery.gemspec
73
+ - lib/fluffery.rb
74
+ - lib/fluffery/config.rb
75
+ - lib/fluffery/forms/builder.rb
76
+ - lib/fluffery/forms/utilities.rb
77
+ - lib/fluffery/forms/validation/base.rb
78
+ - lib/fluffery/forms/validation/validators.rb
79
+ - lib/fluffery/helpers/elements.rb
80
+ - lib/fluffery/helpers/includes.rb
81
+ - lib/fluffery/helpers/navigation.rb
82
+ - lib/fluffery/helpers/page_variables.rb
83
+ - lib/fluffery/railtie.rb
84
+ - lib/fluffery/utils/configurator.rb
85
+ - lib/fluffery/utils/internal.rb
86
+ - lib/fluffery/version.rb
87
+ has_rdoc: true
88
+ homepage: http://github.com/kurbmedia/fluffery
89
+ licenses:
90
+ - MIT
91
+ post_install_message:
92
+ rdoc_options: []
93
+
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: "0"
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: "0"
108
+ requirements: []
109
+
110
+ rubyforge_project: fluffery
111
+ rubygems_version: 1.6.1
112
+ signing_key:
113
+ specification_version: 3
114
+ summary: ummm.. Adds misc fluffery to yer apps.
115
+ test_files: []
116
+