Skip to content

Instantly share code, notes, and snippets.

@marshallswain
Created December 23, 2013 08:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marshallswain/8093413 to your computer and use it in GitHub Desktop.
Save marshallswain/8093413 to your computer and use it in GitHub Desktop.
Firebase CanJS LIst Controller
var FirebaseListController = can.Control.extend({
defaults: {
// The main Firebase URL, including the trailing slash.
baseURL: 'https://bchm.firebaseIO.com/',
// The location of the list of data in Firebase.
location: "test_list",
// The HTML attribute that should be added to a template element in the list.
// It will need to be unique and will contain a single value, like an id, not a class.
// unused because I can't get can.Mustache to work with it right now. Keeps printing __!!__
// firebaseKeyName: "data-firebasekey",
// The HTML tag that will contain the data-firebasekey attribute.
tag: "tr",
// Each can.Map in the list will be available at can.data('firebaseData') unless
// this is changed.
firebaseDataKey:"firebaseData",
// The name of the can.List
listName: "list"
}
},{
'init': function(element){
var self = this;
self.newItems = false;
// Create empty list to populate.
self.options.list = new can.List();
window.ListMe = self.options.list;
// Build a firebaseURL out of the baseURL and location.
self.options.firebaseURL = self.options.baseURL + self.options.location;
// Get items from Firebase.
self.firebaseRef = new Firebase(self.options.firebaseURL);
// TODO: Use prevChildName for proper sorting.
// Upon Firebase child_added, push the child to the can.List.
self.firebaseRef.on('child_added', function(snapshot, prevChildName){
if (!self.newItems) return;
// Get the data from the Firebase snapshot.
var data = snapshot.val();
// Add the firebasekey to the data so template has access to it.
data.firebasekey = snapshot.name();
// Add each child_added to the user list.
self.options.list.push(data);
}, function(error){console.log(error)});
self.firebaseRef.once('value', function(snapshot, prevChildName){
// This keeps 'child_added' from firing until the initial 'value' is done.
self.newItems = true;
// Prepare an array to push into self.options.list all at once.
// It's faster to set an array into a can.List than it is to use can.List.push(item)
var dataArray = new Array();
snapshot.forEach(function(childSnapshot) {
data = childSnapshot.val();
data.firebasekey = childSnapshot.name();
// Add to the array.
dataArray.push(data);
});
// Set array into the can.List.
self.options.list.attr(dataArray);
}, function(error){console.log(error)});
self.addListeners();
},
// Add other listeners after the inital data has loaded.
'addListeners': function(){
var self = this;
// Upon Firebase child_changed, update the changes to the corresponding can.Map.
self.firebaseRef.on('child_changed', function(snapshot, prevChildName){
var data = snapshot.val();
data.firebasekey = snapshot.name();
// Find the matching element / data
var query = self.options.tag+'[data-firebasekey="'+ data.firebasekey +'"]';
var item = self.element.find(query).data("firebaseData");
// Overwrite all data in the can.Map.
item.attr(data, true);
});
// Upon Firebase child_removed, remove from the can.List.
self.firebaseRef.on('child_removed', function(snapshot, prevChildName){
var data = snapshot.val();
// Find the matching element / data
var query = self.options.tag+'[data-firebasekey="'+ snapshot.name() +'"]';
var item = self.element.find(query).data("firebaseData");
// Remove the item from the list.
var position = self.options.list.indexOf(item);
self.options.list.splice(position, 1);
});
// Upon adding to the can.List, add it to Firebase.
self.options.list.bind('add', function(ev, newElement, index) {
// console.log(ev, newElements, index);
// var newRef = new Firebase(self.options.firebaseURL).push();
// if (newElements != undefined) {
// console.log(newElement);
// newElement.attr('name', "moose");
// newRef.set(data);
// };
});
// Upon editing a can.List item, update Firebase.
self.options.list.bind('change', function(ev, index, how, newVal, oldVal) {
// console.log(ev + ', ' + index + ', ' + how + ', ' + newVal + ', ' + oldVal);
});
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment