<commit_before>/**
 * @module ogs.vgl
 */

/**
 * Create a new instance of class renderState
 *
 * @class vglModule.renderState
 * @returns {vglModule.renderState}
 */
vglModule.renderState = function() {
  this.m_modelViewMatrix = mat4.create();
  this.m_projectionMatrix = null;
  this.m_material = null;
  this.m_mapper = null;
};

/**
 * Create a new instance of class renderer
 *
 * @class vglModule.renderer
 * @returns {vglModule.renderer}
 */
vglModule.renderer = function() {

  if (!(this instanceof vglModule.renderer)) {
    return new vglModule.renderer();
  }
  vglModule.object.call(this);

  /** @private */
  var m_backgroundColor = [0.0, 0.0, 0.0, 1.0];

  /** @private */
  var m_sceneRoot = new vglModule.groupNode();

  /** @private */
  var m_camera = new vglModule.camera();
  m_camera.addChild(m_sceneRoot);

  /** @private */
  var m_width = 0;

  /** @private */
  var m_height = 0;

  /**
   * Get width of the renderer
   */
  this.width = function() {
    return m_width;
  };

  /**
   * Get height of the renderer
   */
  this.height = function() {
    return m_height;
  };

  /**
   * Get background color
   */
  this.backgroundColor = function() {
    return m_backgroundColor;
  };

  /**
   * Set background color
   */
  this.setBackgroundColor = function(r, g, b, a) {
    m_backgroundColor[0] = r;
    m_backgroundColor[1] = g;
    m_backgroundColor[2] = b;
    m_backgroundColor[3] = a;

    this.modified();
  };

  /**
   * Get scene root
   */
  this.sceneRoot = function() {
    return m_sceneRoot;
  };

  /**
   * Get main camera of the renderer
   */
  this.camera = function() {
    return m_camera;
  };

  /**
   * Render the scene
   */
  this.render = function() {
    var i = 0,
        renSt = null,
        children = null,
        actor = null,
        sortedActors = [];

    gl.clearColor(m_backgroundColor[0], m_backgroundColor[1],
      m_backgroundColor[2], m_backgroundColor[3]);
    gl.enable(gl.DEPTH_TEST);
    gl.depthFunc(gl.LEQUAL);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    renSt = new vglModule.renderState();
    children = m_sceneRoot.children();

    renSt.m_projectionMatrix = m_camera.projectionMatrix();

    for ( i = 0; i < children.length; ++i) {
      actor = children[i];
      actor.computeBounds();
      if (actor.visible() === false) {
        continue;
      }

      sortedActors.push([actor.material().binNumber(), actor]);
    }

    // Now perform sorting
    sortedActors.sort(function(a, b) {return a[0] - b[0]});

    for ( i = 0; i < sortedActors.length; ++i) {
      console.log(sortedActors[i][0]);
      actor = sortedActors[i][1];

      mat4.multiply(renSt.m_modelViewMatrix, m_camera.viewMatrix(),
                    actor.matrix());
      renSt.m_material = actor.material();
      renSt.m_mapper = actor.mapper();

      // TODO Fix this shortcut
      renSt.m_material.render(renSt);
      renSt.m_mapper.render(renSt);
      renSt.m_material.remove(renSt);
    }
  };

  /**
   * Automatically set up the camera based on visible actors
   */
  this.resetCamera = function() {
    m_camera.computeBounds();

    var vn = m_camera.directionOfProjection(),
        visibleBounds = m_camera.bounds(),
        center = [
          (visibleBounds[0] + visibleBounds[1]) / 2.0,
          (visibleBounds[2] + visibleBounds[3]) / 2.0,
          (visibleBounds[4] + visibleBounds[5]) / 2.0
        ],
        diagonals = [
          visibleBounds[1] - visibleBounds[0],
          visibleBounds[3] - visibleBounds[2],
          visibleBounds[5] - visibleBounds[4]
        ],
        radius = 0.0,
        aspect = m_camera.viewAspect(),
        angle = m_camera.viewAngle();

    if (diagonals[0] > diagonals[1]) {
      if (diagonals[0] > diagonals[2]) {
        radius = diagonals[0] / 2.0;
      } else {
        radius = diagonals[2] / 2.0;
      }
    } else {
      if (diagonals[1] > diagonals[2]) {
        radius = diagonals[1] / 2.0;
      } else {
        radius = diagonals[2] / 2.0;
      }
    }

    // @todo Need to figure out what's happening here
    if (aspect >= 1.0) {
      angle = 2.0 * Math.atan(Math.tan(angle * 0.5) / aspect);
    } else {
      angle = 2.0 * Math.atan(Math.tan(angle * 0.5) * aspect);
    }

    var distance = radius / Math.sin(angle * 0.5),
        vup = m_camera.viewUpDirection();

    if (Math.abs(vec3.dot(vup, vn)) > 0.999) {
      m_camera.setViewUpDirection(-vup[2], vup[0], vup[1]);
    }

    m_camera.setFocalPoint(center[0], center[1], center[2]);
    m_camera.setPosition(center[0] + distance * -vn[0],
      center[1] + distance * -vn[1], center[2] + distance * -vn[2]);

    this.resetCameraClippingRange(visibleBounds);
  };

  /**
   * Recalculate camera's clipping range
   */
  this.resetCameraClippingRange = function(bounds) {
    var vn = m_camera.viewPlaneNormal(),
        position = m_camera.position(),
        a = -vn[0],
        b = -vn[1],
        c = -vn[2],
        d = -(a*position[0] + b*position[1] + c*position[2]),
        range = vec2.create(),
        dist = null;

    // Set the max near clipping plane and the min far clipping plane
    range[0] = a * bounds[0] + b * bounds[2] + c * bounds[4] + d;
    range[1] = 1e-18;

    // Find the closest / farthest bounding box vertex
    for (var k = 0; k < 2; k++ ) {
      for (var j = 0; j < 2; j++) {
        for (var i = 0; i < 2; i++) {
          dist = a * bounds[i] + b * bounds[2 + j] + c * bounds[4 + k] + d;
          range[0] = (dist < range[0]) ? (dist) : (range[0]);
          range[1] = (dist > range[1]) ? (dist) : (range[1]);
        }
      }
    }

    // Do not let the range behind the camera throw off the calculation.
    if (range[0] < 0.0) {
      range[0] = 0.0;
    }

    // Give ourselves a little breathing room
    range[0] = 0.99*range[0] - (range[1] - range[0])*0.5;
    range[1] = 1.01*range[1] + (range[1] - range[0])*0.5;

    // Make sure near is not bigger than far
    range[0] = (range[0] >= range[1])?(0.01*range[1]):(range[0]);

    // @todo
    // Make sure near is at least some fraction of far - this prevents near
    // from being behind the camera or too close in front. How close is too
    // close depends on the resolution of the depth buffer
    // if (!this->NearClippingPlaneTolerance)
    //   {
    //   this->NearClippingPlaneTolerance = 0.01;
    //   if (this->RenderWindow)
    //     {
    //     int ZBufferDepth = this->RenderWindow->GetDepthBufferSize();
    //     if ( ZBufferDepth > 16 )
    //       {
    //       this->NearClippingPlaneTolerance = 0.001;
    //       }
    //     }
    //   }

    // make sure the front clipping range is not too far from the far clippnig
    // range, this is to make sure that the zbuffer resolution is effectively
    // used
    // if (range[0] < this->NearClippingPlaneTolerance*range[1]) {
    //   range[0] = this->NearClippingPlaneTolerance*range[1];
    // }

    m_camera.setClippingRange(range[0], range[1]);
  };

  /**
   * Resize viewport given a width and height
   */
  this.resize = function(width, height) {
    // @note: where do m_x and m_y come from?
    this.positionAndResize(m_x, m_y, width, height);
  };

  /**
   * Resize viewport given a position, width and height
   */
  this.positionAndResize = function(x, y, width, height) {
    // TODO move this code to camera
    if (x < 0 || y < 0 || width < 0 || height < 0) {
      console.log('[error] Invalid position and resize values',
        x, y, width, height);
    }

    m_width = width;
    m_height = height;

    gl.viewport(x, y, m_width, m_height);
    m_camera.setViewAspect(m_width / m_height);
    this.modified();
  };

  /**
   * Add new actor to the collection
   */
  this.addActor = function(actor) {
    if (actor instanceof vglModule.actor) {
      m_sceneRoot.addChild(actor);
      this.modified();
      return true;
    }

    return false;
  };

  /**
   * Add an array of actors to the collection
   */
  this.addActors = function(actors) {
    var i = null
    if (actors instanceof Array) {
      for (i = 0; i < actors.length; ++i) {
        m_sceneRoot.addChild(actors[i]);
      }
      this.modified();
    }
  };

  /**
   * Remove the actor from the collection
   */
  this.removeActor = function(actor) {
    if (m_sceneRoot.children().indexOf(actor) !== -1) {
      m_sceneRoot.removeChild(actor);
      this.modified();
      return true;
    }

    return false;
  };

  /**
   * Remove actors from the collection
   */
  this.removeActors = function(actors) {
    if (!(actors instanceof Array)) {
      return false;
    }

    var i = null;
    for (i = 0; i < actors.length; ++i) {
      m_sceneRoot.removeChild(actors[i]);
    }
    this.modified();
    return true;
  };

  /**
   * Remove all actors for a renderer
   */
  this.removeAllActors = function() {
    m_sceneRoot.removeChildren();
  }

  /**
   * Transform a point in the world space to display space
   */
  this.worldToDisplay = function(worldPt, viewMatrix, projectionMatrix, width,
                                 height) {
    var viewProjectionMatrix = mat4.create();
    mat4.multiply(viewProjectionMatrix, projectionMatrix, viewMatrix);

    // Transform world to clipping coordinates
    var clipPt = vec4.create();
    vec4.transformMat4(clipPt, worldPt, viewProjectionMatrix);

    if (clipPt[3] !== 0.0) {
      clipPt[0] = clipPt[0] / clipPt[3];
      clipPt[1] = clipPt[1] / clipPt[3];
      clipPt[2] = clipPt[2] / clipPt[3];
      clipPt[3] = 1.0;
    }

    var winX = Math.round((((clipPt[0]) + 1) / 2.0) * width);
    // / We calculate -point3D.getY() because the screen Y axis is
    // / oriented top->down
    var winY = Math.round(((1 - clipPt[1]) / 2.0) * height);
    var winZ = clipPt[2];
    var winW = clipPt[3];

    return vec4.fromValues(winX, winY, winZ, winW);
  };

  /**
   * Transform a point in display space to world space
   */
  this.displayToWorld = function(displayPt, viewMatrix, projectionMatrix,
                                 width, height) {
    var x = (2.0 * displayPt[0] / width) - 1,
        y = -(2.0 * displayPt[1] / height) + 1,
        z = displayPt[2];

    var viewProjectionInverse = mat4.create();
    mat4.multiply(viewProjectionInverse, projectionMatrix, viewMatrix);
    mat4.invert(viewProjectionInverse, viewProjectionInverse);

    var worldPt = vec4.fromValues(x, y, z, 1);
    vec4.transformMat4(worldPt, worldPt, viewProjectionInverse);
    if (worldPt[3] !== 0.0) {
      worldPt[0] = worldPt[0] / worldPt[3];
      worldPt[1] = worldPt[1] / worldPt[3];
      worldPt[2] = worldPt[2] / worldPt[3];
      worldPt[3] = 1.0;
    }

    return worldPt;
  };

  return this;
};

