simple firebase tree

A nested data tree with add/delete in Firebase and jQuery

by Kato Richardson

HTML

<script src="http://cdn.firebase.com/v0/firebase.js"></script>
   
<ul id="records"></ul>
<form><input type="text"><button>add</button></form>
    
<li id="recordTemplate"> 
    <span></span> <a href="#">X</a>
    <ul></ul>
    <form><input type="text"><button>add</button></form>
</li>
    
<!-- after parsing the records, they look like this 
     (the hash is stored in data-id):
<li data-id="-iZjYl...."> 
    <span>Title here</span> <a href="#">X</a>
    <ul>... children here... </ul>
    <form><input type="text"><button>add</button></form>
</li>
-->

CSS

form {
    display: block;
}

ul {
    border-top: 1px solid #eee;
    border-bottom: 1px solid #eee;
}

#recordTemplate { display: none; }

a {
  color: red;
  display: inline-block;
    padding: 2px;
    border: 1px solid #ddd;
}

a:hover {
   background-color: #ffc; 
}

JavaScript

var rootRef = new Firebase("https://kato-rp2.firebaseio-demo.com");

// delete record when a tag is clicked
jQuery('body').on('click', 'a', function() {
   var $rec = $(this).closest('[data-id]');
    var id = $rec.attr('data-id') || null;
    if( id ) {
       // remove any nested children
       $rec.find('[data-id]').each(function() {
          rootRef.child($(this).attr('data-id')).remove(); 
       });
       
       // remove the record
       rootRef.child(id).remove();
    }
    return false;
});

// add new records at the appropriate level when a button is clicked
jQuery('body').on('click', 'button', function () {
    var $input = $(this).prev('input');
    var title = $input.val();
    var parent = $input.closest('[data-id]').attr('data-id') || null;
    console.log('creating', parent, title);
    if (title) {
        rootRef.push({ 'title': title, 'parent': parent });
    }
    $input.val('');
    return false;
})

rootRef.on('child_added', function (snapshot) {
    var message = snapshot.val();
    console.log('child_added', message);
    displayTitleMessage(snapshot.name(), message.title, message.parent);
});

rootRef.on('child_removed', function(snapshot) {
    $('#records').find('[data-id="'+snapshot.name()+'"]').remove();
});

function displayTitleMessage(id, title, parentId) {
    var $parent = parentId ? findParent(parentId) : $('#records');
    var $el = makeListItem(title);
    console.log('displaying', id, parentId, $parent, title);
    // add a data-parent attribute, which we use to locate parent elements
    $el.appendTo($parent).attr('data-id', id);
}

function findParent(parentId) {
    return $('#records').find('[data-id="' + parentId + '"] > ul');
}

function makeListItem(title) {
    return $('#recordTemplate').clone()
    // remove the id attr
    .attr('id', null)
    // enter the <span> tag and use .text() to escape title
    .find('span').text(title)
    // navigate back to the cloned element and return it
    .end();
}