Permalink
Browse files

added collection filtering/grouping

  • Loading branch information...
1 parent 3f94672 commit 7ef337f3d45a20fe4896331f8ec59f720ebf3f50 @collin committed Apr 13, 2012
@@ -0,0 +1,54 @@
+AS = require "alpha_simprini"
+_ = require "underscore"
+knead = require "knead"
+
+AS.Views.Dialog = AS.Views.Panel.extend ({delegate, include, def, defs}) ->
+ def initialize: ->
+ @constructor::events ?= {}
+ _.extend @constructor::events,
+ "click .accept": "trigger_commit"
+ "click .cancel": "trigger_cancel"
+ "esc @application": "trigger_cancel"
+ "accept @application": "trigger_commit"
+
+ "knead:dragstart header": "dragstart"
+ "knead:drag header": "drag"
+ "knead:dragend header": "dragend"
+
+ @_super.apply(this, arguments)
+
+ @head = @$ @header @header_content
+ @content = @$ @section @main_content
+ @foot = @$ @footer @footer_content
+ knead.monitor @head
+
+ def header_content: ->
+ def main_content: ->
+ def footer_content: ->
+ @accept = @$ @button class:"accept", -> "Accept"
+ @cancel = @$ @a href:"#", class:"cancel", -> "cancel"
+
+ def open: ->
+ @el.css width: "", height: ""
+ @trigger "open"
+
+ def close: ->
+ @el.css width: 0, height: 0, overflow: "hidden"
+ @trigger "close"
+
+ def trigger_commit: ->
+ @trigger "commit"
+ @close()
+
+ def trigger_cancel: ->
+ @trigger "cancel"
+ @close()
+
+ def dragstart: (event) ->
+ @start = @el.position()
+ def drag: (event) ->
+ @el.css
+ top: event.deltaY + @start.top
+ left: event.deltaX + @start.left
+ def dragend: (event) ->
+ delete @start
@@ -10,9 +10,10 @@ Core.require """
properties/field properties/has_many properties/has_one properties/virtual_property
properties/embeds_many properties/embeds_one properties/belongs_to
- collection
+ collection filtered_collection
models/radio_selection_model models/multiple_selection_model
+ models/group models/grouping
"""
# model/share
@@ -81,6 +81,12 @@ AS.Collection = AS.Object.extend ({def, include, delegate}) ->
event: "all"
namespace: @objectId()
+ def filter: (fn) ->
+ AS.FilteredCollection.new(this, fn)
+
+ def groupBy: (key) ->
+ AS.Models.Grouping.new(this, key)
+
# # When an event is triggered from a model, it is bubbled up through the collection.
def _onModelEvent: (event, model, collection, options) ->
return unless isString(event)
@@ -0,0 +1,58 @@
+# How would you implement this such that the @parent/@filter property could be changed?
+#
+# perhaps.. something like this?
+#
+# @property "parent"
+# @property "filter"
+
+# @virtualProperty "parent", "filter",
+# models:
+# get: ->
+# set: ->
+# add: ->
+# remove: ->
+AS = require "alpha_simprini"
+{extend, isString} = require "underscore"
+
+AS.FilteredCollection = AS.Collection.extend ({delegate, include, def, defs}) ->
+ delegate 'add', 'remove', to: 'parent'
+
+ def initialize: (@parent, @filter=(-> true)) ->
+ @_super()
+ @parent.bind
+ event: 'add'
+ handler: @addToSelf
+ context: this
+ namespace: @objectId()
+
+ @parent.bind
+ event: 'remove'
+ handler: @removeFromSelf
+ context: this
+ namespace: @objectId()
+
+ @parent.each (model) -> @addToSelf(model)
+
+ def determinePlacementInSelf: (model) ->
+ if @filter(model) is true
+ @addToSelf(model)
+ else
+ @removeFromSelf(model)
+
+ def addToSelf: (model) ->
+ model.unbind "." + @objectId()
+
+ model.bind
+ event: "change"
+ handler: @determinePlacementInSelf
+ namespace: @objectId()
+ context: this
+
+ return unless @filter(model) is true
+ @_add(model)
+
+ def removeFromSelf: (model) ->
+ model.unbind "." + @objectId()
+ return unless @models.indexOf(model)
+ @_remove(model)
+
@@ -0,0 +1,7 @@
+AS = require "alpha_simprini"
+
+AS.Models.Group = AS.Model.extend ({delegate, include, def, defs}) ->
+ @field "name"
+ @hasMany "members"
+
+ @virtualProperties 'members', membersCount: -> @members.backingCollection.length
@@ -0,0 +1,51 @@
+AS = require "alpha_simprini"
+AS.Models.Grouping = AS.Model.extend ({delegate, include, def, defs}) ->
+ @hasMany 'groups'
+
+ def initialize: (@backingCollection, @groupByProperty) ->
+ @groupMap = AS.Map.new()
+ # TODO: send newvalue/oldvalue when triggering field changes ;)
+ # that way an itemMap isn't neccessary.
+ @itemMap = AS.Map.new()
+
+ @backingCollection.bind
+ event: "add"
+ handler: @addToGroup
+ context: this
+
+ @backingCollection.bind
+ event: "remove"
+ handler: @removeFromGroup
+ context: this
+
+ @backingCollection.bind
+ event: "change:#{@groupByProperty}"
+ handler: @determineNewGroup
+ context: this
+
+ @backingCollection.each (item) -> @addToGroup(item)
+
+ def addToGroup: (item) ->
+ name = item[@groupByProperty].get()
+ unless group = @groupMap.get(name)
+ group = AS.Models.Group.new(name: name)
+ @groupMap.set(name, group)
+
+ @itemMap.set item, group
+ group.members.add(item)
+
+ def removeFromGroup: (item) ->
+ return unless group = @itemMap.get(item)
+ group.members.remove(item)
+
+ def determineNewGroup: (item) ->
+ @removeFromGroup(item)
+ @addToGroup(item)
+
+# @currentUser.labors.groupBy "endDateGroup", (group) ->
+# @text group.name
+# @text "(" ;@group.binding "membersCount"; @text ")"
+
+# group.members.groupBy 'orgName', (group) ->
+# group.binding "name"
+# @text "("; @group.binding "membersCount"; @text ")"
@@ -0,0 +1,90 @@
+{AS, _, sinon, coreSetUp} = require require("path").resolve("./test/helper")
+exports.setUp = coreSetUp
+
+C = AS.Namespace.new("Collections")
+
+C.Model = AS.Model.extend ({delegate, include, def, defs}) ->
+ @field "truth", type: Boolean, default: false
+
+C.Collection = AS.Collection.extend ({delegate, include, def, defs}) ->
+
+exports.FilteredCollection =
+ "by default, all members are in the filtered collection": (test) ->
+ c = C.Collection.new()
+ f = c.filter()
+
+ one = c.add C.Model.new()
+ two = c.add C.Model.new()
+ three = c.add C.Model.new()
+
+ test.deepEqual [one, two, three], f.models.value()
+ test.done()
+
+ "removes items from filter when they are removed from collection": (test) ->
+ c = C.Collection.new()
+ f = c.filter()
+
+ one = c.add C.Model.new()
+ two = c.add C.Model.new()
+ three = c.add C.Model.new()
+
+ c.remove(two)
+
+ test.deepEqual [one, three], f.models.value()
+ test.done()
+
+ "respects filter function when adding models": (test) ->
+ c = C.Collection.new()
+ f = c.filter (model) -> model.truth.get() is false
+
+ one = c.add C.Model.new()
+ two = c.add C.Model.new(truth: true)
+ three = c.add C.Model.new()
+
+ test.deepEqual [one, three], f.models.value()
+ test.done()
+
+ "add filtered items when they change": (test) ->
+ c = C.Collection.new()
+ f = c.filter (model) -> model.truth.get() is false
+
+ one = c.add C.Model.new()
+ two = c.add C.Model.new(truth: true)
+ three = c.add C.Model.new()
+
+ two.truth.set(false)
+
+ test.deepEqual [one, three, two], f.models.value()
+ test.done()
+
+ "remove filtered items when they change": (test) ->
+ c = C.Collection.new()
+ f = c.filter (model) -> model.truth.get() is false
+
+ one = c.add C.Model.new()
+ two = c.add C.Model.new()
+ three = c.add C.Model.new()
+
+ two.truth.set(true)
+
+ test.deepEqual [one, three], f.models.value()
+ test.done()
+
+ "triggers add/remove events": (test) ->
+ test.expect 4
+
+ c = C.Collection.new()
+ f = c.filter (model) -> model.truth.get() is false
+
+ f.bind "add", (model) -> test.ok(model)
+
+ one = c.add C.Model.new()
+ two = c.add C.Model.new(truth: true)
+ three = c.add C.Model.new()
+
+ two.truth.set(false)
+ two.truth.set(true)
+
+ test.deepEqual [one, three], f.models.value()
+ test.done()
+
@@ -0,0 +1,43 @@
+{AS, _, sinon, coreSetUp} = require require("path").resolve("./test/helper")
+exports.setUp = coreSetUp
+
+G = AS.Namespace.new("Grouping")
+
+G.Model = AS.Model.extend ({delegate, include, def, defs}) ->
+ @field "point", default: "default"
+
+G.Collection = AS.Collection.extend ({delegate, include, def, defs}) ->
+ model: -> G.Model
+
+exports["Models.Grouping"] =
+ setUp: (callback) ->
+ @c = G.Collection.new()
+ @g = @c.groupBy("point")
+ callback()
+
+ "adds item to a group": (test) ->
+ @c.add G.Model.new()
+ @c.add G.Model.new()
+
+ test.equal 2, @g.groupMap.get("default").membersCount.get()
+
+ test.done()
+
+ "removes items from their gorup": (test) ->
+ @c.add G.Model.new()
+ item = @c.add G.Model.new()
+ @c.remove(item)
+
+ test.equal 1, @g.groupMap.get("default").membersCount.get()
+
+ test.done()
+
+ "moves items inbetween groups": (test) ->
+ @c.add G.Model.new()
+ item = @c.add G.Model.new()
+ item.point.set("alternate")
+
+ test.equal 1, @g.groupMap.get("default").membersCount.get()
+ test.equal 1, @g.groupMap.get("alternate").membersCount.get()
+
+ test.done()

0 comments on commit 7ef337f

Please sign in to comment.