inherit(vglModule.renderer, vglModule.object);
<commit_msg>Clean up<commit_after>/**
 * @module ogs.vgl
 */

/**
 * Create a new instance of class renderState
 *
 * @class vglModule.renderState
 * @returns {vglModule.renderState}
 */
vglModule.renderState = function() {
  this.m_modelViewMatrix = mat4.create();
  this.m_projectionMatrix = null;
  this.m_material = null;
  this.m_mapper = null;
};

/**
 * Create a new instance of class renderer
 *
 * @class vglModule.renderer
 * @returns {vglModule.renderer}
 */
vglModule.renderer = function() {

  if (!(this instanceof vglModule.renderer)) {
    return new vglModule.renderer();
  }
  vglModule.object.call(this);

  /** @private */
  var m_backgroundColor = [0.0, 0.0, 0.0, 1.0];

  /** @private */
  var m_sceneRoot = new vglModule.groupNode();

  /** @private */
  var m_camera = new vglModule.camera();
  m_camera.addChild(m_sceneRoot);

  /** @private */
  var m_width = 0;

  /** @private */
  var m_height = 0;

  /**
   * Get width of the renderer
   */
  this.width = function() {
    return m_width;
  };

  /**
   * Get height of the renderer
   */
  this.height = function() {
    return m_height;
  };

  /**
   * Get background color
   */
  this.backgroundColor = function() {
    return m_backgroundColor;
  };

  /**
   * Set background color
   */
  this.setBackgroundColor = function(r, g, b, a) {
    m_backgroundColor[0] = r;
    m_backgroundColor[1] = g;
    m_backgroundColor[2] = b;
    m_backgroundColor[3] = a;

    this.modified();
  };

  /**
   * Get scene root
   */
  this.sceneRoot = function() {
    return m_sceneRoot;
  };

  /**
   * Get main camera of the renderer
   */
  this.camera = function() {
    return m_camera;
  };

  /**
   * Render the scene
   */
  this.render = function() {
    var i = 0,
        renSt = null,
        children = null,
        actor = null,
        sortedActors = [];

    gl.clearColor(m_backgroundColor[0], m_backgroundColor[1],
      m_backgroundColor[2], m_backgroundColor[3]);
    gl.enable(gl.DEPTH_TEST);
    gl.depthFunc(gl.LEQUAL);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    renSt = new vglModule.renderState();
    children = m_sceneRoot.children();

    renSt.m_projectionMatrix = m_camera.projectionMatrix();

    for ( i = 0; i < children.length; ++i) {
      actor = children[i];
      actor.computeBounds();
      if (actor.visible() === false) {
        continue;
      }

      sortedActors.push([actor.material().binNumber(), actor]);
    }

    // Now perform sorting
    sortedActors.sort(function(a, b) {return a[0] - b[0]});

    for ( i = 0; i < sortedActors.length; ++i) {
      actor = sortedActors[i][1];

      mat4.multiply(renSt.m_modelViewMatrix, m_camera.viewMatrix(),
                    actor.matrix());
      renSt.m_material = actor.material();
      renSt.m_mapper = actor.mapper();

      // TODO Fix this shortcut
      renSt.m_material.render(renSt);
      renSt.m_mapper.render(renSt);
      renSt.m_material.remove(renSt);
    }
  };

  /**
   * Automatically set up the camera based on visible actors
   */
  this.resetCamera = function() {
    m_camera.computeBounds();

    var vn = m_camera.directionOfProjection(),
        visibleBounds = m_camera.bounds(),
        center = [
          (visibleBounds[0] + visibleBounds[1]) / 2.0,
          (visibleBounds[2] + visibleBounds[3]) / 2.0,
          (visibleBounds[4] + visibleBounds[5]) / 2.0
        ],
        diagonals = [
          visibleBounds[1] - visibleBounds[0],
          visibleBounds[3] - visibleBounds[2],
          visibleBounds[5] - visibleBounds[4]
        ],
        radius = 0.0,
        aspect = m_camera.viewAspect(),
        angle = m_camera.viewAngle();

    if (diagonals[0] > diagonals[1]) {
      if (diagonals[0] > diagonals[2]) {
        radius = diagonals[0] / 2.0;
      } else {
        radius = diagonals[2] / 2.0;
      }
    } else {
      if (diagonals[1] > diagonals[2]) {
        radius = diagonals[1] / 2.0;
      } else {
        radius = diagonals[2] / 2.0;
      }
    }

    // @todo Need to figure out what's happening here
    if (aspect >= 1.0) {
      angle = 2.0 * Math.atan(Math.tan(angle * 0.5) / aspect);
    } else {
      angle = 2.0 * Math.atan(Math.tan(angle * 0.5) * aspect);
    }

    var distance = radius / Math.sin(angle * 0.5),
        vup = m_camera.viewUpDirection();

    if (Math.abs(vec3.dot(vup, vn)) > 0.999) {
      m_camera.setViewUpDirection(-vup[2], vup[0], vup[1]);
    }

    m_camera.setFocalPoint(center[0], center[1], center[2]);
    m_camera.setPosition(center[0] + distance * -vn[0],
      center[1] + distance * -vn[1], center[2] + distance * -vn[2]);

    this.resetCameraClippingRange(visibleBounds);
  };

  /**
   * Recalculate camera's clipping range
   */
  this.resetCameraClippingRange = function(bounds) {
    var vn = m_camera.viewPlaneNormal(),
        position = m_camera.position(),
        a = -vn[0],
        b = -vn[1],
        c = -vn[2],
        d = -(a*position[0] + b*position[1] + c*position[2]),
        range = vec2.create(),
        dist = null;

    // Set the max near clipping plane and the min far clipping plane
    range[0] = a * bounds[0] + b * bounds[2] + c * bounds[4] + d;
    range[1] = 1e-18;

    // Find the closest / farthest bounding box vertex
    for (var k = 0; k < 2; k++ ) {
      for (var j = 0; j < 2; j++) {
        for (var i = 0; i < 2; i++) {
          dist = a * bounds[i] + b * bounds[2 + j] + c * bounds[4 + k] + d;
          range[0] = (dist < range[0]) ? (dist) : (range[0]);
          range[1] = (dist > range[1]) ? (dist) : (range[1]);
        }
      }
    }

    // Do not let the range behind the camera throw off the calculation.
    if (range[0] < 0.0) {
      range[0] = 0.0;
    }

    // Give ourselves a little breathing room
    range[0] = 0.99*range[0] - (range[1] - range[0])*0.5;
    range[1] = 1.01*range[1] + (range[1] - range[0])*0.5;

    // Make sure near is not bigger than far
    range[0] = (range[0] >= range[1])?(0.01*range[1]):(range[0]);

    // @todo
    // Make sure near is at least some fraction of far - this prevents near
    // from being behind the camera or too close in front. How close is too
    // close depends on the resolution of the depth buffer
    // if (!this->NearClippingPlaneTolerance)
    //   {
    //   this->NearClippingPlaneTolerance = 0.01;
    //   if (this->RenderWindow)
    //     {
    //     int ZBufferDepth = this->RenderWindow->GetDepthBufferSize();
    //     if ( ZBufferDepth > 16 )
    //       {
    //       this->NearClippingPlaneTolerance = 0.001;
    //       }
    //     }
    //   }

    // make sure the front clipping range is not too far from the far clippnig
    // range, this is to make sure that the zbuffer resolution is effectively
    // used
    // if (range[0] < this->NearClippingPlaneTolerance*range[1]) {
    //   range[0] = this->NearClippingPlaneTolerance*range[1];
    // }

    m_camera.setClippingRange(range[0], range[1]);
  };

  /**
   * Resize viewport given a width and height
   */
  this.resize = function(width, height) {
    // @note: where do m_x and m_y come from?
    this.positionAndResize(m_x, m_y, width, height);
  };

  /**
   * Resize viewport given a position, width and height
   */
  this.positionAndResize = function(x, y, width, height) {
    // TODO move this code to camera
    if (x < 0 || y < 0 || width < 0 || height < 0) {
      console.log('[error] Invalid position and resize values',
        x, y, width, height);
    }

    m_width = width;
    m_height = height;

    gl.viewport(x, y, m_width, m_height);
    m_camera.setViewAspect(m_width / m_height);
    this.modified();
  };

  /**
   * Add new actor to the collection
   */
  this.addActor = function(actor) {
    if (actor instanceof vglModule.actor) {
      m_sceneRoot.addChild(actor);
      this.modified();
      return true;
    }

    return false;
  };

  /**
   * Add an array of actors to the collection
   */
  this.addActors = function(actors) {
    var i = null
    if (actors instanceof Array) {
      for (i = 0; i < actors.length; ++i) {
        m_sceneRoot.addChild(actors[i]);
      }
      this.modified();
    }
  };

  /**
   * Remove the actor from the collection
   */
  this.removeActor = function(actor) {
    if (m_sceneRoot.children().indexOf(actor) !== -1) {
      m_sceneRoot.removeChild(actor);
      this.modified();
      return true;
    }

    return false;
  };

  /**
   * Remove actors from the collection
   */
  this.removeActors = function(actors) {
    if (!(actors instanceof Array)) {
      return false;
    }

    var i = null;
    for (i = 0; i < actors.length; ++i) {
      m_sceneRoot.removeChild(actors[i]);
    }
    this.modified();
    return true;
  };

  /**
   * Remove all actors for a renderer
   */
  this.removeAllActors = function() {
    m_sceneRoot.removeChildren();
  }

  /**
   * Transform a point in the world space to display space
   */
  this.worldToDisplay = function(worldPt, viewMatrix, projectionMatrix, width,
                                 height) {
    var viewProjectionMatrix = mat4.create();
    mat4.multiply(viewProjectionMatrix, projectionMatrix, viewMatrix);

    // Transform world to clipping coordinates
    var clipPt = vec4.create();
    vec4.transformMat4(clipPt, worldPt, viewProjectionMatrix);

    if (clipPt[3] !== 0.0) {
      clipPt[0] = clipPt[0] / clipPt[3];
      clipPt[1] = clipPt[1] / clipPt[3];
      clipPt[2] = clipPt[2] / clipPt[3];
      clipPt[3] = 1.0;
    }

    var winX = Math.round((((clipPt[0]) + 1) / 2.0) * width);
    // / We calculate -point3D.getY() because the screen Y axis is
    // / oriented top->down
    var winY = Math.round(((1 - clipPt[1]) / 2.0) * height);
    var winZ = clipPt[2];
    var winW = clipPt[3];

    return vec4.fromValues(winX, winY, winZ, winW);
  };

  /**
   * Transform a point in display space to world space
   */
  this.displayToWorld = function(displayPt, viewMatrix, projectionMatrix,
                                 width, height) {
    var x = (2.0 * displayPt[0] / width) - 1,
        y = -(2.0 * displayPt[1] / height) + 1,
        z = displayPt[2];

    var viewProjectionInverse = mat4.create();
    mat4.multiply(viewProjectionInverse, projectionMatrix, viewMatrix);
    mat4.invert(viewProjectionInverse, viewProjectionInverse);

    var worldPt = vec4.fromValues(x, y, z, 1);
    vec4.transformMat4(worldPt, worldPt, viewProjectionInverse);
    if (worldPt[3] !== 0.0) {
      worldPt[0] = worldPt[0] / worldPt[3];
      worldPt[1] = worldPt[1] / worldPt[3];
      worldPt[2] = worldPt[2] / worldPt[3];
      worldPt[3] = 1.0;
    }

    return worldPt;
  };

  return this;
};

inherit(vglModule.renderer, vglModule.object);
<|endoftext|>


<commit_before>charts.point = function(args) {
    this.args = args;

    this.init = function(args) {
        raw_data_transformation(args);
        process_point(args);
        init(args);
        x_axis(args);
        y_axis(args);
        return this;
    }

    this.markers = function() {
        markers(args);
        if (args.least_squares){
            add_ls(args);
        }
        // if (args.lowess){
        //     add_lowess(args);
        // }
        return this
    }

    this.mainPlot = function() {
        var svg = d3.select(args.target + ' svg');
        var g;

        // plot the points, pretty straight-forward
        g = svg.append('g')
            .classed('points', true);

        var pts = g.selectAll('circle')
            .data(args.data[0])
            .enter().append('svg:circle')
                .attr('cx', args.scalefns.xf)
                .attr('cy', args.scalefns.yf);

        if (args.color_accessor!=null){
            pts.attr('fill',   args.scalefns.color);
            pts.attr('stroke', args.scalefns.color);
        } else {
            pts.attr('fill',   '#0000ff');
            pts.attr('stroke', '#0000ff');
        }
        if (args.size_accessor!=null){
            pts.attr('r', args.scalefns.size);
        } else {
            pts.attr('r', 2);
        }
        var rug;
        if (args.x_rug){
            //var data = args.data[0].map(function(d){return d[args.x_accessor]});
            rug=g.selectAll('line.x_rug').data(args.data[0]).enter().append('svg:line')
                .attr('x1', args.scalefns.xf)
                .attr('x2', args.scalefns.xf)
                .attr('y1', args.height-args.top+args.buffer)
                .attr('y2', args.height-args.top)
                .attr('opacity', .3);
            if (args.color_accessor){
                rug.attr('stroke', args.scalefns.color);
            } else {
                rug.attr('stroke', 'black');
            }
        }
        if (args.y_rug){
            rug=g.selectAll('line.y_rug').data(args.data[0]).enter().append('svg:line')
                .attr('x1', args.left+1)
                .attr('x2', args.left+args.buffer)
                .attr('y1', args.scalefns.yf)
                .attr('y2', args.scalefns.yf)
                .attr('stroke', 'black')
                .attr('opacity', .2);
            if (args.color_accessor){
                rug.attr('stroke', args.scalefns.color);
            } else {
                rug.attr('stroke', 'black');
            }
        }

        return this;
    }

    this.rollover = function() {
        var svg = d3.select(args.target + ' svg');

        var clips = svg.append('g')
                .attr('id', 'point-clips');

        var paths = svg.append('g')
            .attr('id', 'point-paths');

        //remove rollover text if it already exists
        if($(args.target + ' svg .active_datapoint').length > 0) {
            $(args.target + ' svg .active_datapoint').remove();
        }

        //add rollover text
        svg.append('text')
            .attr('class', 'active_datapoint')
            .attr('xml:space', 'preserve')
            .attr('x', args.width - args.right)
            .attr('y', args.top / 2)
            .attr('text-anchor', 'end');

        var voronoi = d3.geom.voronoi()
            .x(args.scalefns.xf)
            .y(args.scalefns.yf)
            .clipExtent([[args.buffer, args.buffer], [args.width - args.buffer, args.height - args.buffer]]);

        paths.selectAll('path')
            .data(voronoi(args.data[0]))
            .enter().append('path')
                .attr('d', function(d) {
                    if(d == undefined) return;
                    return 'M' + d.join(',') + 'Z';
                })
                .attr('id', function(d,i) {
                    return 'path-' + i;
                })
                .attr('clip-path', function(d,i) {
                    return 'url(#clip-'+i+')';
                })
                .style('fill-opacity', 0)
                .on('mouseover', this.rolloverOn(args))
                .on('mouseout', this.rolloverOff(args));

        return this;
    }

    this.rolloverOn = function(args) {
        var svg = d3.select(args.target + ' svg');

        return function(d, i){
            svg.selectAll('.points circle')
                .classed('unselected', true);

            var fmt = d3.time.format('%b %e, %Y');

            if (args.format == 'count') {
                var num = function(d_) {
                    var is_float = d_ % 1 != 0;
                    var n = d3.format("0,000");
                    d_ = is_float ? d3.round(d_, args.decimals) : d_;
                    return n(d_);
                }
            }
            else {
                var num = function(d_) {
                    var fmt_string = (args.decimals ? '.' + args.decimals : '' ) + '%';
                    var n = d3.format(fmt_string);
                    return n(d_);
                }
            }

            //highlight active point
            var pts = svg.selectAll('.points circle')
                .filter(function(g,j){return i == j})
                .classed('unselected', false)
                .classed('selected', true);

            if (args.size_accessor){
                pts.attr('r', function(di){return args.scalefns.size(di)+1});
            } else {
                pts.attr('r', 3);
            }

            //update rollover text
            if (args.show_rollover_text) {
                svg.select('.active_datapoint')
                    .text(function() {
                        if(args.time_series) {
                            var dd = new Date(+d['point'][args.x_accessor]);
                            dd.setDate(dd.getDate());

                            return fmt(dd) + '  ' + args.yax_units
                                + num(d['point'][args.y_accessor]);
                        }
                        else {
                            return args.x_accessor + ': ' + num(d['point'][args.x_accessor])
                                + ', ' + args.y_accessor + ': ' + args.yax_units
                                + num(d['point'][args.y_accessor]);
                        }
                    });
            }
        }
    }

    this.rolloverOff = function(args) {
        var svg = d3.select(args.target + ' svg');

        return function(d,i){
            //reset active point
            var pts = svg.selectAll('.points circle')
                .classed('unselected', false)
                .classed('selected', false);

            if (args.size_accessor){
                pts.attr('r', args.scalefns.size);
            } else {
                pts.attr('r', 2);
            }

            //reset active data point text
            svg.select('.active_datapoint')
                .text('');
        }
    }

    this.update = function(args) {
        return this;
    }

    this.init(args);

    return this;
}
<commit_msg>Fix issue #156<commit_after>charts.point = function(args) {
    this.args = args;

    this.init = function(args) {
        raw_data_transformation(args);
        process_point(args);
        init(args);
        x_axis(args);
        y_axis(args);
        return this;
    }

    this.markers = function() {
        markers(args);
        if (args.least_squares){
            add_ls(args);
        }
        // if (args.lowess){
        //     add_lowess(args);
        // }
        return this
    }

    this.mainPlot = function() {
        var svg = d3.select(args.target + ' svg');
        var g;

        // plot the points, pretty straight-forward
        g = svg.append('g')
            .classed('points', true);

        var pts = g.selectAll('circle')
            .data(args.data[0])
            .enter().append('svg:circle')
                .attr('cx', args.scalefns.xf)
                .attr('cy', args.scalefns.yf);

        if (args.color_accessor!=null){
            pts.attr('fill',   args.scalefns.color);
            pts.attr('stroke', args.scalefns.color);
        } else {
            pts.attr('fill',   '#0000ff');
            pts.attr('stroke', '#0000ff');
        }
        if (args.size_accessor!=null){
            pts.attr('r', args.scalefns.size);
        } else {
            pts.attr('r', 2);
        }
        var rug;
        if (args.x_rug){
            //var data = args.data[0].map(function(d){return d[args.x_accessor]});
            rug=g.selectAll('line.x_rug').data(args.data[0]).enter().append('svg:line')
                .attr('x1', args.scalefns.xf)
                .attr('x2', args.scalefns.xf)
                .attr('y1', args.height-args.top+args.buffer)
                .attr('y2', args.height-args.top)
                .attr('opacity', .3);
            if (args.color_accessor){
                rug.attr('stroke', args.scalefns.color);
            } else {
                rug.attr('stroke', 'black');
            }
        }
        if (args.y_rug){
            rug=g.selectAll('line.y_rug').data(args.data[0]).enter().append('svg:line')
                .attr('x1', args.left+1)
                .attr('x2', args.left+args.buffer)
                .attr('y1', args.scalefns.yf)
                .attr('y2', args.scalefns.yf)
                .attr('stroke', 'black')
                .attr('opacity', .2);
            if (args.color_accessor){
                rug.attr('stroke', args.scalefns.color);
            } else {
                rug.attr('stroke', 'black');
            }
        }

        return this;
    }

    this.rollover = function() {
        var svg = d3.select(args.target + ' svg');

        var clips = svg.append('g')
                .attr('id', 'point-clips');

        var paths = svg.append('g')
            .attr('id', 'point-paths');

        //remove rollover text if it already exists
        if($(args.target + ' svg .active_datapoint').length > 0) {
            $(args.target + ' svg .active_datapoint').remove();
        }

        //add rollover text
        svg.append('text')
            .attr('class', 'active_datapoint')
            .attr('xml:space', 'preserve')
            .attr('x', args.width - args.right)
            .attr('y', args.top / 2)
            .attr('text-anchor', 'end');

        var voronoi = d3.geom.voronoi()
            .x(args.scalefns.xf)
            .y(args.scalefns.yf)
            .clipExtent([[args.buffer, args.buffer], [args.width - args.buffer, args.height - args.buffer]]);

        paths.selectAll('path')
            .data(voronoi(args.data[0]))
            .enter().append('path')
                .attr('d', function(d) {
                    if(d == undefined) return;
                    return 'M' + d.join(',') + 'Z';
                })
                .attr('id', function(d,i) {
                    return 'path-' + i;
                })
                .attr('clip-path', function(d,i) {
                    return 'url(#clip-'+i+')';
                })
                .style('fill-opacity', 0)
                .on('mouseover', this.rolloverOn(args))
                .on('mouseout', this.rolloverOff(args));

        return this;
    }

    this.rolloverOn = function(args) {
        var svg = d3.select(args.target + ' svg');

        return function(d, i){
            svg.selectAll('.points circle')
                .classed('unselected', true);

            var fmt = d3.time.format('%b %e, %Y');

            if (args.format == 'count') {
                var num = function(d_) {
                    var is_float = d_ % 1 != 0;
                    var n = d3.format("0,000");
                    d_ = is_float ? d3.round(d_, args.decimals) : d_;
                    return n(d_);
                }
            }
            else {
                var num = function(d_) {
                    var fmt_string = (args.decimals ? '.' + args.decimals : '' ) + '%';
                    var n = d3.format(fmt_string);
                    return n(d_);
                }
            }

            //highlight active point
            var pts = svg.selectAll('.points circle')
                .filter(function(g,j){return i == j})
                .classed('unselected', false)
                .classed('selected', true);

            if (args.size_accessor){
                pts.attr('r', function(di){return args.scalefns.size(di)+1});
            } else {
                pts.attr('r', 3);
            }

            //update rollover text
            if (args.show_rollover_text) {
                svg.select('.active_datapoint')
                    .text(function() {
                        if(args.time_series) {
                            var dd = new Date(+d['point'][args.x_accessor]);
                            dd.setDate(dd.getDate());

                            return fmt(dd) + '  ' + args.yax_units
                                + num(d['point'][args.y_accessor]);
                        }
                        else {
                            return args.x_accessor + ': ' + num(d['point'][args.x_accessor])
                                + ', ' + args.y_accessor + ': ' + args.yax_units
                                + num(d['point'][args.y_accessor]);
                        }
                    });
            }

            if(args.rollover_callback) {
                args.rollover_callback(d, i);
            }
        }
    }

    this.rolloverOff = function(args) {
        var svg = d3.select(args.target + ' svg');

        return function(d,i){
            //reset active point
            var pts = svg.selectAll('.points circle')
                .classed('unselected', false)
                .classed('selected', false);

            if (args.size_accessor){
                pts.attr('r', args.scalefns.size);
            } else {
                pts.attr('r', 2);
            }

            //reset active data point text
            svg.select('.active_datapoint')
                .text('');
        }
    }

    this.update = function(args) {
        return this;
    }

    this.init(args);

    return this;
}
<|endoftext|>


