Class: Arbre::Html::Tag

Inherits:
Element show all
Defined in:
lib/arbre/html/tag.rb

Overview

HTML tag element. Has attributes and is rendered as a HTML tag.

Direct Known Subclasses

Document

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Element

#+, #<<, #ancestors, #arbre_context, #assigns, #children, #content, #content=, #descendants, #has_children?, #helpers, #indent_level, #orphan?, #parent, #parent=, #remove!, #respond_to?, #to_html

Methods included from Querying

#child_tags, #descendant_tags, #find, #find_by_classes, #find_by_id, #find_by_tag, #find_by_tag_and_classes, #find_first

Methods included from Element::Building

#append_within, #append_within?, #build, #current_element, #current_flow, included, #insert, #insert_child, #prepend_within, #prepend_within?, #temporary

Constructor Details

#initializeTag

Initialization



13
14
15
16
17
# File 'lib/arbre/html/tag.rb', line 13

def initialize(*)
  super

  @attributes = Attributes.new
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Arbre::Element

Instance Attribute Details

#attributesObject (readonly)

Returns the value of attribute attributes.



38
39
40
# File 'lib/arbre/html/tag.rb', line 38

def attributes
  @attributes
end

Class Method Details

.attribute(*attributes, boolean: false) ⇒ Object

Defines an HTML attribute accessor.

Example

class CheckBox < Tag

  def tag_name
    'input'
  end

  attribute :value
  attribute :checked, boolean: true

  def build
    self[:type] = 'checkbox'
    self.value = '1'         # equivalent to self[:value] = '1'
    self.checked = true      # equivalent to self[:checked] = 'checked'
    self.checked = false     # equivalent to self[:checked] = nil, i.e. removes the attribute
  end

end


106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/arbre/html/tag.rb', line 106

