'use strict';
/* @module traversal */
/**
* @class Recursive traversal callback for a given node at a given depth.
* @author Ryan Sandor Richards
* @param {Object} parent Parent node of the recur.
* @param {Number} depth Depth of the parent node.
* @return {TreeTraversal~recur} The recur method for the node and depth.
*/
function Recur(traversal, parent, depth) {
/**
* Recurs further into the traversal given the next node.
* @callback recur
* @param {Object} node Node on which to continue the traversal.
* @param {Number} [givenDepth] Traversal depth override.
*/
var recur = function(node, givenDepth) {
if (!givenDepth) {
givenDepth = depth + 1;
}
return traversal.run(node, givenDepth);
};
recur._options = {
autoTraverse: true,
reduce: function(a, b) {
return a + b;
},
reduceInitial: '',
depth: depth
};
for (var name in Recur.prototype) {
recur[name] = Recur.prototype[name];
}
return recur;
}
/**
* Stop automatic traversal for names defined with `TreeTraversal.preorder`
* and `TreeTraversal.postorder`.
*/
Recur.prototype.stop = function() {
this._options.autoTraverse = false;
};
/**
* Sets the reduce function for `.each`.
* @param {Function} fn Reduce function.
*/
Recur.prototype.setReduce = function(fn) {
this._options.reduce = fn;
};
/**
* Sets initial value for `.each` reduce.
* @param initial Intial value.
*/
Recur.prototype.setReduceInitial = function(initial) {
this._options.reduceInitial = initial;
};
/**
* Recurs further in the traversal for each node in a given array.
* @param {Array} list Array of nodes to traverse.
* @param {Number} [givenDepth] Traversal depth override.
*/
Recur.prototype.each = function(list, givenDepth) {
if (!givenDepth) {
givenDepth = this._options.depth + 1;
}
var recur = this;
return list.map(function (node) {
return recur(node, givenDepth);
}).reduce(function (left, right) {
return recur._options.reduce(left, right);
}, "");
};