Class: Undies::Element

Inherits:
Node
  • Object
show all
Defined in:
lib/undies/element.rb

Constant Summary collapse

ID_METH_REGEX =

CSS proxy methods ============================================

/^([^_].+)!$/
CLASS_METH_REGEX =
/^([^_].+)$/

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Node

add_build, attrs, builds, content, end_tag, merge_attrs, mode, node_name, start_tag

Constructor Details

#initialize(name, attrs = {}, &build) ⇒ Element

Returns a new instance of Element.



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/undies/element.rb', line 66

def initialize(name, attrs={}, &build)
  super(nil)
  @start_tag = ""
  @end_tag = ""
  @content = nil
  @builds = []
  @children = false

  if !attrs.kind_of?(::Hash)
    raise ArgumentError, "#{name.inspect} attrs must be provided as a Hash."
  end

  @name  = name.to_s
  @attrs = attrs
  @builds << build if build

  # cache in an instance variable for fast access with flush and pop
  self.class.set_start_tag(self)
  self.class.set_end_tag(self)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args, &block) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/undies/element.rb', line 91

def method_missing(meth, *args, &block)
  if meth.to_s =~ ID_METH_REGEX
    proxy($1, args.first || {}, block) do |value|
      @attrs.merge!(:id => value)
    end
  elsif meth.to_s =~ CLASS_METH_REGEX
    proxy($1, args.first || {}, block) do |value|
      @attrs[:class] = [@attrs[:class], value].compact.join(' ')
    end
  else
    super
  end
end

Class Method Details

.children(element) ⇒ Object



36
37
38
# File 'lib/undies/element.rb', line 36

def self.children(element)
  element.instance_variable_get("@children")
end

.escape_attr_value(value) ⇒ Object



24
25
26
27
28
29
30
# File 'lib/undies/element.rb', line 24

def self.escape_attr_value(value)
  value.
    to_s.
    gsub('&', '&amp;').
    gsub('<', '&lt;').
    gsub('"', '&quot;')
end

.hash_attrs(attrs = "", ns = nil) ⇒ Object

have as many methods to the class level as possilbe to keep from polluting the public instance methods and to maximize the effectiveness of the Element#method_missing logic



10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/undies/element.rb', line 10

def self.hash_attrs(attrs="", ns=nil)
  return attrs.to_s if !attrs.kind_of?(::Hash)

  {}.tap do |a|
    attrs.each { |k, v| a[ns ? "#{ns}_#{k}" : k.to_s] = v }
  end.sort.inject('') do |html, k_v|
    html + if k_v.last.kind_of?(::Hash)
      hash_attrs(k_v.last, k_v.first)
    else
      " #{k_v.first}=\"#{escape_attr_value(k_v.last)}\""
    end
  end
end

.prefix(element, meth, level, indent) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
# File 'lib/undies/element.rb', line 40

def self.prefix(element, meth, level, indent)
  "".tap do |value|
    if indent > 0
      if meth == 'start_tag'
        value << "#{level > 0 ? "\n": ''}#{' '*level*indent}"
      elsif meth == 'end_tag'
        value << "\n#{' '*level*indent}" if children(element)
      end
    end
  end
end

.set_children(element, value) ⇒ Object



32
33
34
# File 'lib/undies/element.rb', line 32

def self.set_children(element, value)
  element.instance_variable_set("@children", value)
end

.set_end_tag(element) ⇒ Object



59
60
61
62
63
64
# File 'lib/undies/element.rb', line 59

def self.set_end_tag(element)
  element.instance_variable_set(
    "@end_tag",
    builds(element).size > 0 ? "</#{node_name(element)}>" : nil
  )
end

.set_start_tag(element) ⇒ Object



52
53
54
55
56
57
# File 'lib/undies/element.rb', line 52

def self.set_start_tag(element)
  element.instance_variable_set(
    "@start_tag",
    "<#{node_name(element)}#{hash_attrs(attrs(element))}" + (builds(element).size > 0 ? ">" : " />")
  )
end

Instance Method Details

#==(other) ⇒ Object



114
115
116
117
# File 'lib/undies/element.rb', line 114

def ==(other)
  other.instance_variable_get("@name")  == @name  &&
  other.instance_variable_get("@attrs") == @attrs
end

#respond_to?(*args) ⇒ Boolean

Returns:

  • (Boolean)


105
106
107
108
109
110
111
# File 'lib/undies/element.rb', line 105

def respond_to?(*args)
  if args.first.to_s =~ ID_METH_REGEX || args.first.to_s =~ CLASS_METH_REGEX
    true
  else
    super
  end
end

#to_str(*args) ⇒ Object Also known as: inspect

overriding this because the base Node class defines a ‘to_s’ method that needs to be honored



121
122
123
124
# File 'lib/undies/element.rb', line 121

def to_str(*args)
  "Undies::Element:#{self.object_id} " +
  "@name=#{@name.inspect}, @attrs=#{@attrs.inspect}"
end