Skip to content

Instantly share code, notes, and snippets.

@pier-oliviert
Last active August 29, 2015 14:08
Show Gist options
  • Select an option

  • Save pier-oliviert/69d60505fa6e44863e52 to your computer and use it in GitHub Desktop.

Select an option

Save pier-oliviert/69d60505fa6e44863e52 to your computer and use it in GitHub Desktop.
module ContentTagHelper
def content_tag(*args)
if block_given?
tag = Tag.new(args[0], args[1] || {})
old_buf = @output_buffer
@output_buffer = ActionView::OutputBuffer.new
value = yield(tag)
content = tag.render(@output_buffer.presence || value)
@output_buffer = old_buf
content
else
super
end
end
class Tag
include ActionView::Helpers::CaptureHelper
attr_accessor :id
attr_reader :name, :css
def initialize(name, attributes = {})
@name = name
@attributes = attributes.with_indifferent_access
@attributes[:class] = Tag::CSS.new(attributes[:class])
end
def []=(k,v)
@attributes[k] = v
end
def [](k)
@attributes[k]
end
def render(content)
"<#{name}#{render_attributes}>#{content.strip}</#{name}>".html_safe
end
def render_attributes
attrs = @attributes.dup
if self[:class].empty?
attrs.delete :class
else
attrs[:class] = self[:class].to_s
end
attrs.keys.map do |k|
"#{k}='#{attrs[k]}'".html_safe
end.join.prepend(' ')
end
class CSS
def initialize(css)
if css.is_a? String
@internals = css.split(' ')
else
@internals = css.to_a
end
end
def to_s
@internals.uniq.join(' ')
end
def empty?
@internals.empty?
end
def <<(name)
@internals << name
nil
end
end
end
end
<%= content_tag :div do |div| %>
<% if true %>
<% div[:class] << :selected %>
<% end %>
<h1>Hello!</h1>
<% end %>
@tors
Copy link

tors commented Oct 27, 2014

Hey, this is neat. However li.css is kind of confusing in my opinion because what you are referring to .css here is just the CSS classes. li.css_classes might be more appropriate to avoid confusion. With .css you can implement something like what jQuery CSS api offers. See http://api.jquery.com/css/

@pier-oliviert
Copy link
Author

Hey, sorry I didn't see your comment earlier. I agree that li.css is confusing. However, I would like to keep the method to a single name to make it easier to understand.

Right now, I set/access every other html attributes using the []=(k,v) and I'm wondering if CSS shouldn't be the same. So basically, it would change from

li.css << :selected

to

li[:class] << :selected

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment