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