def attribute(*attributes, boolean: false)
  attributes.each do |attribute|
    if boolean
      class_eval <<-RUBY, __FILE__, __LINE__+1
        def #{attribute}
          has_attribute? :#{attribute}
        end
        def #{attribute}=(value)
          self[:#{attribute}] = !!value
        end
      RUBY
    else
      class_eval <<-RUBY, __FILE__, __LINE__+1
        def #{attribute}
          self[:#{attribute}]
        end
        def #{attribute}=(value)
          self[:#{attribute}] = value
        end
      RUBY
    end
  end
end

.classes(*classes) ⇒ Object

Defines the tag (CSS) classes for this class and derived classes.

Usage

The following two are equivalent:

classes 'dashboard', 'floatright'

and

def build!(*)
  super
  add_class 'dashboard'
  add_class 'floatright'
end


189
190
191
192
193
194
195
196
# File 'lib/arbre/html/tag.rb', line 189

def classes(*classes)
  classes = classes.flatten.map(&:to_s)
  class_eval <<-RUBY, __FILE__, __LINE__+1
    def tag_classes
      #{classes.inspect}
    end
  RUBY
end

.id(id) ⇒ Object

Defines the tag ID attribute for this class and derived classes.

Usage

The following two are equivalent:

id 'my-div'

and

def build!(*)
  super
  self.id = 'my-div'
end


166
167
168
169
170
171
172
# File 'lib/arbre/html/tag.rb', line 166

def id(id)
  class_eval <<-RUBY, __FILE__, __LINE__+1
    def tag_id
      #{id.to_s.inspect}
    end
  RUBY
end

.tag(tag) ⇒ Object

Defines the tag name for this class and derived classes. This is a DSL-alternative to defining method tag_name.

Usage

The following two are equivalent:

tag 'div'

and

def tag_name
  'div'
end


144
145
146
147
148
149
150
# File 'lib/arbre/html/tag.rb', line 144

def tag(tag)
  class_eval <<-RUBY, __FILE__, __LINE__+1
    def tag_name
      #{tag.to_s.inspect}
    end
  RUBY
end

Instance Method Details

#[](attribute) ⇒ Object Also known as: get_attribute



200
201
202
# File 'lib/arbre/html/tag.rb', line 200

def [](attribute)
  attributes[attribute]
end

#[]=(attribute, value) ⇒ Object Also known as: set_attribute



205
206
207
# File 'lib/arbre/html/tag.rb', line 205

def []=(attribute, value)
  attributes[attribute] = value
end

#add_class(classes) ⇒ Object



222
223
224
# File 'lib/arbre/html/tag.rb', line 222

def add_class(classes)
  self[:class].add classes if classes.present?
end

#build!(*args, **extra) ⇒ Object

Builds a tag.

Any remaining keyword arguments that are received by this method are merged into the attributes array. This means that in your subclass, you can use keyword arguments, if you always end with **extra which you pass on to this method.

Parameters:

  • content (String)

    Any raw content for in the tag.

  • attributes (Hash)

    HTML attributes to render.



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/arbre/html/tag.rb', line 54

def build!(*args, **extra)
  attributes = args.extract_options!

  self.content  = args.first unless args.empty?
  self.id     ||= tag_id

  attributes.update extra

  # Take out attributes that have a corresponding '<attribute>=' method, so that
  # they can be processed better.
  attributes.keys.each do |name|
    next if name.to_s == 'content'
    next if helpers && helpers.respond_to?(:"#{name}=")

    send :"#{name}=", attributes.delete(name) if respond_to?(:"#{name}=")
  end

  # Set all other attributes normally.
  self.attributes.update attributes

  # Add classes now, so as to not overwrite these with a :class argument.
  add_class tag_classes.join(' ') if tag_classes.present?

  super()
end

#classesObject



235
236
237
# File 'lib/arbre/html/tag.rb', line 235

def classes
  self[:class]
end

#classes=(classes) ⇒ Object



231
232
233
# File 'lib/arbre/html/tag.rb', line 231

def classes=(classes)
  self[:class] = classes.present? ? classes : nil
end

#empty?Boolean

Returns:

  • (Boolean)


295
296
297
# File 'lib/arbre/html/tag.rb', line 295

def empty?
  children.empty?
end

#generate_id!Object



218
219
220
# File 'lib/arbre/html/tag.rb', line 218

def generate_id!
  self.id = object_id
end

#has_attribute?(name) ⇒ Boolean

Returns:

  • (Boolean)


210
211
212
# File 'lib/arbre/html/tag.rb', line 210

def has_attribute?(name)
  attributes.has_key? name
end

#has_class?(klass) ⇒ Boolean

Returns:

  • (Boolean)


239
240
241
# File 'lib/arbre/html/tag.rb', line 239

def has_class?(klass)
  klass.split(' ').all? { |cls| classes.include?(cls) }
end

#inspectObject

Misc



312
313
314
315
316
317
318
319
320
# File 'lib/arbre/html/tag.rb', line 312

def inspect
  tag_desc = tag_name
  tag_desc << "(#{self.class.name})" if self.class.name.demodulize != tag_name.camelize
  tag_desc << "##{id}" if id
  tag_desc << classes.map{ |cls| ".#{cls}" }.join
  tag_desc << "[type=#{self[:type]}]" if has_attribute?(:type)

  "<#{tag_desc}>"
end

#one_line?Boolean

Returns:

  • (Boolean)


299
300
301
302
303
# File 'lib/arbre/html/tag.rb', line 299

def one_line?
  children.length == 1 &&
  children.first.is_a?(TextNode) &&
  !children.first.text.include?("\n")
end

#remove_class(classes) ⇒ Object



226
227
228
229
# File 'lib/arbre/html/tag.rb', line 226

def remove_class(classes)
  self[:class].remove classes
  self[:class] = nil if self[:class].empty?
end

#self_closing_tag?Boolean

Returns:

  • (Boolean)


305
306
307
# File 'lib/arbre/html/tag.rb', line 305

def self_closing_tag?
  false
end

#styleObject



243
244
245
# File 'lib/arbre/html/tag.rb', line 243

def style
  self[:style]
end

#style=(value) ⇒ Object



246
247
248
# File 'lib/arbre/html/tag.rb', line 246

def style=(value)
  self[:style] = value
end

#tag_classesObject

Override this if you want to give your tag some default classes. You can also use method classes for the same purpose.



35
36
# File 'lib/arbre/html/tag.rb', line 35

def tag_classes
end

#tag_idObject

Override this if you want to give your tag a default ID. You can also use method id for the same purpose.



30
31
# File 'lib/arbre/html/tag.rb', line 30

def tag_id
end

#tag_nameObject

Override this to provide a proper tag name. You can also use method tag for the same purpose.

Raises:

  • (NotImplementedError)


24
25
26
# File 'lib/arbre/html/tag.rb', line 24

def tag_name
  raise NotImplementedError, "method `tag_name' not implemented for #{self.class.name}"
end

#to_sObject

Rendering



253
254
255
# File 'lib/arbre/html/tag.rb', line 253

def to_s
  indent opening_tag, content, closing_tag
end