<commit_before>var shiv = {
  version    : '0.01',
  loading    : false,
  shivPrefix : '',
  modules    : {}
};

shiv.addOnLoad = (function() {
    var onload = window.onload;
    var loadqueue = [];
    window.onload = function() {
      onload && onload();
      for (var i=0; i<loadqueue.length; i++) {
        loadqueue[i]();
      }
    }
    return function(func) {
      loadqueue.push(func);
    }
  })();

shiv.log = (function() {
    if (window.console != null) {
      return function(msg) {
        console.debug(msg);
      };
    } else {
      return function() {};
    }
  })();

shiv.xhr = (function() {
    if (typeof XMLHttpRequest != "undefined") {
      return function() {
        return new XMLHttpRequest();
      };
    } else if (typeof ActiveXObject != "undefined") {
      return function() {
        return new ActiveXObject("Microsoft.XMLHTTP");
      };
    } else {
      throw new Error("XMLHttpRequest not supported");
    }
  })();

shiv.post = function(opts) {
  var xhr = shiv.xhr();

  xhr.open( "POST",
    opts.url      || '/' ,
    !!!(opts.sync || false)
  );

  xhr.setRequestHeader(
    "Content-type",
    opts.contentType || "application/json"
  );

  xhr.setRequestHeader("Content-length", opts.body.length);
  xhr.setRequestHeader("Connection", "close");

  xhr.send(opts.body);

}

shiv.get = function(opts) {
  var xhr   = shiv.xhr();
  var async = !!!(opts.sync || false);

  xhr.open( "GET",
    opts.url || '/' ,
    async
  );

  if (async) {
    xhr.onreadystatechange = function() {
      if (xhr.readyState == 4) {
        switch (xhr.status) {
        case 200:
          opts.callback(xhr.responseText);
          break;
        default:
          shiv.log("Optimism is insufficient for this operation!");
          break;
        }
      }
    }
    xhr.send();
  } else {
    xhr.send();
    opts.callback(xhr.responseText);
  }
}

shiv.load = function(res) {
  if (shiv.modules[res] != null) {
    shiv.log("shiv.load : Resource " + res + " already loaded");
  } else {
    shiv.log("shiv.load : Attempting to load resource " + res);
    shiv.get({
        url      : shiv.shivPrefix + res + '.js',
        sync     : true,
        callback : function(data) {
          shiv.log("shiv.load.callback : loading resource " + res + " succeeded.");
          shiv.modules[res] = true;
          try {
            with (top) {
              eval(data); // Yeah, yeah, I know - eval is evil.
            }
          } catch(e) {
            shiv.log("shiv.load.callback : eval'ing resource " + res + " FAILED : " + e.toString());
          }
        }
      });
  }
}

<commit_msg>Added simple test for IE<commit_after>var shiv = {
  version    : '0.01',
  loading    : false,
  shivPrefix : '',
  modules    : {}
};

shiv.isIE = /*@cc_on!@*/false;

shiv.addOnLoad = (function() {
    var onload = window.onload;
    var loadqueue = [];
    window.onload = function() {
      onload && onload();
      for (var i=0; i<loadqueue.length; i++) {
        loadqueue[i]();
      }
    }
    return function(func) {
      loadqueue.push(func);
    }
  })();

shiv.log = (function() {
    if (window.console != null) {
      return function(msg) {
        console.debug(msg);
      };
    } else {
      return function() {};
    }
  })();

shiv.xhr = (function() {
    if (typeof XMLHttpRequest != "undefined") {
      return function() {
        return new XMLHttpRequest();
      };
    } else if (typeof ActiveXObject != "undefined") {
      return function() {
        return new ActiveXObject("Microsoft.XMLHTTP");
      };
    } else {
      throw new Error("XMLHttpRequest not supported");
    }
  })();

shiv.post = function(opts) {
  var xhr = shiv.xhr();

  xhr.open( "POST",
    opts.url      || '/' ,
    !!!(opts.sync || false)
  );

  xhr.setRequestHeader(
    "Content-type",
    opts.contentType || "application/json"
  );

  xhr.setRequestHeader("Content-length", opts.body.length);
  xhr.setRequestHeader("Connection", "close");

  xhr.send(opts.body);

}

shiv.get = function(opts) {
  var xhr   = shiv.xhr();
  var async = !!!(opts.sync || false);

  xhr.open( "GET",
    opts.url || '/' ,
    async
  );

  if (async) {
    xhr.onreadystatechange = function() {
      if (xhr.readyState == 4) {
        switch (xhr.status) {
        case 200:
          opts.callback(xhr.responseText);
          break;
        default:
          shiv.log("Optimism is insufficient for this operation!");
          break;
        }
      }
    }
    xhr.send();
  } else {
    xhr.send();
    opts.callback(xhr.responseText);
  }
}

shiv.load = function(res) {
  if (shiv.modules[res] != null) {
    shiv.log("shiv.load : Resource " + res + " already loaded");
  } else {
    shiv.log("shiv.load : Attempting to load resource " + res);
    shiv.get({
        url      : shiv.shivPrefix + res + '.js',
        sync     : true,
        callback : function(data) {
          shiv.log("shiv.load.callback : loading resource " + res + " succeeded.");
          shiv.modules[res] = true;
          try {
            with (top) {
              eval(data); // Yeah, yeah, I know - eval is evil.
            }
          } catch(e) {
            shiv.log("shiv.load.callback : eval'ing resource " + res + " FAILED : " + e.toString());
          }
        }
      });
  }
}

<|endoftext|>


<commit_before>define([
  'jquery', 'underscore', 'peerjs', 'net/BbsNetwork', 'net/RequestDispatcher', 'utils/Utils'
], function($, _, Peer, BbsNetwork, RequestDispatcher, Utils) {
  var NetworkAgent = function(config) {
    var self = this;

    this._config = config;
    this._threadListNetwork = new BbsNetwork(this._replacePeerId(
      config, 'T'
    ), function(fromPeerId, request, callback) {
      self._onRequestReceived(fromPeerId, request, callback);
    });
    this._threadNetworks = {};
    this._requestDispatcher = new RequestDispatcher();
    this._peers = [];
  };

  NetworkAgent.prototype = {
    createNetwork: function(callback) {
      this._threadListNetwork.createNetwork(callback);
    },

    joinNetwork: function(callback) {
      var self = this;

      Utils.debug("Trying to join thread list network.");

      this._getBootstrapIds(function(bootstrapIds) {
        self._peers = bootstrapIds;

        if (_.isEmpty(bootstrapIds)) {
          self.createNetwork(callback);
          return;
        }

        var retryJoinNetwork = function(bootstrapIds, callback) {
          if (_.isEmpty(bootstrapIds)) {
            return callback(null, new Error("Failed to join network."));
          }

          self._threadListNetwork.joinNetwork(_.first(bootstrapIds), function(peerId, error) {
            if (error) {
              Utils.debug("Failed to connect to", _.first(bootstrapIds), "(", error, "). Retry next peer.");
              retryJoinNetwork(_.rest(bootstrapIds), callback);
              return;
            }

            Utils.debug("Joining thread list network succeeded.");

            callback(peerId);
          });
        };
        retryJoinNetwork(bootstrapIds, callback);
      });
    },

    leaveNetwork: function() {
      var self = this;

      _.each(_.keys(this._threadNetworks), function(threadId) {
        self.leaveThreadNetwork(threadId);
      });
      this._threadListNetwork.leaveNetwork();

      Utils.debug("Left thread list network.");
    },

    fetchThreads: function(excludeIds, callback) {
      this._threadListNetwork.fetchThreads(excludeIds, callback);
    },

    spreadThread: function(threadInfo) {
      this._threadListNetwork.spreadThread(threadInfo);
    },

    fetchMessages: function(threadId, excludeIds, callback) {
      if (!_.has(this._threadNetworks, threadId)) {
        return callback(new Error("Unknown thread ID: " + threadId));
      }

      this._threadNetworks[threadId].fetchMessages(threadId, excludeIds, callback);
    },

    spreadMessage: function(messageInfo) {
      this._threadNetworks[messageInfo.threadId].spreadMessage(messageInfo);
    },

    joinThreadNetwork: function(threadId, callback) {
      var self = this;

      if (_.has(this._threadNetworks, threadId)) {
        return callback();
      }

      Utils.debug("Trying to join thread network (thread ID", threadId, ")");

      var threadNetwork = new BbsNetwork(this._replacePeerId(
        this._config, 't'
      ), function(fromPeerId, request, callback) {
        self._onRequestReceived(fromPeerId, request, callback);
      });
      this._threadNetworks[threadId] = threadNetwork;

      this._threadListNetwork.retrieveEntries(threadId, function(bootstrapIds, error) {
        if (error) {
          delete self._threadNetworks[threadId];
          return callback(new Error("Failed to retrieve bootstrap IDs:", error));
        }

        Utils.debug("[joinThreadNetwork] bootstrapIds:", bootstrapIds.toString());

        bootstrapIds = _.filter(bootstrapIds, function(id) {
          return Utils.isNonemptyString(id) && id.charAt(0) === 't';
        });

        if (_.isEmpty(bootstrapIds)) {
          threadNetwork.createNetwork(function(peerId, error) {
            if (error) {
              delete self._threadNetworks[threadId];
              return callback(error);
            }

            Utils.debug("Created thread network (thread ID:", threadId, ")");

            self._threadListNetwork.insertEntry(threadId, peerId);
            callback();
          });
          return;
        }

        var retryJoinNetwork = function(bootstrapIds, callback) {
          if (_.isEmpty(bootstrapIds)) {
            return callback(null, new Error("No peer ID to join is left."));
          }

          threadNetwork.joinNetwork(_.first(bootstrapIds), function(peerId, error) {
            if (error) {
              Utils.debug("Failed to connect to " + _.first(bootstrapIds), ". Retry next peer.");
              return retryJoinNetwork(_.rest(bootstrapIds), callback);
            }

            callback(peerId);
          });
        };

        retryJoinNetwork(bootstrapIds, function(peerId, error) {
          if (error) {
            delete self._threadNetworks[threadId];
            return callback(error);
          }

          Utils.debug("Joining thread network succeeded (thread ID:", threadId, ")");

          self._threadListNetwork.insertEntry(threadId, peerId);
          callback();
        });
      });
    },

    leaveThreadNetwork: function(threadId) {
      if (!_.has(this._threadNetworks, threadId)) {
        throw new Error("Unknown thread ID: " + threadId);
      }
      this._threadListNetwork.removeEntry(threadId, this._threadNetworks[threadId].getPeerId());
      this._threadNetworks[threadId].leaveNetwork();
      delete this._threadNetworks[threadId];

      Utils.debug("Left thread network (thread ID:", threadId, ")");
    },

    _replacePeerId: function(config, prefix) {
      config.peer.id = prefix + (Math.random().toString(36) + '0000000000000000000').substr(2, 16);
      return config;
    },

    _getBootstrapIds: function(callback) {
      var options = this._config.peer.options;
      var url = 'http://' + options.host + ':' + options.port + '/' + options.key + '/peers';
      $.ajax({
        url: url,
        success: function(peers) {
          if (!_.isArray(peers) || _.isEmpty(peers)) {
            Utils.debug("Retrieved no peer IDs.");
            return callback([]);
          }

          Utils.debug("[_getBootstrapIds] peers:", peers);

          peers = _.filter(peers, function(peer) { return peer.charAt(0) === 'T'; });

          callback(peers);
        },
        error: function(xhr, status, error) {
          console.log("Failed to retrieve peers: " + error);
          callback([]);
        }
      });
    },

    _onRequestReceived: function(fromPeerId, request, callback) {
      this._requestDispatcher.dispatch(fromPeerId, request, callback);
    },

    getJoiningThreadIds: function() {
      return _.keys(this._threadNetworks);
    },

    getPeerId: function(threadId) {
      if (!threadId) {
        return this._threadListNetwork.getPeerId();
      }
      if (!_.has(this._threadNetworks, threadId)) {
        throw new Error("Unknown thread ID: " + threadId);
      }
      return this._threadNetworks[threadId].getPeerId();
    },

    getPeers: function() {
      return this._peers;
    },

    getDirectConnectedPeers: function(threadId) {
      if (!threadId) {
        return this._threadListNetwork.getDirectConnectedPeers();
      }
      if (!_.has(this._threadNetworks, threadId)) {
        throw new Error("Unknown thread ID: " + threadId);
      }
      return this._threadNetworks[threadId].getDirectConnectedPeers();
    },

    getState: function(threadId) {
      if (!threadId) {
        return this._threadListNetwork.getState();
      }
      if (!_.has(this._threadNetworks, threadId)) {
        throw new Error("Unknown thread ID: " + threadId);
      }
      return this._threadNetworks[threadId].getState();
    },

    checkPeerSetting: function() {
      if (!_.isObject(this._config.peer)) {
        throw new Error("Property 'peer' is required in config object.");
      }
      if (!_.isObject(this._config.peer.options)) {
        throw new Error("Property 'options' is required in config.peer object.");
      }
      if (!Utils.isNonemptyString(this._config.peer.options.host) ||
          this._config.peer.options.host === 'YOUR PEERSERVER HOST') {
        throw new Error("Specify the PeerServer host used in the system.");
      }
      if (!Utils.isNonemptyString(this._config.peer.options.key) ||
          this._config.peer.options.key === 'YOUR KEY') {
        throw new Error("Specify the key for the PeerServer used in the system.");
      }
    }
  };

  return NetworkAgent;
});
<commit_msg>Modify NetworkAgent#_replacePeerId.<commit_after>define([
  'jquery', 'underscore', 'peerjs', 'net/BbsNetwork', 'net/RequestDispatcher', 'utils/Utils'
], function($, _, Peer, BbsNetwork, RequestDispatcher, Utils) {
  var NetworkAgent = function(config) {
    var self = this;

    this._config = config;
    this._threadListNetwork = new BbsNetwork(this._replacePeerId(
      config, 'T'
    ), function(fromPeerId, request, callback) {
      self._onRequestReceived(fromPeerId, request, callback);
    });
    this._threadNetworks = {};
    this._requestDispatcher = new RequestDispatcher();
    this._peers = [];
  };

  NetworkAgent.prototype = {
    createNetwork: function(callback) {
      this._threadListNetwork.createNetwork(callback);
    },

    joinNetwork: function(callback) {
      var self = this;

      Utils.debug("Trying to join thread list network.");

      this._getBootstrapIds(function(bootstrapIds) {
        self._peers = bootstrapIds;

        if (_.isEmpty(bootstrapIds)) {
          self.createNetwork(callback);
          return;
        }

        var retryJoinNetwork = function(bootstrapIds, callback) {
          if (_.isEmpty(bootstrapIds)) {
            return callback(null, new Error("Failed to join network."));
          }

          self._threadListNetwork.joinNetwork(_.first(bootstrapIds), function(peerId, error) {
            if (error) {
              Utils.debug("Failed to connect to", _.first(bootstrapIds), "(", error, "). Retry next peer.");
              retryJoinNetwork(_.rest(bootstrapIds), callback);
              return;
            }

            Utils.debug("Joining thread list network succeeded.");

            callback(peerId);
          });
        };
        retryJoinNetwork(bootstrapIds, callback);
      });
    },

    leaveNetwork: function() {
      var self = this;

      _.each(_.keys(this._threadNetworks), function(threadId) {
        self.leaveThreadNetwork(threadId);
      });
      this._threadListNetwork.leaveNetwork();

      Utils.debug("Left thread list network.");
    },

    fetchThreads: function(excludeIds, callback) {
      this._threadListNetwork.fetchThreads(excludeIds, callback);
    },

    spreadThread: function(threadInfo) {
      this._threadListNetwork.spreadThread(threadInfo);
    },

    fetchMessages: function(threadId, excludeIds, callback) {
      if (!_.has(this._threadNetworks, threadId)) {
        return callback(new Error("Unknown thread ID: " + threadId));
      }

      this._threadNetworks[threadId].fetchMessages(threadId, excludeIds, callback);
    },

    spreadMessage: function(messageInfo) {
      this._threadNetworks[messageInfo.threadId].spreadMessage(messageInfo);
    },

    joinThreadNetwork: function(threadId, callback) {
      var self = this;

      if (_.has(this._threadNetworks, threadId)) {
        return callback();
      }

      Utils.debug("Trying to join thread network (thread ID", threadId, ")");

      var threadNetwork = new BbsNetwork(this._replacePeerId(
        this._config, 't'
      ), function(fromPeerId, request, callback) {
        self._onRequestReceived(fromPeerId, request, callback);
      });
      this._threadNetworks[threadId] = threadNetwork;

      this._threadListNetwork.retrieveEntries(threadId, function(bootstrapIds, error) {
        if (error) {
          delete self._threadNetworks[threadId];
          return callback(new Error("Failed to retrieve bootstrap IDs:", error));
        }

        Utils.debug("[joinThreadNetwork] bootstrapIds:", bootstrapIds.toString());

        bootstrapIds = _.filter(bootstrapIds, function(id) {
          return Utils.isNonemptyString(id) && id.charAt(0) === 't';
        });

        if (_.isEmpty(bootstrapIds)) {
          threadNetwork.createNetwork(function(peerId, error) {
            if (error) {
              delete self._threadNetworks[threadId];
              return callback(error);
            }

            Utils.debug("Created thread network (thread ID:", threadId, ")");

            self._threadListNetwork.insertEntry(threadId, peerId);
            callback();
          });
          return;
        }

        var retryJoinNetwork = function(bootstrapIds, callback) {
          if (_.isEmpty(bootstrapIds)) {
            return callback(null, new Error("No peer ID to join is left."));
          }

          threadNetwork.joinNetwork(_.first(bootstrapIds), function(peerId, error) {
            if (error) {
              Utils.debug("Failed to connect to " + _.first(bootstrapIds), ". Retry next peer.");
              return retryJoinNetwork(_.rest(bootstrapIds), callback);
            }

            callback(peerId);
          });
        };

        retryJoinNetwork(bootstrapIds, function(peerId, error) {
          if (error) {
            delete self._threadNetworks[threadId];
            return callback(error);
          }

          Utils.debug("Joining thread network succeeded (thread ID:", threadId, ")");

          self._threadListNetwork.insertEntry(threadId, peerId);
          callback();
        });
      });
    },

    leaveThreadNetwork: function(threadId) {
      if (!_.has(this._threadNetworks, threadId)) {
        throw new Error("Unknown thread ID: " + threadId);
      }
      this._threadListNetwork.removeEntry(threadId, this._threadNetworks[threadId].getPeerId());
      this._threadNetworks[threadId].leaveNetwork();
      delete this._threadNetworks[threadId];

      Utils.debug("Left thread network (thread ID:", threadId, ")");
    },

    _replacePeerId: function(config, prefix) {
      var _config = _.clone(config);
      _config.peer = _.clone(config.peer);
      _config.peer.options = _.clone(config.peer.options);
      _config.peer.id = prefix + (Math.random().toString(36) + '0000000000000000000').substr(2, 16);
      return _config;
    },

    _getBootstrapIds: function(callback) {
      var options = this._config.peer.options;
      var url = 'http://' + options.host + ':' + options.port + '/' + options.key + '/peers';
      $.ajax({
        url: url,
        success: function(peers) {
          if (!_.isArray(peers) || _.isEmpty(peers)) {
            Utils.debug("Retrieved no peer IDs.");
            return callback([]);
          }

          Utils.debug("[_getBootstrapIds] peers:", peers);

          peers = _.filter(peers, function(peer) { return peer.charAt(0) === 'T'; });

          callback(peers);
        },
        error: function(xhr, status, error) {
          console.log("Failed to retrieve peers: " + error);
          callback([]);
        }
      });
    },

    _onRequestReceived: function(fromPeerId, request, callback) {
      this._requestDispatcher.dispatch(fromPeerId, request, callback);
    },

    getJoiningThreadIds: function() {
      return _.keys(this._threadNetworks);
    },

    getPeerId: function(threadId) {
      if (!threadId) {
        return this._threadListNetwork.getPeerId();
      }
      if (!_.has(this._threadNetworks, threadId)) {
        throw new Error("Unknown thread ID: " + threadId);
      }
      return this._threadNetworks[threadId].getPeerId();
    },

    getPeers: function() {
      return this._peers;
    },

    getDirectConnectedPeers: function(threadId) {
      if (!threadId) {
        return this._threadListNetwork.getDirectConnectedPeers();
      }
      if (!_.has(this._threadNetworks, threadId)) {
        throw new Error("Unknown thread ID: " + threadId);
      }
      return this._threadNetworks[threadId].getDirectConnectedPeers();
    },

    getState: function(threadId) {
      if (!threadId) {
        return this._threadListNetwork.getState();
      }
      if (!_.has(this._threadNetworks, threadId)) {
        throw new Error("Unknown thread ID: " + threadId);
      }
      return this._threadNetworks[threadId].getState();
    },

    checkPeerSetting: function() {
      if (!_.isObject(this._config.peer)) {
        throw new Error("Property 'peer' is required in config object.");
      }
      if (!_.isObject(this._config.peer.options)) {
        throw new Error("Property 'options' is required in config.peer object.");
      }
      if (!Utils.isNonemptyString(this._config.peer.options.host) ||
          this._config.peer.options.host === 'YOUR PEERSERVER HOST') {
        throw new Error("Specify the PeerServer host used in the system.");
      }
      if (!Utils.isNonemptyString(this._config.peer.options.key) ||
          this._config.peer.options.key === 'YOUR KEY') {
        throw new Error("Specify the key for the PeerServer used in the system.");
      }
    }
  };

  return NetworkAgent;
});
<|endoftext|>


