Permalink
Browse files

implemented o_O.list (set) per issue #28

  • Loading branch information...
1 parent 247cdce commit 8c602fd95a0c35d00f06546f735d38851d7cbe8f @troygoode committed Mar 31, 2012
Showing with 190 additions and 1 deletion.
  1. +109 −1 o_O.js
  2. +1 −0 test/mocha.html
  3. +80 −0 test/test.list.js
View
@@ -712,7 +712,115 @@ o_O.model = model
\___/___\___(_)_|_|___/\__|
|_____| */
-//TODO: implement o_O.list()
+function list(models) {
+ if(this.constructor != list) return new list(models)
+
+ this.objects = {}
+ this.count = o_O(0)
+
+ eventize(this)
+ if(models) {
+ for(var i=0; i< models.length;i++) {
+ this.add(models[i])
+ }
+ }
+}
+
+var proto = list.prototype
+
+proto.genId = function() {
+ return ++this.genId.id
+}
+proto.genId.id = 0
+
+proto.add = function(o) {
+ o.id = o.id || this.genId()
+ this.objects[o.id] = o
+
+ o.list = this
+
+ if(o.on) {
+ o.on('*', this._onevent, this)
+ o.emit('add', o, this)
+ }
+ else
+ this.emit('add', o)
+
+ this.count.incr()
+}
+
+proto._onevent = function(ev, o, list) {
+ if ((ev == 'add' || ev == 'remove') && list != this) return
+ if (ev == 'destroy') {
+ this.remove(o)
+ }
+ this.emit.apply(this, arguments)
+}
+
+proto.filter = function(fn) {
+ var ret = [];
+ this.each(function(o) {
+ if(fn(o)) ret.push(o)
+ })
+ return ret
+}
+
+proto.find = function(i) {
+ return this.objects[i]
+}
+
+proto.each = proto.forEach = function(fn) {
+ this.count(); // force the dependency
+ for(var i in this.objects)
+ fn.call(this, this.find(i), i)
+}
+
+proto.remove = function(o) {
+ if(undefined === this.objects[o.id])
+ return
+ delete this.objects[o.id]
+ this.count.incr(-1)
+
+ if(this == o.list) delete o.list
+ if(o.off) {
+ o.emit('remove', o, this)
+ o.off('all', this._onevent, this)
+ }else{
+ this.emit('remove', o)
+ }
+}
+
+proto.renderOne = function(item, $el) {
+ $(getTemplate($el)).each(function(i, elem) {
+ var $$ = $(elem)
+ $$.appendTo($el)
+ o_O.bind(item, $$)
+ })
+}
+
+proto.bind = function($el) {
+ var self = this
+
+ this.on('add', function(item) {
+ self.renderOne(item, $el)
+ })
+
+ this.on('remove', this.removeElement, this)
+}
+
+proto.removeElement = function(item) {
+ $(item.el).remove()
+}
+
+proto.toString = function() {
+ return '#<list>'
+}
+
+proto.extend = function() {
+ return inherits(this)
+}
+
+o_O.list = list
/* ___
___ / _ \ __ _ _ __ _ __ __ _ _ _
View
@@ -18,6 +18,7 @@
<script src="test.conditionals.js"></script>
<script src="test.eventize.js"></script>
<script src="test.expressions.js"></script>
+ <script src="test.list.js"></script>
<script src="test.model.js"></script>
<script src="test.property.js"></script>
View
@@ -0,0 +1,80 @@
+expect = global.expect || require('expect.js')
+o_O = global.o_O || require('../o_O')
+
+describe('a list', function() {
+ var col
+
+ beforeEach(function() {
+ col = o_O.list()
+ })
+
+ it('has a count of 0', function() {
+ expect(col.count()).to.be(0)
+ })
+
+ describe('adding/removing', function() {
+ var obj
+ beforeEach(function() {
+ obj = {}
+ col.add(obj)
+ })
+
+ it('has a count of 1', function() {
+ expect(col.count()).to.be(1)
+ })
+
+ it('handles the removal of an item it doesn\'t have gracefully', function() {
+ col.remove({foo: 'bar'})
+ expect(col.count()).to.be(1)
+ })
+
+ it('increases count after add', function() {
+ expect(col.count()).to.be(1)
+ })
+
+ it('triggers the *add* event after add', function() {
+ var eventTriggered = false
+ col.on('add', function(){
+ eventTriggered = true
+ })
+
+ var obj2 = {}
+ col.add(obj2)
+
+ expect(eventTriggered).to.be(true)
+
+ // cleanup
+ col.remove(obj2)
+ })
+
+ it('decreases count after remove', function() {
+ col.remove(obj)
+ expect(col.count()).to.be(0)
+ })
+
+ it('triggers the *remove* event after remove', function() {
+ var eventTriggered = false
+ col.on('remove', function(){
+ eventTriggered = true
+ })
+
+ col.remove(obj)
+
+ expect(eventTriggered).to.be(true)
+ })
+
+ it('triggers the *remove* event after remove (on model)', function() {
+ var M = o_O.model({age: 1})
+ var m = new M({age:2})
+ var eventTriggered = false
+ col.on('remove', function(){
+ eventTriggered = true
+ })
+
+ col.add(m)
+ col.remove(m)
+
+ expect(eventTriggered).to.be(true)
+ })
+ })
+})

0 comments on commit 8c602fd

Please sign in to comment.