Sorted Collections - SortedArrayController in Ember.js
Problem
Need a collection of objects that always render in a sorted order and not the insert order. For example showing events ordered on timestamp.
Update: added maximum size so it will always trim the collection to a running set of n latest items.
Solution
I created this small extension to ember that will keep the collection always sorted (based on a sortFunction or default sort order). It also supports reverse order and random order. The code is in coffeescript but you can convert it to javascript via this tool.
Ember.SortedArrayController = Ember.ArrayController.extend(
sortOrder: "normal"
sortFunction: null
inputCollectionName: "content"
outputCollectionName: "content"
maxCollectionSize: -1
init: ->
@set(@inputCollectionName, [])
@addObserver(@inputCollectionName + '.@each', -> @elementAdded())
@addObserver(@outputCollectionName + '.@each', -> @trimArray())
elementAdded: (->
context = @
content = @get(@inputCollectionName)
if @sortOrder == "normal"
if @sortFunction? then content.sort((a,b)-> context.sortFunction(a,b)) else content.sort()
else if @sortOrder == "reverse"
if @sortFunction? then content.sort((a,b)-> context.sortFunction(b,a)) else content.reverse()
else if @sortOrder == "random"
content.sort((a,b)-> 0.5 - Math.random("deadbeef"))
@set(@outputCollectionName, content)
)
trimArray: (->
content = @get(@outputCollectionName)
@set(@outputCollectionName, content.slice(0, @maxCollectionSize-1))if (@maxCollectionSize > 0) and (content.length > @maxCollectionSize)
)
)
window.myArray = Ember.SortedArrayController.create()
myArray.content.pushObjects(["Jack", "Cassandra", "Raj"])
window.myArray2 = Ember.SortedArrayController.create({sortOrder: "reverse"})
myArray2.content.pushObjects(["Jack", "Cassandra", "Raj"])
window.myArray3 = Ember.SortedArrayController.create({sortOrder: "random"})
myArray3.content.pushObjects(["Jack", "Cassandra", "Raj"])
you will get the following results:
myArray.content
["Cassandra", "Jack", "Raj"]
myArray2.content
["Raj", "Cassandra", "Jack"]
myArray3.content
["Jack", "Raj", "Cassandra"]Written by Bashir Eghbali
Related protips
1 Response
I made a gist out of the js / non-coffeescript version: https://gist.github.com/chrisjlee/31d1ea4f7cd90517b2d8
Have a fresh tip? Share with Coderwall community!
JavaScript on a page runs with the privileges of that origin. One altered library, tag manager, or snippet can read inputs, change what people see, and call your APIs as the user.
Security insights from Cside