tree-traversal.js
function traverseBreadthFirst(rootNode, options) {
  options = extend({
    subnodesAccessor: function(node) { return node.subnodes; },
    userdataAccessor: function(node, userdata) { return userdata; },
    onNode: function(node, callback, userdata) { callback(); },
    onComplete: function(rootNode) {},
    userdata: null
  }, options);

  var queue = [];
  queue.push([rootNode, options.userdata]);

  (function next() {
    if (queue.length == 0) {
      options.onComplete(rootNode);
      return;
    }

    var front = queue.shift();
    var node = front[0];
    var data = front[1];

    options.onNode(node, function() {
      var subnodeData = options.userdataAccessor(node, data);
      var subnodes = options.subnodesAccessor(node);
      async.eachSeries(subnodes,
        function(subnode, nextNode) {
          queue.push([subnode, subnodeData]);
          async.setImmediate(nextNode);
        },
        function() {
          async.setImmediate(next);
        }
      );
    },
    data);
  })();
}
function traverseBreadthFirst(rootNode, options) {
  options = extend({
    subnodesAccessor: function(node) { return node.subnodes; },
    userdataAccessor: function(node, userdata) { return userdata; },
    onNode: function(node, callback, userdata) { callback(); },
    onComplete: function(rootNode) {},
    userdata: null
  }, options);

  var queue = [];
  queue.push([rootNode, options.userdata]);

  (function next() {
    if (queue.length == 0) {
      options.onComplete(rootNode);
      return;
    }

    var front = queue.shift();
    var node = front[0];
    var data = front[1];

    options.onNode(node, function() {
      var subnodeData = options.userdataAccessor(node, data);
      var subnodes = options.subnodesAccessor(node);
      async.eachSeries(subnodes,
        function(subnode, nextNode) {
          queue.push([subnode, subnodeData]);
          async.setImmediate(nextNode);
        },
        function() {
          async.setImmediate(next);
        }
      );
    },
    data);
  })();
}
function traverseBreadthFirst ( rootNode , options ) { options = extend ( { subnodesAccessor : function ( node ) { return node . subnodes ; } , userdataAccessor : function ( node , userdata ) { return userdata ; } , onNode : function ( node , callback , userdata ) { callback ( ) ; } , onComplete : function ( rootNode ) { } , userdata : null } , options ) ; var queue = [ ] ; queue . push ( [ rootNode , options . userdata ] ) ; ( function next ( ) { if ( queue . length == 0 ) { options . onComplete ( rootNode ) ; return ; } var front = queue . shift ( ) ; var node = front [ 0 ] ; var data = front [ 1 ] ; options . onNode ( node , function ( ) { var subnodeData = options . userdataAccessor ( node , data ) ; var subnodes = options . subnodesAccessor ( node ) ; async . eachSeries ( subnodes , function ( subnode , nextNode ) { queue . push ( [ subnode , subnodeData ] ) ; async . setImmediate ( nextNode ) ; } , function ( ) { async . setImmediate ( next ) ; } ) ; } , data ) ; } ) ( ) ; }
Asynchronously traverses the tree breadth first.
Asynchronously traverses the tree breadth first .