pakyow-presenter/lib/presenter/view.rb in pakyow-presenter-0.6.3.1 vs pakyow-presenter/lib/presenter/view.rb in pakyow-presenter-0.7.0
- old
+ new
@@ -1,24 +1,28 @@
module Pakyow
module Presenter
class View
class << self
- attr_accessor :binders, :cache, :default_view_path, :default_is_root_view
+ attr_accessor :binders, :default_view_path, :default_is_root_view
def view_path(dvp, dirv=false)
self.default_view_path = dvp
self.default_is_root_view = dirv
end
end
attr_accessor :doc
-
+
+ def dup
+ self.class.new(@doc.dup)
+ end
+
def initialize(arg=nil, is_root_view=false)
arg = self.class.default_view_path if arg.nil? && self.class.default_view_path
is_root_view = self.class.default_is_root_view if arg.nil? && self.class.default_is_root_view
- if arg.is_a?(Nokogiri::XML::Element)
+ if arg.is_a?(Nokogiri::XML::Element) || arg.is_a?(Nokogiri::XML::Document)
@doc = arg
elsif arg.is_a?(Pakyow::Presenter::Views)
@doc = arg.first.doc.dup
elsif arg.is_a?(Pakyow::Presenter::View)
@doc = arg.doc.dup
@@ -26,22 +30,15 @@
if arg[0, 1] == '/'
view_path = "#{Configuration::Presenter.view_dir}#{arg}"
else
view_path = "#{Configuration::Presenter.view_dir}/#{arg}"
end
- # Only load one time if view caching is enabled
- self.class.cache ||= {}
-
- if !self.class.cache.has_key?(view_path) || !Configuration::Base.presenter.view_caching
- if is_root_view then
- self.class.cache[view_path] = Nokogiri::HTML::Document.parse(File.read(view_path))
- else
- self.class.cache[view_path] = Nokogiri::HTML.fragment(File.read(view_path))
- end
+ if is_root_view then
+ @doc = Nokogiri::HTML::Document.parse(File.read(view_path))
+ else
+ @doc = Nokogiri::HTML.fragment(File.read(view_path))
end
-
- @doc = self.class.cache[view_path].dup
else
raise ArgumentError, "No View for you! Come back, one year."
end
end
@@ -89,12 +86,12 @@
def in_context(&block)
ViewContext.new(self).instance_eval(&block)
end
- def bind(object, type = nil)
- type = type || StringUtils.underscore(object.class.name)
+ def bind(object, opts = {})
+ bind_as = opts[:to] ? opts[:to].to_s : StringUtils.underscore(object.class.name.split('::').last)
@doc.traverse do |o|
if attribute = o.get_attribute('itemprop')
selector = attribute
elsif attribute = o.get_attribute('name')
@@ -103,36 +100,30 @@
next
end
next unless attribute
- if selector.include?('[')
- type_len = type.length
- object_type = selector[0,type_len]
- attribute = selector[type_len + 1, attribute.length - type_len - 2]
- else
- object_type = nil
- attribute = selector
- end
+ type_len = bind_as.length
+ next if selector[0, type_len + 1] != "#{bind_as}["
- next if !object_type.nil? && object_type != type
+ attribute = selector[type_len + 1, attribute.length - type_len - 2]
binding = {
:element => o,
:attribute => attribute.to_sym,
:selector => selector
}
- bind_object_to_binding(object, binding, object_type.nil?)
+ bind_object_to_binding(object, binding, bind_as)
end
end
- def repeat_for(objects, &block)
+ def repeat_for(objects, opts = {}, &block)
if o = @doc
objects.each do |object|
view = View.new(self)
- view.bind(object)
+ view.bind(object, opts)
ViewContext.new(view).instance_exec(object, &block) if block_given?
o.add_previous_sibling(view.doc)
end
@@ -237,36 +228,28 @@
def append(content)
self.doc.add_child(Nokogiri::HTML.fragment(content.to_s))
end
alias :render :append
-
- def +(value)
- if @previous_method
- append_value(val)
- else
- super
- end
- end
-
- def <<(value)
- if @previous_method
- append_value(val)
- else
- super
- end
- end
-
+
def method_missing(method, *args)
return unless @previous_method == :attributes
@previous_method = nil
if method.to_s.include?('=')
attribute = method.to_s.gsub('=', '')
value = args[0]
- self.doc[attribute] = value
+ if value.is_a? Proc
+ value = value.call(self.doc[attribute])
+ end
+
+ if value.nil?
+ self.doc.remove_attribute(attribute)
+ else
+ self.doc[attribute] = value
+ end
else
return self.doc[method.to_s]
end
end
@@ -296,47 +279,41 @@
elements
end
protected
- def append_value(value_to_append)
- case @previous_method
- when :content
- append(value_to_append)
- end
-
- @previous_method = nil
- end
-
- def bind_object_to_binding(object, binding, wild = false)
+ def bind_object_to_binding(object, binding, bind_as)
binder = nil
- # fetch value
- if object.is_a? Hash
- value = object[binding[:attribute]]
+ if View.binders
+ b = View.binders[bind_as.to_sym] and binder = b.new(object, binding[:element])
+ end
+
+ if binder && binder.class.method_defined?(binding[:attribute])
+ value = binder.send(binding[:attribute])
else
- if View.binders
- b = View.binders[object.class.to_s.to_sym] and binder = b.new(object, binding[:element])
- end
-
- if binder && binder.class.method_defined?(binding[:attribute])
- value = binder.send(binding[:attribute])
+ if object.is_a? Hash
+ value = object[binding[:attribute]]
else
- if wild && !object.class.method_defined?(binding[:attribute])
- return
- elsif Configuration::Base.app.dev_mode == true && !object.class.method_defined?(binding[:attribute])
+ if Configuration::Base.app.dev_mode == true && !object.class.method_defined?(binding[:attribute])
Log.warn("Attempting to bind object to #{binding[:html_tag]}#{binding[:selector].gsub('*', '').gsub('\'', '')} but #{object.class.name}##{binding[:attribute]} is not defined.")
return
else
value = object.send(binding[:attribute])
end
end
end
if value.is_a? Hash
value.each do |k, v|
- if k == :content
+ if v.is_a? Proc
+ v = v.call(binding[:element][k.to_s])
+ end
+
+ if v.nil?
+ binding[:element].remove_attribute(k.to_s)
+ elsif k == :content
bind_value_to_binding(v, binding, binder)
else
binding[:element][k.to_s] = v.to_s
end
end
@@ -380,10 +357,10 @@
end
else
binding[:element].inner_html = Nokogiri::HTML.fragment(value.to_s)
end
elsif binding[:element].name == 'input' && binding[:element][:type] == 'checkbox'
- if value == true || binding[:element].attributes['value'].value == value.to_s
+ if value == true || (binding[:element].attributes['value'] && binding[:element].attributes['value'].value == value.to_s)
binding[:element]['checked'] = 'checked'
else
binding[:element].delete('checked')
end
elsif binding[:element].name == 'input' && binding[:element][:type] == 'radio'