Core libraries and tools part for pro architecture. It's a submodule - use from this perspective http://git.maniak.pro/madmaniak/pro
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

131 lines
3.7 KiB

class global.Collection
@list: {}
constructor: (@scope = [], @params = {}, @belongs_to) ->
@v = 0
Dispatcher.on "#{@constructor.base}_change", @change
unless @belongs_to
# root in Store
@belongs_to = id: 1, type: @constructor.path
@belongs_to[@constructor.base] = @
Store.collections[@constructor.path] = 1: @belongs_to
load: -> @go {}, (scope) => @scope = scope
elements: ->
if @_v == @v
then @_collection
else @_v = @v; @_collection = Store.get @constructor.base, @scope
add: (object, relations = []) ->
Store.add @constructor.base, object, relations.concat @belongs_to
render()
add_id: (id) ->
@scope.push(id); @v++
i = @reorder(@scope.length - 1)
object = @_object(id)
L.wait_for_real_id [object], =>
if @scope[i] != id
i = @index_of(object, id)
@scope.splice(i, true, object.id); @v++
@_create_relations(id)
_create_relations: (id) ->
object = @_object(id)
L.each @constructor.relations, (ns, relation) ->
if !object[relation] or L.isArray object[relation]
object[relation] = new Collection.list[ns](object[relation], {}, object)
change: (id) =>
if object = @_object(id)
# still exists?
# id in scope?
if (i = @index_of(object)) != -1
then @reorder(i)
else @scope.splice(i, 1); @v++
else
# don't exist at all?
# was in scope?
if (i = L.indexOf(@scope, id)) != -1
@scope.splice(i, 1); @v++
reorder: (i) ->
c = @elements()
if direction = @_direction c[i-1], c[i], c[i+1]
# wrong order?
split = i + direction
destination =
if direction < 0
then @proper_index(c[i], c, 0, split-1)
else i + @proper_index(c[i], c, split)
@move i, destination
destination || i
# which way unsorted element should go
_direction: (left, object, right) ->
if right and @compare(object, right) then 1
else if left and @compare(left, object) then -1
else 0
move: (from, to) ->
@scope.splice to, 0, @scope.splice(from, 1)[0]; @v++
# is a >= b considering [attribute, boolean:descending]?
compare: (a, b) ->
for order in @constructor.order
return !order[1] if a[order[0]] > b[order[0]]
return order[1] if a[order[0]] < b[order[0]]
return !order[1] if L.isString(a[order[0]]) && L.isInteger(b[order[0]])
return order[1] if L.isString(b[order[0]]) && L.isInteger(a[order[0]])
true
# binary search for proper index
proper_index: (object, collection, left, right) ->
collection ||= @elements()
l = left || 0
r = right || collection.length - 1
m = H.half_way(l, r)
while true
return l if @compare(collection[l], object)
return r+1 if @compare(object, collection[r])
if @compare(collection[m], object)
then r = m - 1
else l = m + 1
m = H.half_way(l, r)
index_of: (object, id = object.id) ->
i = @proper_index object
return i if @scope[i] == id
j = 1
while (i2 = i+j) < @scope.length
return i2 if @scope[i2] == id or @scope[i-j] == id
j++
while (i2 = i-j) >= 0
return i2 if @scope[i2] == id
j++
-1
_object: (id) -> Store.get(@constructor.base, id)[0]
go: (params, scope_f) ->
@done = false
query = L.merge(params, @params)
rk = @constructor.path + L.stringify(query)
Dispatcher.once Requests.perform(@constructor.path, query), (reply) =>
# Cache.set rk, reply.raw
scope_f?.call(@, reply.scope); @v++
if @constructor.relations
L.each Store.get(@constructor.base, reply.scope), (object) =>
@_create_relations(object.id)
@done = true
@
H =
half_way: (l, r) ->
l + Math.floor (r - l)/2
require './static'
require './dynamic'