Home Reference Source Repository

src/main/draw.js

/**
 * draw:
 * manages the heavy lifting of d3 by creating  a reusable pattern to 
 * create graphics.  Note: if setting.data is `false` parent object will 
 * bind only.
 *
 * @param {String} what - what will be picked in the selection 
 * @param {D3Object} parent - the svg that will be render new images
 * @param {Object} settings - Object of data and is.
 * @param {Array} settings.data - an Array or an Array of an Array and an
 *  id fuction.
 * @param {Object} settings.is - a function following d3 convention of 
 *   passing the parent to perform d3 methods on.
 * @return {Object}
 * @example 
 * draw("rect.range", container, {
 *   data: rangez,
 *   is : {
 *     enter : (selection) => {
 *       return selection.enter().append("rect")
 *         .attr({
 *           "class": (d, i) => "range s" + i,
 *           "width": w0,
 *           "height": height,
 *           "x": reverse ? lastScale : 0
 *         })
 *       .transition()
 *         .duration(duration)
 *         .attr({
 *           "width": w1,
 *           "x": reverse ? currentScale : 0
 *         });
 *     },
 *     postUpdate : (selection) => {
 *       return selection.transition()
 *         .duration(duration)
 *         .attr({
 *           "x": reverse ? currentScale : 0,
 *           "width": w1,
 *           "height": height
 *         });
 *     },
 *     exit : (selection) => {
 *       return selection.exit().remove();
 *     }
 *   }
 * });
 */
function draw(what, parent, settings) {
  let data = settings.data;
  let create = data === false ? parent : parent.selectAll(what);
  let keys = Object.keys(settings.is);
  let len = keys.length;
  let applyArgs;

  // I do not believe that I have actually covered all cases
  if (!(data instanceof Array && data[1] instanceof Function)) {
    applyArgs = [data];
  } else {
    applyArgs = data;
  }

  if (data) {
    create = create.data.apply(create, applyArgs);
  }

  for (let i = 0; i < len; i++) {
    create.call(settings.is[ keys[i] ]);  
  }
  return create;
}

export default draw;