pakyow-presenter/lib/presenter/view_collection.rb in pakyow-presenter-0.8.0 vs pakyow-presenter/lib/presenter/view_collection.rb in pakyow-presenter-0.9.0
- old
+ new
@@ -1,143 +1,116 @@
module Pakyow
module Presenter
class ViewCollection
include Enumerable
- attr_accessor :context, :composer
-
def initialize
@views = []
end
def each
@views.each { |v| yield(v) }
end
- def attributes(attrs = {})
- collection = AttributesCollection.new
- self.each{|v| collection << v.attributes(attrs)}
- return collection
+ def attrs(attrs = {})
+ inject(AttributesCollection.new) { |coll, view|
+ coll << view.attrs(attrs)
+ }
end
- alias :attrs :attributes
-
def remove
- self.each {|e| e.remove}
+ each {|e| e.remove}
end
- alias :delete :remove
-
- # SEE COMMENT IN VIEW
- # def add_class(val)
- # self.each {|e| e.add_class(val)}
- # end
-
- # SEE COMMENT IN VIEW
- # def remove_class(val)
- # self.each {|e| e.remove_class(val)}
- # end
-
def clear
- self.each {|e| e.clear}
+ each {|e| e.clear}
end
def text
- self.map { |v| v.text }
+ map { |v| v.text }
end
def text=(text)
- self.each {|e| e.text = text}
+ each {|e| e.text = text}
end
def html
- self.map { |v| v.html }
+ map { |v| v.html }
end
def html=(html)
- self.each {|e| e.html = html}
+ each {|e| e.html = html}
end
def to_html
- self.map { |v| v.to_html }.join('')
+ map { |v| v.to_html }.join('')
end
alias :to_s :to_html
def append(content)
- self.each {|e| e.append(content)}
+ each do |view|
+ view.append(content)
+ end
end
- alias :render :append
-
def prepend(content)
- self.each {|e| e.prepend(content)}
+ each do |view|
+ view.prepend(content)
+ end
end
def <<(val)
if val.is_a? View
@views << val
end
+
+ self
end
def concat(views)
@views.concat(views)
end
def [](i)
- view = @views[i]
- return if view.nil?
-
- view.context = @context
- view.composer = @composer
- return view
+ @views[i]
end
def length
@views.length
end
def scope(name)
- views = ViewCollection.new
- views.context = @context
- views.composer = @composer
- self.each{|v|
- next unless svs = v.scope(name)
- svs.each{ |sv|
- sv.context = @context
- sv.composer = @composer
- views << sv
+ inject(ViewCollection.new) { |coll, view|
+ scopes = view.scope(name)
+ next if scopes.nil?
+
+ scopes.inject(coll) { |coll, scoped_view|
+ coll << scoped_view
}
}
-
- views
end
def prop(name)
- views = ViewCollection.new
- views.context = @context
- views.composer = @composer
- self.each{|v|
- next unless svs = v.prop(name)
- svs.each{ |sv|
- sv.context = @context
- sv.composer = @composer
- views << sv
+ inject(ViewCollection.new) { |coll, view|
+ scopes = view.prop(name)
+ next if scopes.nil?
+
+ scopes.inject(coll) { |coll, scoped_view|
+ coll << scoped_view
}
}
-
- views
end
# call-seq:
# with {|view| block}
#
# Creates a context in which view manipulations can be performed.
#
def with(&block)
if block.arity == 0
- self.instance_exec(&block)
+ instance_exec(&block)
else
yield(self)
end
self
@@ -151,22 +124,21 @@
# means the block will be yielded self.length times.
#
# (this is basically Bret's `map` function)
#
def for(data, &block)
- data = data.to_a if data.is_a?(Enumerator)
- data = [data] if (!data.is_a?(Enumerable) || data.is_a?(Hash))
+ data = Array.ensure(data)
+ each_with_index do |view, i|
+ datum = data[i]
+ break if datum.nil?
- self.each_with_index { |v,i|
- break unless datum = data[i]
-
if block.arity == 1
- v.instance_exec(data[i], &block)
+ view.instance_exec(data[i], &block)
else
- block.call(v, data[i])
+ block.call(view, data[i])
end
- }
+ end
end
# call-seq:
# for_with_index {|view, datum, i| block}
#
@@ -188,96 +160,82 @@
end
# call-seq:
# match(data) => ViewCollection
#
- # Returns a ViewCollection object that has been manipulated to match the data.
- # For the ViewCollection case, the returned ViewCollection collection will consist n copies
- # of self[data index] || self[-1], where n = data.length.
+ # Manipulates the current collection to match the data. The final ViewCollection object
+ # will consist n copies of self[data index] || self[-1], where n = data.length.
#
def match(data)
- data = data.to_a if data.is_a?(Enumerator)
- data = [data] if (!data.is_a?(Enumerable) || data.is_a?(Hash))
+ data = Array.ensure(data)
- views = ViewCollection.new
- views.context = @context
- views.composer = @composer
- data.each_with_index {|datum,i|
- unless v = self[i]
+ # an empty set always means an empty view
+ if data.empty?
+ remove
+ else
+ original_view = self[-1].soft_copy if data.length > length
- # we're out of views, so use the last one
- v = self[-1]
+ if length > data.length
+ self[data.length..-1].each do |view|
+ view.remove
+ end
+ else
+ data[length..-1].each do
+ duped_view = original_view.soft_copy
+ self[-1].after(duped_view)
+ self << duped_view
+ end
end
+ end
- d_v = v.doc.dup
- v.doc.before(d_v)
- v.invalidate!(true)
-
- new_v = View.from_doc(d_v)
-
- # find binding subset (keeps us from refinding)
- new_v.bindings = v.bindings.dup
- new_v.scoped_as = v.scoped_as
- new_v.context = @context
- new_v.composer = @composer
-
- views << new_v
- }
-
- # do not use self.remove since that refinds bindings
- self.each {|v|
- next if v.doc.parent.nil?
- v.doc.remove
- }
-
- views
+ self
end
# call-seq:
# repeat(data) {|view, datum| block}
#
# Matches self to data and yields a view/datum pair.
#
def repeat(data, &block)
- self.match(data).for(data, &block)
+ match(data).for(data, &block)
end
# call-seq:
# repeat_with_index(data) {|view, datum, i| block}
#
# Matches self with data and yields a view/datum pair with index.
#
def repeat_with_index(data, &block)
- self.match(data).for_with_index(data, &block)
+ match(data).for_with_index(data, &block)
end
# call-seq:
# bind(data)
#
# Binds data across existing scopes.
#
- def bind(data, bindings = {}, &block)
- self.for(data) {|view, datum|
- view.bind(datum, bindings)
+ def bind(data, bindings: {}, context: nil, &block)
+ self.for(data) do |view, datum|
+ view.bind(datum, bindings: bindings, context: context)
next if block.nil?
if block.arity == 1
view.instance_exec(datum, &block)
else
block.call(view, datum)
end
- }
+ end
end
# call-seq:
# bind_with_index(data)
#
# Binds data across existing scopes, yielding a view/datum pair with index.
#
- def bind_with_index(data, bindings = {}, &block)
+ def bind_with_index(*a, **k, &block)
i = 0
- self.bind(data) do |ctx, datum|
+ bind(*a, **k) do |ctx, datum|
if block.arity == 2
ctx.instance_exec(datum, i, &block)
else
block.call(ctx, datum, i)
end
@@ -289,11 +247,11 @@
# call-seq:
# apply(data)
#
# Matches self to data then binds data to the view.
#
- def apply(data, bindings = {}, &block)
- self.match(data).bind(data, bindings, &block)
+ def apply(data, bindings: {}, context: nil, &block)
+ match(data).bind(data, bindings: bindings, context: context, &block)
end
end
end
end