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, #build, #current_element, #current_flow, included, #insert, #insert_child, #prepend_within, #temporary

Constructor Details

#initializeTag

Initialization



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

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.



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

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


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

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


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

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


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

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


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

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



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

def [](attribute)
  attributes[attribute]
end

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



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

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

#add_class(classes) ⇒ Object



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

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.



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

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



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

def classes
  self[:class]
end

#classes=(classes) ⇒ Object



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

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

#empty?Boolean

Returns:

  • (Boolean)


287
288
289
# File 'lib/arbre/html/tag.rb', line 287

def empty?
  children.empty?
end

#generate_id!Object



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

def generate_id!
  self.id = object_id
end

#has_attribute?(name) ⇒ Boolean

Returns:

  • (Boolean)


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

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

#has_class?(klass) ⇒ Boolean

Returns:

  • (Boolean)


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

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

#inspectObject

Misc



304
305
306
307
308
309
310
311
312
# File 'lib/arbre/html/tag.rb', line 304

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)


291
292
293
294
295
# File 'lib/arbre/html/tag.rb', line 291

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

#remove_class(classes) ⇒ Object



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

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

#self_closing_tag?Boolean

Returns:

  • (Boolean)


297
298
299
# File 'lib/arbre/html/tag.rb', line 297

def self_closing_tag?
  false
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.



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

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.



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

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)


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

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

#to_sObject

Rendering



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

def to_s
  indent opening_tag, content, closing_tag
end