<commit_before>var _ = require('lodash');
var phantom = require('phantom');
var temp = require('temp');
var fs = require('fs');

// default viewport options for phantom. we will tweak these to match
// the browser frame that we will fit the page into. NOTE: phantom is
// a mess and probably doesn't enjoy rendering pages from 1998 either
var viewportOpts = {
    width: 1200,
    height: 1000
};

var phantomActions = function() {
    // trigger in-page js to close wayback machine nav
    __wm.h();

    //
    // inject a function to iterate through all text nodes in the body, so we can clean them up a bit
    //
    function nativeSelector() {
        var walker = document.createTreeWalker(
            document.body,
            NodeFilter.SHOW_TEXT,
            null,
            false
        );

        var node;
        var textNodes = [];

        // this is silly because there's no logic here, so we could just
        // pass in a function to run against the node, but leaving for now
        while((node = walker.nextNode())) {
            textNodes.push(node);
        }

        return textNodes;
    }

    var textnodes = nativeSelector(),
        _nv;
    for (var i = 0, len = textnodes.length; i<len; i++){
        _nv = textnodes[i].textContent;

        // attempt to strip email addresses and phone numbers from output
        _nv = _nv.replace(/[A-Za-z0-9_\-\.]+\@/g, '░░░░░@').
            replace(/[\(\+]?\b[ 0-9\-\(\)+^'^"^<^>]{10,14}\b/g, function(m) { return m.replace(/[0-9]/g, "x"); });

        textnodes[i].textContent = _nv;
    }

};

var path = require('path');
var frames = JSON.parse(fs.readFileSync(path.resolve(__dirname, 'frames.json')));

var wrap = function(src, p, frame) {
    var exec = require('child_process').execFileSync;

    var pointsize = frame["caption-font-size"] || 14;
    var caption_bgcolor = frame["caption-bgcolor"] || "white";

    var text = temp.path({prefix:'text', suffix:'.png'});
    var command = [
        "-background", "rgba(0,0,0,0.0)",
        "-fill", "black",
        "-font", "font.ttf",
        "-pointsize", pointsize,
        "label:" + p.url,
        text
    ];

    var dest = temp.path({prefix: 'results', suffix: '.png'});
    console.log(command.join(' '));
    exec('convert', command);

    command = [ src, 'images/' + frame.name,
                '-geometry', '+' + frame.x + '+' + frame.y,
                dest];
    console.log(command.join(' '));

    exec('composite', command);

    if ( frame['caption-x']) {
        command = [ text, dest,
                    '-geometry', '+' + (frame['caption-x'] + 3) + '+' + (frame['caption-y'] + 3),
                    dest];
        console.log(command.join(' '));

        exec('composite', command);
    }

    return dest;

};

var render = function(p, cb) {
    var url = "https://web.archive.org/web/" + p.tstamp + "/" + p.url;
    console.log(url);

    var frame = _.sample(frames);

    phantom.create(function (ph) {
        ph.createPage(function (page) {
            page.open(url, function (status) {
                console.log("status? ", status);

                // set the size of the browser to be the size of the interior of the frame
                if ( p.wrap !== "undefined" && p.wrap === true ) {
                    viewportOpts.width = frame.w;
                    viewportOpts.height = frame.h;
                }
                else {
                    console.log("no frame so use default viewport");
                }

                page.set('viewportSize', viewportOpts);
                page.set('clipRect', viewportOpts);

                page.evaluate(phantomActions, function() {

                    var guts = temp.path({prefix: 'page', suffix: '.png'});
                    page.render(guts, function() {
                        var dest;
                        console.log("**** " + p.wrap);
                        if ( p.wrap !== "undefined" && p.wrap === true ) {
                            dest = wrap(guts, p, frame);
                        }
                        else {
                            console.log("no frame!");
                            dest = guts;
                        }

                        console.log(dest);
                        ph.exit();

                        cb(dest);

                    }); // render
                }); // evaluate
            }); // open

        });

    }, {
        dnodeOpts: {weak: false}
    });

};

exports.render = render;
/*
render({ id: 1318,
         url: 'http://www.hiway.com/',
         tstamp: '19961222133514',
         title: 'Systems',
         generator: '',
         score: 84,
         created_at: "Wed Oct 14 2015 22:24:43 GMT+0000 (UTC)",
         posted_at: null
       }, function(dest) { console.log(dest); });
*/<commit_msg>iterate through any frames in this page to close the wayback machine js widget if it exists<commit_after>var _ = require('lodash');
var phantom = require('phantom');
var temp = require('temp');
var fs = require('fs');

// default viewport options for phantom. we will tweak these to match
// the browser frame that we will fit the page into. NOTE: phantom is
// a mess and probably doesn't enjoy rendering pages from 1998 either
var viewportOpts = {
    width: 1200,
    height: 1000
};

var phantomActions = function() {
    // trigger in-page js to close wayback machine nav
    if ( typeof(__wm) !== "undefined" ) {
        __wm.h();
    }

    // try and close WM js on any frames
    var list = Array.prototype.slice.call( document.getElementsByTagName("frame") );
    list.forEach(function(f) {
        if ( f && f.contentWindow && f.contentWindow.__wm ) {
            f.contentWindow.__wm.h();
        }
    });

    //
    // inject a function to iterate through all text nodes in the body, so we can clean them up a bit
    //
    function nativeSelector() {
        var walker = document.createTreeWalker(
            document.body,
            NodeFilter.SHOW_TEXT,
            null,
            false
        );

        var node;
        var textNodes = [];

        // this is silly because there's no logic here, so we could just
        // pass in a function to run against the node, but leaving for now
        while((node = walker.nextNode())) {
            textNodes.push(node);
        }

        return textNodes;
    }

    var textnodes = nativeSelector(),
        _nv;
    for (var i = 0, len = textnodes.length; i<len; i++){
        _nv = textnodes[i].textContent;

        // attempt to strip email addresses and phone numbers from output
        _nv = _nv.replace(/[A-Za-z0-9_\-\.]+\@/g, '░░░░░@').
            replace(/[\(\+]?\b[ 0-9\-\(\)+^'^"^<^>]{10,14}\b/g, function(m) { return m.replace(/[0-9]/g, "x"); });

        textnodes[i].textContent = _nv;
    }

};

var path = require('path');
var frames = JSON.parse(fs.readFileSync(path.resolve(__dirname, 'frames.json')));

var wrap = function(src, p, frame) {
    var exec = require('child_process').execFileSync;

    var pointsize = frame["caption-font-size"] || 14;
    var caption_bgcolor = frame["caption-bgcolor"] || "white";

    var text = temp.path({prefix:'text', suffix:'.png'});
    var command = [
        "-background", "rgba(0,0,0,0.0)",
        "-fill", "black",
        "-font", "font.ttf",
        "-pointsize", pointsize,
        "label:" + p.url,
        text
    ];

    var dest = temp.path({prefix: 'results', suffix: '.png'});
    console.log(command.join(' '));
    exec('convert', command);

    command = [ src, 'images/' + frame.name,
                '-geometry', '+' + frame.x + '+' + frame.y,
                dest];
    console.log(command.join(' '));

    exec('composite', command);

    if ( frame['caption-x']) {
        command = [ text, dest,
                    '-geometry', '+' + (frame['caption-x'] + 3) + '+' + (frame['caption-y'] + 3),
                    dest];
        console.log(command.join(' '));

        exec('composite', command);
    }

    return dest;

};

var render = function(p, cb) {
    var url = "https://web.archive.org/web/" + p.tstamp + "/" + p.url;
    console.log(url);

    var frame = _.sample(frames);

    phantom.create(function (ph) {
        ph.createPage(function (page) {
            page.open(url, function (status) {
                console.log("status? ", status);

                // set the size of the browser to be the size of the interior of the frame
                if ( p.wrap !== "undefined" && p.wrap === true ) {
                    viewportOpts.width = frame.w;
                    viewportOpts.height = frame.h;
                }
                else {
                    console.log("no frame so use default viewport");
                }

                page.set('viewportSize', viewportOpts);
                page.set('clipRect', viewportOpts);

                page.evaluate(phantomActions, function() {

                    var guts = temp.path({prefix: 'page', suffix: '.png'});
                    page.render(guts, function() {
                        var dest;
                        console.log("**** " + p.wrap);
                        if ( p.wrap !== "undefined" && p.wrap === true ) {
                            dest = wrap(guts, p, frame);
                        }
                        else {
                            console.log("no frame!");
                            dest = guts;
                        }

                        console.log(dest);
                        ph.exit();

                        cb(dest);

                    }); // render
                }); // evaluate
            }); // open

        });

    }, {
        dnodeOpts: {weak: false}
    });

};

exports.render = render;
/**
render({ id: 1318,
         url: 'http://yahoo.com/',
         tstamp: '19981206224454',
         title: 'Systems',
         generator: '',
         score: 84,
         created_at: "Wed Oct 14 2015 22:24:43 GMT+0000 (UTC)",
         posted_at: null
       }, function(dest) { console.log(dest); });
*/<|endoftext|>


<commit_before>var sender = require('unifiedpush-node-sender');
var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors');
var optval = require('optval');
var util = require('util');
var winston = require('winston')
var requestId = require('connect-requestid');

validateEnvVar('AEROGEAR_SERVER_URL');
validateEnvVar('AEROGEAR_APPLICATION_ID');
validateEnvVar('AEROGEAR_MASTER_SECRET');

var settings = {
  serverUrl: process.env.AEROGEAR_SERVER_URL,
  applicationID: process.env.AEROGEAR_APPLICATION_ID,
  masterSecret: process.env.AEROGEAR_MASTER_SECRET,
  ttl: parseInt(optval(process.env.AEROGEAR_TTL, 3600), 10)
};

function validateEnvVar(envVar) {
  winston.info('Validating Environment variable "' + envVar + '"');
  if( optval(process.env[envVar], null) === null) {
    winston.error('ERROR: Required environment variable "' + envVar + '" not defined. Please set this environment variable via the Environment Variables section of your service')
  };
}

function sendRoute() {
  var send = new express.Router();
  send.use(cors());
  send.use(bodyParser());
  send.use(requestId);

  // POST REST endpoint - note we use 'body-parser' middleware above to parse the request body in this route.
  // This can also be added in application.js
  // See: https://github.com/senchalabs/connect#middleware for a list of Express 4 middleware
  send.post('/', function(req, res) {
    winston.info(req.id, 'In send route POST / req.body =', util.inspect(req.body));

    if( optval(req.body.message, null) === null) {
      // see http://expressjs.com/4x/api.html#res.json
      var message = 'Required JSON Object "message" not provided.'
      winston.warn(req.id, message, util.inspect(req.body));
      return res.status(400).json({'status' : 'error', 'messages' : message});
    }

    if( optval(req.body.message.alert, null) === null) {
      // see http://expressjs.com/4x/api.html#res.json
      var message = 'Required parameter "alert" not provided in message object.'
      winston.warn(req.id, message, util.inspect(req.body.message));
      return res.status(400).json({'status' : 'error', 'messages' : message});
    }

    var message = req.body.message;

    // Set defaults for optional parameters
    message.sound = optval(req.body.message.sound, 'default');
    message.badge = optval(req.body.message.badge, 2);
    message.contentAvailable = optval(req.body.message.contentAvailable, true);

    winston.info(req.id, "Sending message :", util.inspect(message));

    sender.Sender(settings.serverUrl).send(message, settings, function(err) {
      if (err) {
        winston.warn(req.id, 'Error calling push service - ', err);
        return res.status(500).json({'status':'error', 'message':err});
      }

      res.json({'status' : 'ok'});
    });
  });

  return send;
}

module.exports = sendRoute;
<commit_msg>simple push<commit_after>var sender = require('unifiedpush-node-sender');
var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors');
var optval = require('optval');
var util = require('util');
var winston = require('winston')
var requestId = require('connect-requestid');

validateEnvVar('AEROGEAR_SERVER_URL');
validateEnvVar('AEROGEAR_APPLICATION_ID');
validateEnvVar('AEROGEAR_MASTER_SECRET');

var settings = {
  serverUrl: process.env.AEROGEAR_SERVER_URL,
  applicationID: process.env.AEROGEAR_APPLICATION_ID,
  masterSecret: process.env.AEROGEAR_MASTER_SECRET,
  ttl: parseInt(optval(process.env.AEROGEAR_TTL, 3600), 10)
};

function validateEnvVar(envVar) {
  winston.info('Validating Environment variable "' + envVar + '"');
  if( optval(process.env[envVar], null) === null) {
    winston.error('ERROR: Required environment variable "' + envVar + '" not defined. Please set this environment variable via the Environment Variables section of your service')
  };
}

function sendRoute() {
  var send = new express.Router();
  send.use(cors());
  send.use(bodyParser());
  send.use(requestId);

  // POST REST endpoint - note we use 'body-parser' middleware above to parse the request body in this route.
  // This can also be added in application.js
  // See: https://github.com/senchalabs/connect#middleware for a list of Express 4 middleware
  send.post('/', function(req, res) {
    winston.info(req.id, 'In send route POST / req.body =', util.inspect(req.body));

    if( optval(req.body.message, null) === null) {
      // see http://expressjs.com/4x/api.html#res.json
      var message = 'Required JSON Object "message" not provided.'
      winston.warn(req.id, message, util.inspect(req.body));
      return res.status(400).json({'status' : 'error', 'messages' : message});
    }

    if( optval(req.body.message.alert, null) === null) {
      // see http://expressjs.com/4x/api.html#res.json
      var message = 'Required parameter "alert" not provided in message object.'
      winston.warn(req.id, message, util.inspect(req.body.message));
      return res.status(400).json({'status' : 'error', 'messages' : message});
    }

    var message = req.body.message;

    // Set defaults for optional parameters
    message.sound = optval(req.body.message.sound, 'default');
    message.badge = optval(req.body.message.badge, 2);
    message.contentAvailable = optval(req.body.message.contentAvailable, true);

    winston.info(req.id, "Sending message :", util.inspect(message));

    settings.simplePush = 'version=' + new Date().getTime();
    sender.Sender(settings.serverUrl).send(message, settings, function(err) {
      if (err) {
        winston.warn(req.id, 'Error calling push service - ', err);
        return res.status(500).json({'status':'error', 'message':err});
      }

      res.json({'status' : 'ok'});
    });
  });

  return send;
}

module.exports = sendRoute;
<|endoftext|>


<commit_before>module.exports = Backbone.View.extend({
    tagName: 'div',
    className: 'gallery-item',
    initialize: function (opts) {
        opts = opts || {};
        this.annotator = opts.annotator;
        this.metadataView = opts.metadataView;
    },
    render: function() {
        this.$el.html(JST.gallery_item({
            url: this.model.get('url'),
            title: this.model.get('metadata').get('title')
        }));
        var img = this.model.get('image');
        this.$('a').append(img);
        return this;
    },
    events: {
        'change input': 'onSelect',
        'click .picker': 'onPick'
    },
    onSelect: function () {
        this.model.set('selected', !this.model.get('selected'));
        this.$el.toggleClass('active');
    },
    onPick: function () {
        this.annotator.setImage(this.model.get('image'));
        this.metadataView.save();
        this.metadataView.activeImage = this.model;
        this.metadataView.update(this.model.get('metadata'));
    }
});
<commit_msg>clone image to fix dimensions<commit_after>module.exports = Backbone.View.extend({
    tagName: 'div',
    className: 'gallery-item',
    initialize: function (opts) {
        opts = opts || {};
        this.annotator = opts.annotator;
        this.metadataView = opts.metadataView;
    },
    render: function() {
        this.$el.html(JST.gallery_item({
            url: this.model.get('url'),
            title: this.model.get('metadata').get('title')
        }));
        var img = this.model.get('image');
        this.$('a').append(img);
        return this;
    },
    events: {
        'change input': 'onSelect',
        'click .picker': 'onPick'
    },
    onSelect: function () {
        this.model.set('selected', !this.model.get('selected'));
        this.$el.toggleClass('active');
    },
    onPick: function () {
        this.annotator.setImage(this.model.get('image').clone());
        this.metadataView.save();
        this.metadataView.activeImage = this.model;
        this.metadataView.update(this.model.get('metadata'));
    }
});
<|endoftext|>


<commit_before>import $ from 'jquery';
import { clearStyles } from '../util';

export default function () {
    let jews = {};
    var $ = function (b) { return document.querySelector(b); },
        a = [].slice.call($('.arvdate').childNodes).filter(function (v) { return v.nodeType === 3; })[0].textContent.trim();
    jews.title = $('.hbox>h2').textContent.trim();
    jews.subtitle = $('.hbox>h3').textContent.trim();
    jews.reporters = [{
        'name': $('.arvdate>a').textContent.replace('뉴데일리경제', '').trim(),
        'mail': a.match(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b/i)[0]
    }];
    jews.timestamp = {
        'created': new Date(a.match(/\d{4}\.\d{2}.\d{2}\s+\d{2}:\d{2}:\d{2}/)[0].replace(/\./g, '-').replace(/\s+/, 'T') + '+09:00'), // ISO 8601
        'lastModified': undefined
    };
    jews.content = clearStyles(document.getElementById('news_body_area')).innerHTML;
    return jews;
}
<commit_msg>Remove jQuery from 뉴데일리경제<commit_after>import { clearStyles } from '../util';

export default function () {
    let jews = {};
    var $ = function (b) { return document.querySelector(b); },
        a = [].slice.call($('.arvdate').childNodes).filter(function (v) { return v.nodeType === 3; })[0].textContent.trim();
    jews.title = $('.hbox>h2').textContent.trim();
    jews.subtitle = $('.hbox>h3').textContent.trim();
    jews.reporters = [{
        'name': $('.arvdate>a').textContent.replace('뉴데일리경제', '').trim(),
        'mail': a.match(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b/i)[0]
    }];
    jews.timestamp = {
        'created': new Date(a.match(/\d{4}\.\d{2}.\d{2}\s+\d{2}:\d{2}:\d{2}/)[0].replace(/\./g, '-').replace(/\s+/, 'T') + '+09:00'), // ISO 8601
        'lastModified': undefined
    };
    jews.content = clearStyles(document.getElementById('news_body_area')).innerHTML;
    return jews;
}
<|endoftext|>


<commit_before>"use strict";

const options = sortAndAddNameKey({
  "bracket-spacing": {
    type: "boolean",
    isFormatOption: true,
    isHidden: true
  },
  color: {
    // The supports-color package (a sub sub dependency) looks directly at
    // `process.argv` for `--no-color` and such-like options. The reason it is
    // listed here is to avoid "Ignored unknown option: --no-color" warnings.
    // See https://github.com/chalk/supports-color/#info for more information.
    type: "boolean",
    default: true,
    isHidden: true
  },
  config: {
    type: "path",
    description:
      "Path to a prettier configuration file (.prettierrc, package.json, prettier.config.js)."
  },
  "config-precedence": {
    type: "choice",
    default: "cli-override",
    choices: ["cli-override", "file-override", "prefer-file"],
    description: dedent(`
      Defines how config file should be evaluated in combination of CLI options
      cli-override  | default config => config file => CLI options
      file-override | default config => CLI options => config file
      prefer-file   | default config => config file (if config file is found) or
                      default config => CLI options (if no config file is found)
      Defaults to cli-override
    `)
  },
  "cursor-offset": {
    type: "int",
    isFormatOption: true,
    description: dedent(`
      Print (to stderr) where a cursor at the given position would move to after formatting.
      This option cannot be used with --range-start and --range-end
    `)
  },
  "debug-check": {
    type: "boolean",
    isHidden: true
  },
  "debug-print-doc": {
    type: "boolean",
    isHidden: true
  },
  "find-config-path": {
    type: "path",
    description:
      "Finds and prints the path to a configuration file for a given input file."
  },
  "flow-parser": {
    // Deprecated in 0.0.10
    type: "boolean",
    isHidden: true,
    isFormatOption: true
  },
  help: {
    type: "boolean",
    alias: "h",
    description: "Show help"
  },
  "ignore-path": {
    type: "path",
    default: ".prettierignore",
    description: dedent(`
      Path to a file containing patterns that describe files to ignore.
      Defaults to ./.prettierignore.
    `)
  },
  "jsx-bracket-same-line": {
    type: "boolean",
    isFormatOption: true,
    description: "Put > on the last line instead of at a new line."
  },
  "list-different": {
    type: "boolean",
    alias: "l",
    description:
      "Print filenames of files that are different from Prettier formatting."
  },
  "no-bracket-spacing": {
    type: "boolean",
    isDocsOnly: true,
    description: "Do not print spaces between brackets."
  },
  "no-color": {
    type: "boolean",
    isDocsOnly: true,
    description: "Do not colorize error messages."
  },
  "no-config": {
    type: "boolean",
    isDocsOnly: true,
    description: "Do not look for a configuration file."
  },
  "no-semi": {
    type: "boolean",
    isDocsOnly: true,
    description:
      "Do not print semicolons, except at the beginning of lines which may need them."
  },
  parser: {
    type: "choice",
    isFormatOption: true,
    choices: ["flow", "babylon", "typescript", "postcss", "json", "graphql"],
    description: "Specify which parse to use. Defaults to babylon."
  },
  "print-width": {
    type: "int",
    isFormatOption: true,
    description:
      "Specify the length of line that the printer will wrap on. Defaults to 80."
  },
  "range-end": {
    type: "int",
    isFormatOption: true,
    description: dedent(`
      Format code ending at a given character offset (exclusive).
      The range will extend forwards to the end of the selected statement.
      This option cannot be used with --cursor-offset.
      Defaults to Infinity.
    `)
  },
  "range-start": {
    type: "int",
    isFormatOption: true,
    description: dedent(`
      Format code starting at a given character offset.
      The range will extend backwards to the start of the first line containing the selected statement.
      This option cannot be used with --cursor-offset.
      Defaults to 0.
    `)
  },
  semi: {
    type: "boolean",
    isFormatOption: true,
    isHidden: true
  },
  "single-quote": {
    type: "boolean",
    isFormatOption: true,
    description: "Use single quotes instead of double quotes."
  },
  stdin: {
    type: "boolean",
    description: "Read input from stdin."
  },
  "stdin-filepath": {
    type: "path",
    description: "Path to the file used to read from stdin."
  },
  "tab-width": {
    type: "int",
    isFormatOption: true,
    description:
      "Specify the number of spaces per indentation-level. Defaults to 2."
  },
  "trailing-comma": {
    type: "choice",
    isFormatOption: true,
    choices: ["none", "es5", "all"],
    description:
      "Print trailing commas wherever possible when multi-line. Defaults to none."
  },
  "use-tabs": {
    type: "boolean",
    isFormatOption: true,
    description: "Indent lines with tabs instead of spaces."
  },
  version: {
    type: "boolean",
    alias: "v",
    description: "Print Prettier version."
  },
  "with-node-modules": {
    type: "boolean",
    description: "Process files inside 'node_modules' directory."
  },
  write: {
    type: "boolean",
    description: "Edit the file in-place. (Beware!)"
  }
});

const optionArray = Object.keys(options).reduce(
  (current, name) => current.concat(options[name]),
  []
);

const booleanOptionNames = optionArray
  .filter(option => option.isFormatOption && option.type === "boolean")
  .map(option => option.name);

const stringOptionNames = optionArray
  .filter(option => option.isFormatOption && option.type !== "boolean")
  .map(option => option.name);

const minimistOptions = {
  boolean: optionArray
    .filter(option => !option.isDocsOnly && option.type === "boolean")
    .map(option => option.name),
  string: optionArray
    .filter(option => !option.isDocsOnly && option.type !== "boolean")
    .map(option => option.name),
  default: optionArray
    .filter(option => option.default !== undefined)
    .reduce(
      (current, option) =>
        Object.assign({ [option.name]: option.default }, current),
      {}
    ),
  alias: optionArray
    .filter(option => option.alias !== undefined)
    .reduce(
      (current, option) =>
        Object.assign({ [option.name]: option.alias }, current),
      {}
    ),
  unknown: param => {
    if (param.startsWith("-")) {
      console.warn(`Ignored unknown option: ${param}\n`);
      return false;
    }
  }
};

const usage = `
Usage: prettier [opts] [filename ...]

Available options:
${indent(
  optionArray
    .filter(option => !option.isHidden)
    .map(option => createOptionUsage(option.name, option))
    .join("\n"),
  2
)}

`.slice(1); // remove leading line break

function createOptionUsage(name, option) {
  const threshold = 25;

  let header = `--${name}`;

  if (option.alias) {
    header += ` or -${option.alias}`;
  }

  switch (option.type) {
    case "boolean":
      // do nothing
      break;
    case "choice":
      header += ` <${option.choices.join("|")}>`;
      break;
    default:
      header += ` <${option.type}>`;
      break;
  }

  if (header.length >= threshold) {
    header += "\n" + " ".repeat(threshold);
  } else {
    header += " ".repeat(threshold - header.length);
  }

  return (
    header + option.description.replace(/\n/g, "\n" + " ".repeat(threshold))
  );
}

function indent(str, spaces) {
  return str.replace(/^/gm, " ".repeat(spaces));
}

function dedent(str) {
  const spaces = str.match(/\n^( +)/m)[1].length;
  return str.replace(new RegExp(`^ {${spaces}}`, "gm"), "").trim();
}

function sortAndAddNameKey(obj) {
  return Object.keys(obj)
    .sort()
    .reduce(
      (current, name) =>
        Object.assign(current, { [name]: Object.assign({ name }, obj[name]) }),
      {}
    );
}

module.exports = {
  booleanOptionNames,
  stringOptionNames,
  minimistOptions,
  options,
  usage
};
<commit_msg>refactor: no need to pass additional arg<commit_after>"use strict";

const options = sortAndAddNameKey({
  "bracket-spacing": {
    type: "boolean",
    isFormatOption: true,
    isHidden: true
  },
  color: {
    // The supports-color package (a sub sub dependency) looks directly at
    // `process.argv` for `--no-color` and such-like options. The reason it is
    // listed here is to avoid "Ignored unknown option: --no-color" warnings.
    // See https://github.com/chalk/supports-color/#info for more information.
    type: "boolean",
    default: true,
    isHidden: true
  },
  config: {
    type: "path",
    description:
      "Path to a prettier configuration file (.prettierrc, package.json, prettier.config.js)."
  },
  "config-precedence": {
    type: "choice",
    default: "cli-override",
    choices: ["cli-override", "file-override", "prefer-file"],
    description: dedent(`
      Defines how config file should be evaluated in combination of CLI options
      cli-override  | default config => config file => CLI options
      file-override | default config => CLI options => config file
      prefer-file   | default config => config file (if config file is found) or
                      default config => CLI options (if no config file is found)
      Defaults to cli-override
    `)
  },
  "cursor-offset": {
    type: "int",
    isFormatOption: true,
    description: dedent(`
      Print (to stderr) where a cursor at the given position would move to after formatting.
      This option cannot be used with --range-start and --range-end
    `)
  },
  "debug-check": {
    type: "boolean",
    isHidden: true
  },
  "debug-print-doc": {
    type: "boolean",
    isHidden: true
  },
  "find-config-path": {
    type: "path",
    description:
      "Finds and prints the path to a configuration file for a given input file."
  },
  "flow-parser": {
    // Deprecated in 0.0.10
    type: "boolean",
    isHidden: true,
    isFormatOption: true
  },
  help: {
    type: "boolean",
    alias: "h",
    description: "Show help"
  },
  "ignore-path": {
    type: "path",
    default: ".prettierignore",
    description: dedent(`
      Path to a file containing patterns that describe files to ignore.
      Defaults to ./.prettierignore.
    `)
  },
  "jsx-bracket-same-line": {
    type: "boolean",
    isFormatOption: true,
    description: "Put > on the last line instead of at a new line."
  },
  "list-different": {
    type: "boolean",
    alias: "l",
    description:
      "Print filenames of files that are different from Prettier formatting."
  },
  "no-bracket-spacing": {
    type: "boolean",
    isDocsOnly: true,
    description: "Do not print spaces between brackets."
  },
  "no-color": {
    type: "boolean",
    isDocsOnly: true,
    description: "Do not colorize error messages."
  },
  "no-config": {
    type: "boolean",
    isDocsOnly: true,
    description: "Do not look for a configuration file."
  },
  "no-semi": {
    type: "boolean",
    isDocsOnly: true,
    description:
      "Do not print semicolons, except at the beginning of lines which may need them."
  },
  parser: {
    type: "choice",
    isFormatOption: true,
    choices: ["flow", "babylon", "typescript", "postcss", "json", "graphql"],
    description: "Specify which parse to use. Defaults to babylon."
  },
  "print-width": {
    type: "int",
    isFormatOption: true,
    description:
      "Specify the length of line that the printer will wrap on. Defaults to 80."
  },
  "range-end": {
    type: "int",
    isFormatOption: true,
    description: dedent(`
      Format code ending at a given character offset (exclusive).
      The range will extend forwards to the end of the selected statement.
      This option cannot be used with --cursor-offset.
      Defaults to Infinity.
    `)
  },
  "range-start": {
    type: "int",
    isFormatOption: true,
    description: dedent(`
      Format code starting at a given character offset.
      The range will extend backwards to the start of the first line containing the selected statement.
      This option cannot be used with --cursor-offset.
      Defaults to 0.
    `)
  },
  semi: {
    type: "boolean",
    isFormatOption: true,
    isHidden: true
  },
  "single-quote": {
    type: "boolean",
    isFormatOption: true,
    description: "Use single quotes instead of double quotes."
  },
  stdin: {
    type: "boolean",
    description: "Read input from stdin."
  },
  "stdin-filepath": {
    type: "path",
    description: "Path to the file used to read from stdin."
  },
  "tab-width": {
    type: "int",
    isFormatOption: true,
    description:
      "Specify the number of spaces per indentation-level. Defaults to 2."
  },
  "trailing-comma": {
    type: "choice",
    isFormatOption: true,
    choices: ["none", "es5", "all"],
    description:
      "Print trailing commas wherever possible when multi-line. Defaults to none."
  },
  "use-tabs": {
    type: "boolean",
    isFormatOption: true,
    description: "Indent lines with tabs instead of spaces."
  },
  version: {
    type: "boolean",
    alias: "v",
    description: "Print Prettier version."
  },
  "with-node-modules": {
    type: "boolean",
    description: "Process files inside 'node_modules' directory."
  },
  write: {
    type: "boolean",
    description: "Edit the file in-place. (Beware!)"
  }
});

const optionArray = Object.keys(options).reduce(
  (current, name) => current.concat(options[name]),
  []
);

const booleanOptionNames = optionArray
  .filter(option => option.isFormatOption && option.type === "boolean")
  .map(option => option.name);

const stringOptionNames = optionArray
  .filter(option => option.isFormatOption && option.type !== "boolean")
  .map(option => option.name);

const minimistOptions = {
  boolean: optionArray
    .filter(option => !option.isDocsOnly && option.type === "boolean")
    .map(option => option.name),
  string: optionArray
    .filter(option => !option.isDocsOnly && option.type !== "boolean")
    .map(option => option.name),
  default: optionArray
    .filter(option => option.default !== undefined)
    .reduce(
      (current, option) =>
        Object.assign({ [option.name]: option.default }, current),
      {}
    ),
  alias: optionArray
    .filter(option => option.alias !== undefined)
    .reduce(
      (current, option) =>
        Object.assign({ [option.name]: option.alias }, current),
      {}
    ),
  unknown: param => {
    if (param.startsWith("-")) {
      console.warn(`Ignored unknown option: ${param}\n`);
      return false;
    }
  }
};

const usage = `
Usage: prettier [opts] [filename ...]

Available options:
${indent(
  optionArray
    .filter(option => !option.isHidden)
    .map(createOptionUsage)
    .join("\n"),
  2
)}

`.slice(1); // remove leading line break

function createOptionUsage(option) {
  const threshold = 25;

  let header = `--${option.name}`;

  if (option.alias) {
    header += ` or -${option.alias}`;
  }

  switch (option.type) {
    case "boolean":
      // do nothing
      break;
    case "choice":
      header += ` <${option.choices.join("|")}>`;
      break;
    default:
      header += ` <${option.type}>`;
      break;
  }

  if (header.length >= threshold) {
    header += "\n" + " ".repeat(threshold);
  } else {
    header += " ".repeat(threshold - header.length);
  }

  return (
    header + option.description.replace(/\n/g, "\n" + " ".repeat(threshold))
  );
}

function indent(str, spaces) {
  return str.replace(/^/gm, " ".repeat(spaces));
}

function dedent(str) {
  const spaces = str.match(/\n^( +)/m)[1].length;
  return str.replace(new RegExp(`^ {${spaces}}`, "gm"), "").trim();
}

function sortAndAddNameKey(obj) {
  return Object.keys(obj)
    .sort()
    .reduce(
      (current, name) =>
        Object.assign(current, { [name]: Object.assign({ name }, obj[name]) }),
      {}
    );
}

module.exports = {
  booleanOptionNames,
  stringOptionNames,
  minimistOptions,
  options,
  usage
};
<|endoftext|>