<commit_before>var numbers = require('../numbers');
var calculus = exports;

/**
 * Calculate point differential for a specified function at a
 * specified point.  For functions of one variable.
 *
 * @param {Function} math function to be evaluated
 * @param {Number} point to be evaluated
 * @return {Number} result
 */
calculus.pointDiff = function (func, point) {
  var a = func(point - 1e-15);
  var b = func(point + 1e-15);

  return (b - a) / (Number.MIN_VALUE*2);
};

/**
 * Calculate riemann sum for a specified, one variable, function
 * from a starting point, to a finishing point, with n divisions.
 *
 * @param {Function} math function to be evaluated
 * @param {Number} point to initiate evaluation
 * @param {Number} point to complete evaluation
 * @param {Number} quantity of divisions
 * @param {Function} (Optional) Function that returns which value
 * to sample on each interval; if none is provided, left endpoints
 * will be used.
 * @return {Number} result
 */
calculus.riemann = function (func, start, finish, n, sampler) {
  var inc = (finish - start) / n, totalHeight = 0, i;

  if (typeof sampler === 'function') {
    for (i = start; i < finish; i += inc) {
      totalHeight += func(sampler(i, i + inc));
    }
  } else {
    for (i = start; i < finish; i += inc) {
      totalHeight += func(i);
    }
  }

  return totalHeight * inc;
};

/**
 * Helper function in calculating integral of a function
 * from a to b using simpson quadrature.
 *
 * @param {Function} math function to be evaluated
 * @param {Number} point to initiate evaluation
 * @param {Number} point to complete evaluation
 * @return {Number} evaluation
 */
function simpsonDef (func, a, b) {
  var c = (a + b) / 2;
  var d = Math.abs(b - a) / 6;
  return d * (func(a) + 4 * func(c) + func(b));
}

/**
 * Helper function in calculating integral of a function
 * from a to b using simpson quadrature.  Manages recursive
 * investigation, handling evaluations within an error bound.
 *
 * @param {Function} math function to be evaluated
 * @param {Number} point to initiate evaluation
 * @param {Number} point to complete evaluation
 * @param {Number} total value
 * @param {Number} Error bound (epsilon)
 * @return {Number} recursive evaluation of left and right side
 */
function simpsonRecursive (func, a, b, whole, eps) {
  var c = a + b,
      left = simpsonDef(func, a, c),
      right = simpsonDef(func, c, b);

  if (Math.abs(left + right - whole) <= 15 * eps) {
    return left + right + (left + right - whole) / 15;
  } else {
    return simpsonRecursive(func, a, c, eps/2, left) + simpsonRecursive(func, c, b, eps / 2, right);
  }
}

/**
 * Evaluate area under a curve using adaptive simpson quadrature.
 *
 * @param {Function} math function to be evaluated
 * @param {Number} point to initiate evaluation
 * @param {Number} point to complete evaluation
 * @param {Number} Optional error bound (epsilon);
 * global error bound will be used as a fallback.
 * @return {Number} area underneath curve
 */
calculus.adaptiveSimpson = function (func, a, b, eps) {
  eps = (typeof eps === "undefined") ? numbers.EPSILON : eps;

  return simpsonRecursive(func, a, b, simpsonDef(func, a, b), eps);
};

/**
 * Calculate limit of a function at a given point.  Can approach from
 * left, middle, or right.
 *
 * @param {Function} math function to be evaluated
 * @param {Number} point to evaluate
 * @param {String} approach to limit
 * @return {Number} limit
 */
calculus.limit = function (func, point, approach) {
  if (approach === 'left') {
    return func(point - Number.MIN_VALUE);
  } else if (approach === 'right') {
    return func(point + Number.MIN_VALUE);
  } else if (approach === 'middle') {
    return (calculus.limit(func, point, 'left') + calculus.limit(func, point, 'right')) / 2;
  } else {
    throw new Error('Approach not provided');
  }
};
<commit_msg>Don't quite use Number.MIN_VALUE<commit_after>var numbers = require('../numbers');
var calculus = exports;

/**
 * Calculate point differential for a specified function at a
 * specified point.  For functions of one variable.
 *
 * @param {Function} math function to be evaluated
 * @param {Number} point to be evaluated
 * @return {Number} result
 */
calculus.pointDiff = function (func, point) {
  var a = func(point - 1e-15);
  var b = func(point + 1e-15);

  return (b - a) / (2e-15);
};

/**
 * Calculate riemann sum for a specified, one variable, function
 * from a starting point, to a finishing point, with n divisions.
 *
 * @param {Function} math function to be evaluated
 * @param {Number} point to initiate evaluation
 * @param {Number} point to complete evaluation
 * @param {Number} quantity of divisions
 * @param {Function} (Optional) Function that returns which value
 * to sample on each interval; if none is provided, left endpoints
 * will be used.
 * @return {Number} result
 */
calculus.riemann = function (func, start, finish, n, sampler) {
  var inc = (finish - start) / n, totalHeight = 0, i;

  if (typeof sampler === 'function') {
    for (i = start; i < finish; i += inc) {
      totalHeight += func(sampler(i, i + inc));
    }
  } else {
    for (i = start; i < finish; i += inc) {
      totalHeight += func(i);
    }
  }

  return totalHeight * inc;
};

/**
 * Helper function in calculating integral of a function
 * from a to b using simpson quadrature.
 *
 * @param {Function} math function to be evaluated
 * @param {Number} point to initiate evaluation
 * @param {Number} point to complete evaluation
 * @return {Number} evaluation
 */
function simpsonDef (func, a, b) {
  var c = (a + b) / 2;
  var d = Math.abs(b - a) / 6;
  return d * (func(a) + 4 * func(c) + func(b));
}

/**
 * Helper function in calculating integral of a function
 * from a to b using simpson quadrature.  Manages recursive
 * investigation, handling evaluations within an error bound.
 *
 * @param {Function} math function to be evaluated
 * @param {Number} point to initiate evaluation
 * @param {Number} point to complete evaluation
 * @param {Number} total value
 * @param {Number} Error bound (epsilon)
 * @return {Number} recursive evaluation of left and right side
 */
function simpsonRecursive (func, a, b, whole, eps) {
  var c = a + b,
      left = simpsonDef(func, a, c),
      right = simpsonDef(func, c, b);

  if (Math.abs(left + right - whole) <= 15 * eps) {
    return left + right + (left + right - whole) / 15;
  } else {
    return simpsonRecursive(func, a, c, eps/2, left) + simpsonRecursive(func, c, b, eps / 2, right);
  }
}

/**
 * Evaluate area under a curve using adaptive simpson quadrature.
 *
 * @param {Function} math function to be evaluated
 * @param {Number} point to initiate evaluation
 * @param {Number} point to complete evaluation
 * @param {Number} Optional error bound (epsilon);
 * global error bound will be used as a fallback.
 * @return {Number} area underneath curve
 */
calculus.adaptiveSimpson = function (func, a, b, eps) {
  eps = (typeof eps === "undefined") ? numbers.EPSILON : eps;

  return simpsonRecursive(func, a, b, simpsonDef(func, a, b), eps);
};

/**
 * Calculate limit of a function at a given point.  Can approach from
 * left, middle, or right.
 *
 * @param {Function} math function to be evaluated
 * @param {Number} point to evaluate
 * @param {String} approach to limit
 * @return {Number} limit
 */
calculus.limit = function (func, point, approach) {
  if (approach === 'left') {
    return func(point - 1e-15);
  } else if (approach === 'right') {
    return func(point + 1e-15);
  } else if (approach === 'middle') {
    return (calculus.limit(func, point, 'left') + calculus.limit(func, point, 'right')) / 2;
  } else {
    throw new Error('Approach not provided');
  }
};
<|endoftext|>


<commit_before>/* G. Hemingway Copyright @2014
 * Context for the overall CAD assembly
 */
"use strict";

import Assembly from './assembly';
import Annotation          from './annotation';
import DataLoader from './data_loader';
import Shell from './shell';
import {makeGeometry, processKeyframe, processDelta} from './nc_delta';

/*************************************************************************/

export default class NC extends THREE.EventDispatcher {
    constructor(project, workingstep, timeIn, loader) {
        super();
        this.app = loader._app;
        this.project = project;
        this._workingstep = workingstep;
        this._timeIn = timeIn;
        this._loader = loader;
        this._objects = {};
        this.type = 'nc';
        this.raycaster = new THREE.Raycaster();
        this._object3D = new THREE.Object3D();
        this._overlay3D = new THREE.Object3D();
        this._annotation3D = new THREE.Object3D();
        this.state = {
            selected:       false,
            highlighted:    false,
            visible:        true,
            opacity:        1.0,
            explodeDistance: 0,
            collapsed:      false
        }
    }

    addModel(model, usage, type, id, transform, bbox) {
        // console.log('Add Model(' + usage + '): ' + id);
        // Setup 3D object holder
        let obj = {
            model: model,
            usage: usage,
            type: type,
            id: id,
            rendered: true,
            object3D: new THREE.Object3D(),
            transform: (new THREE.Matrix4()).copy(transform),
            bbox: bbox,
            getID: function() { return this.id; },
            getNamedParent: function() { return this },
            getBoundingBox: function() { return this },
            toggleHighlight: function() { },
            toggleVisibility: function() {this.object3D.visible = !this.object3D.visible; },
            setInvisible: function() {this.object3D.visible = false; },
            setVisible: function() {this.object3D.visible = true; },
            toggleOpacity: function() { },
            toggleSelection: function() { },
            toggleCollapsed: function() { },
            explode: function() { }
        };
        obj.object3D.applyMatrix(obj.transform);
        obj.object3D.updateMatrixWorld();
        obj.overlay3D = obj.object3D.clone();
        obj.annotation3D = obj.object3D.clone();
        // Save the object
        this._objects[id] = obj;
        this._object3D.add(obj.object3D);
        this._overlay3D.add(obj.overlay3D);
        this._annotation3D.add(obj.annotation3D);
        if (type === 'shell') {
            model.addEventListener('shellEndLoad', (event) => {
                //This is where the shell gets sent when its loaded so that the full mesh can be added to the 3D objects
                let material = new THREE.ShaderMaterial(new THREE.VelvetyShader());
                let mesh = new THREE.Mesh(event.shell.getGeometry(), material, false);

                if (obj.bbox.isEmpty()) {
                    obj.bbox = event.shell.getBoundingBox();
                }

                mesh.castShadow = true;
                mesh.receiveShadow = true;
                mesh.userData = obj;
                obj.object3D.add(mesh);
                obj.version = 0;
                if (usage === 'asis') {
                    // TODO: add selector for displaying asis geometry or not
                    obj.rendered = false;
                    obj.setInvisible();
                }
            });
        } else if (type === 'polyline') {
            model.addEventListener('annotationEndLoad', (event) => {
                let lineGeometries = event.annotation.getGeometry();
                let material = new THREE.LineBasicMaterial({
                    vertexColors: THREE.VertexColors,
                    //color: 0xffffff,
                    linewidth: 1
                });
                model._addedGeometry = [];
                for (let i = 0; i < lineGeometries.length; i++) {
                    let lines = new THREE.Line(lineGeometries[i], material);
                    lines.visible = true;
                    obj.annotation3D.add(lines);
                    model._addedGeometry.push(lines);
                }
            });
            model.addEventListener("annotationMakeVisible", (event)=>{
              _.each(model._addedGeometry, (line)=>{
                obj.annotation3D.add(line);
              });
            });

            let removeAnno = () => {
                model.removeEventListener('annotationEndLoad', removeAnno);
                _.each(model._addedGeometry, (line)=>{
                    obj.annotation3D.remove(line);
                });
            };

            model.addEventListener("annotationMakeNonVisible", (event)=>{
              if (!model._addedGeometry || model._addedGeometry.length === 0) {
                  model.addEventListener('annotationEndLoad', removeAnno);
              } else {
                  removeAnno();
              }
            });
        }
    }

    getObject3D() {
        return this._object3D;
    };

    getObjects() {
        return this._objects;
    };

    getOverlay3D() {
        return this._overlay3D;
    };

    getAnnotation3D() {
        return this._annotation3D;
    };

    getBoundingBox() {
        if (!this.boundingBox) {
            this.boundingBox = new THREE.Box3();
            let keys = _.keys(this._objects);
            _.each(keys, (key) => {
                let object = this._objects[key];
                if (object.type !== 'polyline') {
                    this.boundingBox.union(object.bbox);
                }
            });
        }
        return this.boundingBox.clone();
    }

    calcBoundingBox() {

        this._overlay3D.remove(this.bbox);
        this.boundingBox = new THREE.Box3();
        let keys = _.keys(this._objects);
        _.each(keys, (key) => {
            let object = this._objects[key];
            if (object.rendered !== false && object.type !== 'polyline') {
                let newBox = new THREE.Box3().setFromObject(object.object3D);
                if (!newBox.isEmpty()) {
                    object.bbox = newBox;
                }
                this.boundingBox.union(object.bbox);
            }
        });
        let bounds = this.boundingBox;

        this.bbox = Assembly.buildBoundingBox(bounds);
        if (this.bbox && this.state.selected) {
            this._overlay3D.add(this.bbox);
        }
    }

    clearHighlights() {
        this.dispatchEvent({ type: "_clearHighlights" });
    }

    hideAllBoundingBoxes() {
        this.dispatchEvent({ type: "_hideBounding" });
    }

    getNamedParent() {
        return this;
    }

    select(camera, mouseX, mouseY) {
        let mouse = new THREE.Vector2();
        mouse.x = (mouseX / window.innerWidth) * 2 - 1;
        mouse.y = -(mouseY / window.innerHeight) * 2 + 1;
        this.raycaster.setFromCamera(mouse, camera);

        let objs = _.map(_.values(this._objects), (obj) => obj.object3D);
        let intersections = this.raycaster.intersectObjects(objs, true);
        // Did we hit anything?
        let object = undefined;
        if (intersections.length > 0) {
            let hit = undefined;
            for (let i = 0; i < intersections.length; i++) {
                if (intersections[i].object.visible) {
                    if (!hit || intersections[i].distance < hit.distance) {
                        hit = intersections[i];
                    }
                }
            }
            if (hit) {
                object = hit.object.userData;
            }
        }
        return object;
    }
    handleInprocessGeom(geom){
        let parseDynamicUpdate = (geom,obj)=> {
            let geometry = makeGeometry(processDelta(geom, obj));
            // Remove all old geometry -- mesh's only
            obj.object3D.traverse(function (child) {
                if (child.type === "Mesh") {
                    obj.object3D.remove(child);
                }
            });
            // Create new modified geometry and add to obj
            let material = new THREE.ShaderMaterial(new THREE.VelvetyShader());
            let mesh = new THREE.Mesh(geometry, material);
            mesh.castShadow = true;
            mesh.receiveShadow = true;
            mesh.userData = obj;
            obj.object3D.add(mesh);
            // Make sure to update the model geometry
            obj.model.setGeometry(geometry);
        };
        let parseDynamicFull = (geom,obj)=>{
            let geometry = makeGeometry(processKeyframe(geom));
            // Remove all old geometry -- mesh's only
            obj.object3D.traverse(function(child) {
                if (child.type === "Mesh") {
                    obj.object3D.remove(child);
                }
            });
            // Add in new geometry
            let material = new THREE.ShaderMaterial(new THREE.VelvetyShader());
            let mesh = new THREE.Mesh(geometry, material);
            mesh.castShadow = true;
            mesh.receiveShadow = true;
            mesh.userData = obj;
            obj.object3D.add(mesh);
            // Make sure to update the model geometry
            obj.model.setGeometry(geometry);
            obj.version = geom.version;
            obj.precision = geom.precision;
            return true;
        };
        let existingobj = this._objects[geom.id];
        if(existingobj === undefined) { //Need a full dynamic shell.
            //Setup the memory
            let color = DataLoader.parseColor("BE17FF");
            let boundingBox = DataLoader.parseBoundingBox(geom.bbox);
            let transform =DataLoader.parseXform(geom.xform,true);
            let shell = new Shell(geom.id,this,this,geom.size,color,boundingBox);
            this.addModel(shell,geom.usage,'shell',geom.id,transform,boundingBox);
            existingobj = this._objects[geom.id];

            request.get('/v3/nc/geometry/delta/-1')
                .end((err,res)=>{
                    let fulldynamic = JSON.parse(res.text);
                    parseDynamicFull(fulldynamic,existingobj);
                });
        }
        else{ //Need an updated dynamic shell.
            request.get('/v3/nc/geometry/delta/'+existingobj.version)
                .end((err,res)=> {
                    let updateddynamic = JSON.parse(res.text);
                    parseDynamicUpdate(updateddynamic,existingobj);
                });
        }
        return true;
        // Don't know what kind of update this is
    }

    applyDelta(delta) {
        let alter = false;
        //There are two types of 'State' that we get- KeyState or DeltaState.

        //If we get a KeyState, we need to re-render the scene.
        //If we get a DeltaState, we need to update the scene.
        //First we handle KeyState.
        if (!delta.hasOwnProperty('prev')){
            //For keyframes, we need to hide the currently drawn but unused geometry,
            //Unhide anything we have that is needed but hidden,
            //And load and display any new things we don't have.
            // Hide existing Stuff. Keep it around in case we need to use it later.
            var oldgeom = _.filter(_.values(this._objects), ['type','shell']);
            _.each(oldgeom,(geom)=> {
                //this._object3D.remove(geom.object3D);
                //this._overlay3D.remove(geom.object3D);
                geom.rendered = false;
                geom.object3D.visible = false;
            });

            var oldannotations =_.values(this._loader._annotations);
            _.each(oldannotations, (oldannotation) => {
                oldannotation.removeFromScene();
            });

            //Load new Stuff.
            var toolpaths = _.filter(delta.geom, (geom) => (geom.usage == 'toolpath' || (_.has(geom, 'polyline') && geom.usage =="tobe")));
            var geoms = _.filter(delta.geom, (geom) => (
                geom.usage =='cutter' || (geom.usage =='tobe' && _.has(geom, 'shell')) ||
                geom.usage =="asis"||geom.usage=='machine' || geom.usage=="fixture")
            );
            let inproc = _.filter(delta.geom, ['usage','inprocess']);
            _.each(inproc, (ip)=>{this.handleInprocessGeom(ip);});
            _.each(toolpaths, (geomData) => {
                let name = geomData.polyline.split('.')[0];
                if (!this._loader._annotations[name]){
                    let annotation = new Annotation(geomData.id, this, this);
                    let transform = DataLoader.parseXform(geomData.xform, true);
                    this.addModel(annotation, geomData.usage, 'polyline', geomData.id, transform, undefined);
                    // Push the annotation for later completion
                    this._loader._annotations[name] = annotation;
                    var url = '/v3/nc/';
                    this._loader.addRequest({
                        path: name,
                        baseURL: url,
                        type: 'annotation'
                    });
                } else {
                    this._loader._annotations[name].addToScene();
                }
            });

            _.each(geoms, (geomData)=>{
                let name = geomData.id;
                //Don't show as-is geom of fixture
                if(geomData.usage =='asis' || (this.app.services.machine === null && geomData.usage == 'fixture')) return;

                if(this._objects[name]) {
                    let obj = this._objects[name];
                    if (!obj.rendered) {
                        //this._overlay3D.add(obj.object3D);
                        obj.rendered = true;
                        obj.visible = true;
                        obj.setVisible();
                        this._objects[name] = obj;
                    }
                }
                else {
                    let color = DataLoader.parseColor("7d7d7d");
                    if(geomData.usage =="cutter"){
                        color = DataLoader.parseColor("FF530D");
                    }
                    let transform = DataLoader.parseXform(geomData.xform,true);
                    let boundingBox = DataLoader.parseBoundingBox(geomData.bbox);
                    let shell = new Shell(geomData.id,this,this,geomData.size,color,boundingBox);
                    this.addModel(shell,geomData.usage,'shell',geomData.id,transform,boundingBox);
                    this._loader._shells[geomData.shell]=shell;
                    var url = "/v3/nc/";
                    this._loader.addRequest({
                        path: name,
                        baseURL: url,
                        type: "shell"
                    })
                }
            });

            this._loader.runLoadQueue();
            alter = true;
            this.app.actionManager.emit('change-workingstep', delta.workingstep);
            //  let lineGeometries = event.annotation.getGeometry();
        }
        else {
            // Handle each geom update in the delta
            // This is usually just a tool movement (and volume removal update).
            _.each(delta.geom, (geom) => {
		    if(geom.usage ==='inprocess') return this.handleInprocessGeom(geom);
                if (!window.geom || window.geom.length < 100){
                    window.geom = window.geom || [];
                    window.geom.push(geom);
                }
                let obj = this._objects[geom.id];
                if(obj !== undefined) {
                    if (obj.rendered !== false) {
                        let transform = new THREE.Matrix4();
                        if (!geom.xform) return;
                        transform.fromArray(geom.xform);
                        let position = new THREE.Vector3();
                        let quaternion = new THREE.Quaternion();
                        let scale = new THREE.Vector3();
                        transform.decompose(position, quaternion, scale);
                        // we need to update all 3D properties so that
                        // annotations, overlays and objects are all updated
                        obj.object3D.position.copy(position);
                        obj.object3D.quaternion.copy(quaternion);
                        obj.annotation3D.position.copy(position);
                        obj.annotation3D.quaternion.copy(quaternion);
                        obj.overlay3D.position.copy(position);
                        obj.overlay3D.quaternion.copy(quaternion);
                        alter = true;
                    }
                }
            });
        }
        return alter;
    }

    getSelected() {
       if(this.state.selected)
        return [this];
        else
            return [];
    }
    getID() { return this.id; }
    toggleHighlight() { }
    toggleVisibility() { }
    toggleOpacity() { }

    toggleSelection() {
        // On deselection
        if(this.state.selected) {
            // Hide the bounding box
            this._overlay3D.remove(this.bbox);
            // On selection
        } else {
            let bounds = this.getBoundingBox(false);
            if (!this.bbox && !bounds.isEmpty()) {
                this.bbox = Assembly.buildBoundingBox(bounds);
            }
            if (this.bbox) {
                // Add the BBox to our overlay object
                this._overlay3D.add(this.bbox);
            }
        }
        this.state.selected = !this.state.selected;
    }

    toggleCollapsed() { }
    explode() { }
}
<commit_msg>Don't want regular geom handler getting the inprocess geometry.<commit_after>/* G. Hemingway Copyright @2014
 * Context for the overall CAD assembly
 */
"use strict";

import Assembly from './assembly';
import Annotation          from './annotation';
import DataLoader from './data_loader';
import Shell from './shell';
import {makeGeometry, processKeyframe, processDelta} from './nc_delta';

/*************************************************************************/

export default class NC extends THREE.EventDispatcher {
    constructor(project, workingstep, timeIn, loader) {
        super();
        this.app = loader._app;
        this.project = project;
        this._workingstep = workingstep;
        this._timeIn = timeIn;
        this._loader = loader;
        this._objects = {};
        this.type = 'nc';
        this.raycaster = new THREE.Raycaster();
        this._object3D = new THREE.Object3D();
        this._overlay3D = new THREE.Object3D();
        this._annotation3D = new THREE.Object3D();
        this.state = {
            selected:       false,
            highlighted:    false,
            visible:        true,
            opacity:        1.0,
            explodeDistance: 0,
            collapsed:      false
        }
    }

    addModel(model, usage, type, id, transform, bbox) {
        // console.log('Add Model(' + usage + '): ' + id);
        // Setup 3D object holder
        let obj = {
            model: model,
            usage: usage,
            type: type,
            id: id,
            rendered: true,
            object3D: new THREE.Object3D(),
            transform: (new THREE.Matrix4()).copy(transform),
            bbox: bbox,
            getID: function() { return this.id; },
            getNamedParent: function() { return this },
            getBoundingBox: function() { return this },
            toggleHighlight: function() { },
            toggleVisibility: function() {this.object3D.visible = !this.object3D.visible; },
            setInvisible: function() {this.object3D.visible = false; },
            setVisible: function() {this.object3D.visible = true; },
            toggleOpacity: function() { },
            toggleSelection: function() { },
            toggleCollapsed: function() { },
            explode: function() { }
        };
        obj.object3D.applyMatrix(obj.transform);
        obj.object3D.updateMatrixWorld();
        obj.overlay3D = obj.object3D.clone();
        obj.annotation3D = obj.object3D.clone();
        // Save the object
        this._objects[id] = obj;
        this._object3D.add(obj.object3D);
        this._overlay3D.add(obj.overlay3D);
        this._annotation3D.add(obj.annotation3D);
        if (type === 'shell') {
            model.addEventListener('shellEndLoad', (event) => {
                //This is where the shell gets sent when its loaded so that the full mesh can be added to the 3D objects
                let material = new THREE.ShaderMaterial(new THREE.VelvetyShader());
                let mesh = new THREE.Mesh(event.shell.getGeometry(), material, false);

                if (obj.bbox.isEmpty()) {
                    obj.bbox = event.shell.getBoundingBox();
                }

                mesh.castShadow = true;
                mesh.receiveShadow = true;
                mesh.userData = obj;
                obj.object3D.add(mesh);
                obj.version = 0;
                if (usage === 'asis') {
                    // TODO: add selector for displaying asis geometry or not
                    obj.rendered = false;
                    obj.setInvisible();
                }
            });
        } else if (type === 'polyline') {
            model.addEventListener('annotationEndLoad', (event) => {
                let lineGeometries = event.annotation.getGeometry();
                let material = new THREE.LineBasicMaterial({
                    vertexColors: THREE.VertexColors,
                    //color: 0xffffff,
                    linewidth: 1
                });
                model._addedGeometry = [];
                for (let i = 0; i < lineGeometries.length; i++) {
                    let lines = new THREE.Line(lineGeometries[i], material);
                    lines.visible = true;
                    obj.annotation3D.add(lines);
                    model._addedGeometry.push(lines);
                }
            });
            model.addEventListener("annotationMakeVisible", (event)=>{
              _.each(model._addedGeometry, (line)=>{
                obj.annotation3D.add(line);
              });
            });

            let removeAnno = () => {
                model.removeEventListener('annotationEndLoad', removeAnno);
                _.each(model._addedGeometry, (line)=>{
                    obj.annotation3D.remove(line);
                });
            };

            model.addEventListener("annotationMakeNonVisible", (event)=>{
              if (!model._addedGeometry || model._addedGeometry.length === 0) {
                  model.addEventListener('annotationEndLoad', removeAnno);
              } else {
                  removeAnno();
              }
            });
        }
    }

    getObject3D() {
        return this._object3D;
    };

    getObjects() {
        return this._objects;
    };

    getOverlay3D() {
        return this._overlay3D;
    };

    getAnnotation3D() {
        return this._annotation3D;
    };

    getBoundingBox() {
        if (!this.boundingBox) {
            this.boundingBox = new THREE.Box3();
            let keys = _.keys(this._objects);
            _.each(keys, (key) => {
                let object = this._objects[key];
                if (object.type !== 'polyline') {
                    this.boundingBox.union(object.bbox);
                }
            });
        }
        return this.boundingBox.clone();
    }

    calcBoundingBox() {

        this._overlay3D.remove(this.bbox);
        this.boundingBox = new THREE.Box3();
        let keys = _.keys(this._objects);
        _.each(keys, (key) => {
            let object = this._objects[key];
            if (object.rendered !== false && object.type !== 'polyline') {
                let newBox = new THREE.Box3().setFromObject(object.object3D);
                if (!newBox.isEmpty()) {
                    object.bbox = newBox;
                }
                this.boundingBox.union(object.bbox);
            }
        });
        let bounds = this.boundingBox;

        this.bbox = Assembly.buildBoundingBox(bounds);
        if (this.bbox && this.state.selected) {
            this._overlay3D.add(this.bbox);
        }
    }

    clearHighlights() {
        this.dispatchEvent({ type: "_clearHighlights" });
    }

    hideAllBoundingBoxes() {
        this.dispatchEvent({ type: "_hideBounding" });
    }

    getNamedParent() {
        return this;
    }

    select(camera, mouseX, mouseY) {
        let mouse = new THREE.Vector2();
        mouse.x = (mouseX / window.innerWidth) * 2 - 1;
        mouse.y = -(mouseY / window.innerHeight) * 2 + 1;
        this.raycaster.setFromCamera(mouse, camera);

        let objs = _.map(_.values(this._objects), (obj) => obj.object3D);
        let intersections = this.raycaster.intersectObjects(objs, true);
        // Did we hit anything?
        let object = undefined;
        if (intersections.length > 0) {
            let hit = undefined;
            for (let i = 0; i < intersections.length; i++) {
                if (intersections[i].object.visible) {
                    if (!hit || intersections[i].distance < hit.distance) {
                        hit = intersections[i];
                    }
                }
            }
            if (hit) {
                object = hit.object.userData;
            }
        }
        return object;
    }
    handleInprocessGeom(geom){
        let parseDynamicUpdate = (geom,obj)=> {
            let geometry = makeGeometry(processDelta(geom, obj));
            // Remove all old geometry -- mesh's only
            obj.object3D.traverse(function (child) {
                if (child.type === "Mesh") {
                    obj.object3D.remove(child);
                }
            });
            // Create new modified geometry and add to obj
            let material = new THREE.ShaderMaterial(new THREE.VelvetyShader());
            let mesh = new THREE.Mesh(geometry, material);
            mesh.castShadow = true;
            mesh.receiveShadow = true;
            mesh.userData = obj;
            obj.object3D.add(mesh);
            // Make sure to update the model geometry
            obj.model.setGeometry(geometry);
        };
        let parseDynamicFull = (geom,obj)=>{
            let geometry = makeGeometry(processKeyframe(geom));
            // Remove all old geometry -- mesh's only
            obj.object3D.traverse(function(child) {
                if (child.type === "Mesh") {
                    obj.object3D.remove(child);
                }
            });
            // Add in new geometry
            let material = new THREE.ShaderMaterial(new THREE.VelvetyShader());
            let mesh = new THREE.Mesh(geometry, material);
            mesh.castShadow = true;
            mesh.receiveShadow = true;
            mesh.userData = obj;
            obj.object3D.add(mesh);
            // Make sure to update the model geometry
            obj.model.setGeometry(geometry);
            obj.version = geom.version;
            obj.precision = geom.precision;
            return true;
        };
        let existingobj = this._objects[geom.id];
        if(existingobj === undefined) { //Need a full dynamic shell.
            //Setup the memory
            let color = DataLoader.parseColor("BE17FF");
            let boundingBox = DataLoader.parseBoundingBox(geom.bbox);
            let transform =DataLoader.parseXform(geom.xform,true);
            let shell = new Shell(geom.id,this,this,geom.size,color,boundingBox);
            this.addModel(shell,geom.usage,'shell',geom.id,transform,boundingBox);
            existingobj = this._objects[geom.id];

            request.get('/v3/nc/geometry/delta/-1')
                .end((err,res)=>{
                    let fulldynamic = JSON.parse(res.text);
                    parseDynamicFull(fulldynamic,existingobj);
                });
        }
        else{ //Need an updated dynamic shell.
            request.get('/v3/nc/geometry/delta/'+existingobj.version)
                .end((err,res)=> {
                    let updateddynamic = JSON.parse(res.text);
                    parseDynamicUpdate(updateddynamic,existingobj);
                });
        }
        return true;
        // Don't know what kind of update this is
    }

    applyDelta(delta) {
        let alter = false;
        //There are two types of 'State' that we get- KeyState or DeltaState.

        //If we get a KeyState, we need to re-render the scene.
        //If we get a DeltaState, we need to update the scene.
        //First we handle KeyState.
        if (!delta.hasOwnProperty('prev')){
            //For keyframes, we need to hide the currently drawn but unused geometry,
            //Unhide anything we have that is needed but hidden,
            //And load and display any new things we don't have.
            // Hide existing Stuff. Keep it around in case we need to use it later.
            var oldgeom = _.filter(_.values(this._objects), (p)=>{
                return(p.type ==='shell'&& p.usage!=='inprocess');
            });
            _.each(oldgeom,(geom)=> {
                //this._object3D.remove(geom.object3D);
                //this._overlay3D.remove(geom.object3D);
                geom.rendered = false;
                geom.object3D.visible = false;
            });

            var oldannotations =_.values(this._loader._annotations);
            _.each(oldannotations, (oldannotation) => {
                oldannotation.removeFromScene();
            });

            //Load new Stuff.
            var toolpaths = _.filter(delta.geom, (geom) => (geom.usage == 'toolpath' || (_.has(geom, 'polyline') && geom.usage =="tobe")));
            var geoms = _.filter(delta.geom, (geom) => (
                geom.usage =='cutter' || (geom.usage =='tobe' && _.has(geom, 'shell')) ||
                geom.usage =="asis"||geom.usage=='machine' || geom.usage=="fixture")
            );
            let inproc = _.filter(delta.geom, ['usage','inprocess']);
            _.each(inproc, (ip)=>{this.handleInprocessGeom(ip);});
            _.each(toolpaths, (geomData) => {
                let name = geomData.polyline.split('.')[0];
                if (!this._loader._annotations[name]){
                    let annotation = new Annotation(geomData.id, this, this);
                    let transform = DataLoader.parseXform(geomData.xform, true);
                    this.addModel(annotation, geomData.usage, 'polyline', geomData.id, transform, undefined);
                    // Push the annotation for later completion
                    this._loader._annotations[name] = annotation;
                    var url = '/v3/nc/';
                    this._loader.addRequest({
                        path: name,
                        baseURL: url,
                        type: 'annotation'
                    });
                } else {
                    this._loader._annotations[name].addToScene();
                }
            });

            _.each(geoms, (geomData)=>{
                let name = geomData.id;
                //Don't show as-is geom of fixture
                if(geomData.usage =='asis' || (this.app.services.machine === null && geomData.usage == 'fixture')) return;

                if(this._objects[name]) {
                    let obj = this._objects[name];
                    if (!obj.rendered) {
                        //this._overlay3D.add(obj.object3D);
                        obj.rendered = true;
                        obj.visible = true;
                        obj.setVisible();
                        this._objects[name] = obj;
                    }
                }
                else {
                    let color = DataLoader.parseColor("7d7d7d");
                    if(geomData.usage =="cutter"){
                        color = DataLoader.parseColor("FF530D");
                    }
                    let transform = DataLoader.parseXform(geomData.xform,true);
                    let boundingBox = DataLoader.parseBoundingBox(geomData.bbox);
                    let shell = new Shell(geomData.id,this,this,geomData.size,color,boundingBox);
                    this.addModel(shell,geomData.usage,'shell',geomData.id,transform,boundingBox);
                    this._loader._shells[geomData.shell]=shell;
                    var url = "/v3/nc/";
                    this._loader.addRequest({
                        path: name,
                        baseURL: url,
                        type: "shell"
                    })
                }
            });

            this._loader.runLoadQueue();
            alter = true;
            this.app.actionManager.emit('change-workingstep', delta.workingstep);
            //  let lineGeometries = event.annotation.getGeometry();
        }
        else {
            // Handle each geom update in the delta
            // This is usually just a tool movement (and volume removal update).
            _.each(delta.geom, (geom) => {
		    if(geom.usage ==='inprocess') return this.handleInprocessGeom(geom);
                if (!window.geom || window.geom.length < 100){
                    window.geom = window.geom || [];
                    window.geom.push(geom);
                }
                let obj = this._objects[geom.id];
                if(obj !== undefined) {
                    if (obj.rendered !== false) {
                        let transform = new THREE.Matrix4();
                        if (!geom.xform) return;
                        transform.fromArray(geom.xform);
                        let position = new THREE.Vector3();
                        let quaternion = new THREE.Quaternion();
                        let scale = new THREE.Vector3();
                        transform.decompose(position, quaternion, scale);
                        // we need to update all 3D properties so that
                        // annotations, overlays and objects are all updated
                        obj.object3D.position.copy(position);
                        obj.object3D.quaternion.copy(quaternion);
                        obj.annotation3D.position.copy(position);
                        obj.annotation3D.quaternion.copy(quaternion);
                        obj.overlay3D.position.copy(position);
                        obj.overlay3D.quaternion.copy(quaternion);
                        alter = true;
                    }
                }
            });
        }
        return alter;
    }

    getSelected() {
       if(this.state.selected)
        return [this];
        else
            return [];
    }
    getID() { return this.id; }
    toggleHighlight() { }
    toggleVisibility() { }
    toggleOpacity() { }

    toggleSelection() {
        // On deselection
        if(this.state.selected) {
            // Hide the bounding box
            this._overlay3D.remove(this.bbox);
            // On selection
        } else {
            let bounds = this.getBoundingBox(false);
            if (!this.bbox && !bounds.isEmpty()) {
                this.bbox = Assembly.buildBoundingBox(bounds);
            }
            if (this.bbox) {
                // Add the BBox to our overlay object
                this._overlay3D.add(this.bbox);
            }
        }
        this.state.selected = !this.state.selected;
    }

    toggleCollapsed() { }
    explode() { }
}
<|endoftext|>


<commit_before>var _ = require('underscore')._;

var commands = function(dbot){
    var commands = {

        "~getprop": function(event){
            if(event.params[1]){
                var primary = dbot.api.users.resolveUser(event.server, event.user);
                var res = dbot.db.profiles[event.server][primary.toLowerCase()].profile[event.params[1]];
                if(res){
                    event.reply(res);
                }
                else{
                    event.reply("Nope.");
                }
            }
        },

        "~setprop": function(event){
            if(event.input[1] && event.input[2]){
                if(_.has(this.config.schema.profile, event.input[1])){
                    var primary = dbot.api.users.resolveUser(event.server, event.user);
                    dbot.db.profiles[event.server][primary.toLowerCase()].profile[event.input[1]] = event.input[2];
                    event.reply("Property set, maybe?");
                }
                else{
                    event.reply("Invalid property. Go home.");
                }
            }
        },

        "~profile": function(event){
            if(event.params[1]){
                var primary = dbot.api.users.resolveUser(event.server, event.params[1]);
                if(_.has(dbot.db.profiles[event.server], primary.toLowerCase())){
                    event.reply(dbot.api.web.getUrl("/profile/"+event.server+"/"+primary.toLowerCase());
                }
                else{
                    event.reply("No profile found for "+event.params[1]);
                }
            }
            else{
                event.message = '~profile ' + event.user;
                event.action = 'PRIVMSG';
                event.params = event.message.split(' ');
                dbot.instance.emit(event);
            }
        }
    };
    commands['~setprop'].regex = [/~setprop ([^ ]+) (.+)/, 3];

    return commands;
};

exports.fetch = function(dbot){
    return commands(dbot);
};
<commit_msg>missing close brakcet in profiles<commit_after>var _ = require('underscore')._;

var commands = function(dbot){
    var commands = {

        "~getprop": function(event){
            if(event.params[1]){
                var primary = dbot.api.users.resolveUser(event.server, event.user);
                var res = dbot.db.profiles[event.server][primary.toLowerCase()].profile[event.params[1]];
                if(res){
                    event.reply(res);
                }
                else{
                    event.reply("Nope.");
                }
            }
        },

        "~setprop": function(event){
            if(event.input[1] && event.input[2]){
                if(_.has(this.config.schema.profile, event.input[1])){
                    var primary = dbot.api.users.resolveUser(event.server, event.user);
                    dbot.db.profiles[event.server][primary.toLowerCase()].profile[event.input[1]] = event.input[2];
                    event.reply("Property set, maybe?");
                }
                else{
                    event.reply("Invalid property. Go home.");
                }
            }
        },

        "~profile": function(event){
            if(event.params[1]){
                var primary = dbot.api.users.resolveUser(event.server, event.params[1]);
                if(_.has(dbot.db.profiles[event.server], primary.toLowerCase())){
                    event.reply(dbot.api.web.getUrl("/profile/"+event.server+"/"+primary.toLowerCase()));
                }
                else{
                    event.reply("No profile found for "+event.params[1]);
                }
            }
            else{
                event.message = '~profile ' + event.user;
                event.action = 'PRIVMSG';
                event.params = event.message.split(' ');
                dbot.instance.emit(event);
            }
        }
    };
    commands['~setprop'].regex = [/~setprop ([^ ]+) (.+)/, 3];

    return commands;
};

exports.fetch = function(dbot){
    return commands(dbot);
};
<|endoftext|>


<commit_before>angular.module('truncate', [])
    .filter('characters', function () {
        return function (input, chars, breakOnWord) {
            if (isNaN(chars)) return input;
            if (chars <= 0) return '';
            if (input && input.length >= chars) {
                input = input.substring(0, chars);

                if (!breakOnWord) {
                    var lastspace = input.lastIndexOf(' ');
                    //get last space
                    if (lastspace !== -1) {
                        input = input.substr(0, lastspace);
                    }
                }else{
                    while(input.charAt(input.length-1) == ' '){
                        input = input.substr(0, input.length -1);
                    }
                }
                return input + '...';
            }
            return input;
        };
    })
    .filter('words', function () {
        return function (input, words) {
            if (isNaN(words)) return input;
            if (words <= 0) return '';
            if (input) {
                var inputWords = input.split(/\s+/);
                if (inputWords.length > words) {
                    input = inputWords.slice(0, words).join(' ') + '...';
                }
            }
            return input;
        };
    });
<commit_msg>Use the "ELLIPSIS"-Character instead of dots<commit_after>angular.module('truncate', [])
    .filter('characters', function () {
        return function (input, chars, breakOnWord) {
            if (isNaN(chars)) return input;
            if (chars <= 0) return '';
            if (input && input.length >= chars) {
                input = input.substring(0, chars);

                if (!breakOnWord) {
                    var lastspace = input.lastIndexOf(' ');
                    //get last space
                    if (lastspace !== -1) {
                        input = input.substr(0, lastspace);
                    }
                }else{
                    while(input.charAt(input.length-1) == ' '){
                        input = input.substr(0, input.length -1);
                    }
                }
                return input + '…';
            }
            return input;
        };
    })
    .filter('words', function () {
        return function (input, words) {
            if (isNaN(words)) return input;
            if (words <= 0) return '';
            if (input) {
                var inputWords = input.split(/\s+/);
                if (inputWords.length > words) {
                    input = inputWords.slice(0, words).join(' ') + '…';
                }
            }
            return input;
        };
    });
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2019 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.dao',
  name: 'CSVSink',
  extends: 'foam.dao.AbstractSink',
  implements: [ 'foam.core.Serializable' ],

  documentation: 'Sink runs the csv outputter, and contains the resulting string in this.csv',

  properties: [
    {
      class: 'String',
      name: 'csv',
      view: 'foam.u2.tag.TextArea'
    },
    {
      class: 'Class',
      name: 'of',
      visibility: 'HIDDEN'
    },
    {
      class: 'StringArray',
      name: 'props',
      visibility: 'HIDDEN'
    },
    {
      name: 'outputter',
      class: 'FObjectProperty',
      of: 'foam.lib.csv.CSVOutputter',
      transient: true,
      factory: function() {
        return this.CSVOutputter.create({
          of: this.of,
          props: this.props
        });
      },
      javaFactory: `
        return new foam.lib.csv.CSVOutputter.Builder(getX()).setOf(getOf()).setProps(getProps()).build();
      `
    }
  ],

  methods: [
    {
      name: 'put',
      args: [
        { type: 'FObject', name: 'obj' }
      ],
      code: function(obj) {
        this.outputter.outputFObject(obj);
      },
      javaCode: `
        getOutputter().outputFObject(obj);
      `
    },

    {
      name: 'eof',
      code: function() {
        this.csv = this.outputter.toString();
      },
      javaCode: `
        setCsv(getOutputter().toString());
      `
    },

    {
      name: 'reset',
      code: function() {
        this.outputter.flush();
        this.csv = '';
      },
      javaCode: `
        getOutputter().flush();
        setCsv("");
      `
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'PropertyCSVRefinement',

  documentation: `Refinement on Properties to handle toCSV() and toCSVLabel().`,

  refines: 'foam.core.Property',

  properties: [
    {
      name: 'toCSV',
      class: 'Function',
      value: function(obj, outputter, prop) {
        outputter.outputValue(obj ? obj[prop.name] : null);
      }
    },
    {
      name: 'toCSVLabel',
      class: 'Function',
      value: function(outputter, prop) {
        outputter.outputValue(prop.name);
      }
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'FObjectPropertyCSVRefinement',

  documentation: `Refinement on FObjects to override toCSV() and toCSVLabel().
  Purpose is to output a dot annotated format, to handle the nested properties on the FObject.`,

  refines: 'foam.core.FObjectProperty',

  properties: [
    {
      name: 'toCSV',
      class: 'Function',
      value: function(x, obj, outputter, prop) {
        if ( ! prop.of ) {
          outputter.outputValue(obj ? obj[prop.name] : null);
          return;
        }
        prop.of.getAxiomsByClass(foam.core.Property)
          .forEach((axiom) => {
            axiom.toCSV(x, obj ? obj[prop.name] : null, outputter, axiom);
          });
      }
    },
    {
      name: 'toCSVLabel',
      class: 'Function',
      value: function(outputter, prop) {
        if ( ! prop.of ) {
          outputter.outputValue(prop.name);
          return;
        }
        // mini decorator
        var prefixedOutputter = {
          output: function(value) {
            outputter.outputValue(prop.name + '.' + value);
          }
        };
        prop.of.getAxiomsByClass(foam.core.Property)
          .forEach((axiom) => {
            axiom.toCSVLabel(prefixedOutputter, axiom);
          });
      }
    }
  ]
});
<commit_msg>explicit class call in CSVSink<commit_after>/**
 * @license
 * Copyright 2019 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.dao',
  name: 'CSVSink',
  extends: 'foam.dao.AbstractSink',
  implements: [ 'foam.core.Serializable' ],

  documentation: 'Sink runs the csv outputter, and contains the resulting string in this.csv',

  properties: [
    {
      class: 'String',
      name: 'csv',
      view: 'foam.u2.tag.TextArea'
    },
    {
      class: 'Class',
      name: 'of',
      visibility: 'HIDDEN'
    },
    {
      class: 'StringArray',
      name: 'props',
      visibility: 'HIDDEN'
    },
    {
      name: 'outputter',
      class: 'FObjectProperty',
      of: 'foam.lib.csv.CSVOutputter',
      transient: true,
      factory: function() {
        return foam.lib.csv.CSVOutputter.create({
          of: this.of,
          props: this.props
        });
      },
      javaFactory: `
        return new foam.lib.csv.CSVOutputter.Builder(getX()).setOf(getOf()).setProps(getProps()).build();
      `
    }
  ],

  methods: [
    {
      name: 'put',
      args: [
        { type: 'FObject', name: 'obj' }
      ],
      code: function(obj) {
        this.outputter.outputFObject(obj);
      },
      javaCode: `
        getOutputter().outputFObject(obj);
      `
    },

    {
      name: 'eof',
      code: function() {
        this.csv = this.outputter.toString();
      },
      javaCode: `
        setCsv(getOutputter().toString());
      `
    },

    {
      name: 'reset',
      code: function() {
        this.outputter.flush();
        this.csv = '';
      },
      javaCode: `
        getOutputter().flush();
        setCsv("");
      `
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'PropertyCSVRefinement',

  documentation: `Refinement on Properties to handle toCSV() and toCSVLabel().`,

  refines: 'foam.core.Property',

  properties: [
    {
      name: 'toCSV',
      class: 'Function',
      value: function(obj, outputter, prop) {
        outputter.outputValue(obj ? obj[prop.name] : null);
      }
    },
    {
      name: 'toCSVLabel',
      class: 'Function',
      value: function(outputter, prop) {
        outputter.outputValue(prop.name);
      }
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'FObjectPropertyCSVRefinement',

  documentation: `Refinement on FObjects to override toCSV() and toCSVLabel().
  Purpose is to output a dot annotated format, to handle the nested properties on the FObject.`,

  refines: 'foam.core.FObjectProperty',

  properties: [
    {
      name: 'toCSV',
      class: 'Function',
      value: function(x, obj, outputter, prop) {
        if ( ! prop.of ) {
          outputter.outputValue(obj ? obj[prop.name] : null);
          return;
        }
        prop.of.getAxiomsByClass(foam.core.Property)
          .forEach((axiom) => {
            axiom.toCSV(x, obj ? obj[prop.name] : null, outputter, axiom);
          });
      }
    },
    {
      name: 'toCSVLabel',
      class: 'Function',
      value: function(outputter, prop) {
        if ( ! prop.of ) {
          outputter.outputValue(prop.name);
          return;
        }
        // mini decorator
        var prefixedOutputter = {
          output: function(value) {
            outputter.outputValue(prop.name + '.' + value);
          }
        };
        prop.of.getAxiomsByClass(foam.core.Property)
          .forEach((axiom) => {
            axiom.toCSVLabel(prefixedOutputter, axiom);
          });
      }
    }
  ]
});
<|endoftext|>


<commit_before>(function() {
  var Account, Attributes, Calendar, Contact, Delta, Draft, Event, File, Folder, Label, ManagementAccount, ManagementModelCollection, Message, NylasConnection, Promise, RestfulModel, RestfulModelCollection, RestfulModelInstance, Tag, Thread, _, clone, logOnError, request;

  _ = require('underscore');

  clone = require('clone');

  request = require('request');

  Promise = require('bluebird');

  RestfulModel = require('./models/restful-model');

  RestfulModelCollection = require('./models/restful-model-collection');

  RestfulModelInstance = require('./models/restful-model-instance');

  Account = require('./models/account');

  ManagementAccount = require('./models/management-account');

  ManagementModelCollection = require('./models/management-model-collection');

  Thread = require('./models/thread');

  Contact = require('./models/contact');

  Message = require('./models/message');

  Draft = require('./models/draft');

  File = require('./models/file');

  Calendar = require('./models/calendar');

  Event = require('./models/event');

  Tag = require('./models/tag');

  Delta = require('./models/delta');

  Label = require('./models/folder').Label;

  Folder = require('./models/folder').Folder;

  Attributes = require('./models/attributes');

  module.exports = NylasConnection = (function() {
    function NylasConnection(accessToken) {
      this.accessToken = accessToken;
      this.threads = new RestfulModelCollection(Thread, this);
      this.contacts = new RestfulModelCollection(Contact, this);
      this.messages = new RestfulModelCollection(Message, this);
      this.drafts = new RestfulModelCollection(Draft, this);
      this.files = new RestfulModelCollection(File, this);
      this.calendars = new RestfulModelCollection(Calendar, this);
      this.events = new RestfulModelCollection(Event, this);
      this.tags = new RestfulModelCollection(Tag, this);
      this.deltas = new Delta(this);
      this.labels = new RestfulModelCollection(Label, this);
      this.folders = new RestfulModelCollection(Folder, this);
      this.account = new RestfulModelInstance(Account, this);
    }

    NylasConnection.prototype.requestOptions = function(options) {
      var Nylas, user;
      if (options == null) {
        options = {};
      }
      options = clone(options);
      Nylas = require('./nylas');
      if (options.method == null) {
        options.method = 'GET';
      }
      if (options.path) {
        if (options.url == null) {
          options.url = "" + Nylas.apiServer + options.path;
        }
      }
      if (!options.formData) {
        if (options.body == null) {
          options.body = {};
        }
      }
      if (options.json == null) {
        options.json = true;
      }
      if (options.downloadRequest == null) {
        options.downloadRequest = false;
      }
      user = options.path.substr(0, 3) === '/a/' ? Nylas.appSecret : this.accessToken;
      if (user) {
        options.auth = {
          'user': user,
          'pass': '',
          'sendImmediately': true
        };
      }
      return options;
    };

    NylasConnection.prototype.request = function(options) {
      if (options == null) {
        options = {};
      }
      options = this.requestOptions(options);
      return new Promise(function(resolve, reject) {
        return request(options, function(error, response, body) {
          var e;
          try {
            if (_.isString(body)) {
              body = JSON.parse(body);
            }
          } catch (_error) {
            e = _error;
            if (!error) {
              error = e;
            }
          }
          if (error || response.statusCode > 299) {
            if (error == null) {
              error = new Error(body.message);
            }
            if (body.type) {
              error.code = body.type;
            }
            logOnError(error, response, body);
            return reject(error);
          } else {
            if (options.downloadRequest) {
              return resolve(response);
            } else {
              return resolve(body);
            }
          }
        });
      });
    };

    return NylasConnection;

  })();

  logOnError = function(error, response, body) {
    console.log('nylas-connection#request error: ', error.toString());
    if (error.code != null) {
      console.log('nylas-connection#request error.code: ', error.code);
    }
    if (error.stack) {
      console.log('nylas-connection#request stack: ', error.stack);
    }
    if (response) {
      console.log('nylas-connection#request response.statusCode: ', response.statusCode);
      console.log('nylas-connection#request response.statusMessage: ', response.statusMessage);
    }
    if (body) {
      return console.log('nylas-connection#request body', body);
    }
  };

}).call(this);
<commit_msg>Add compiled files<commit_after>(function() {
  var Account, Attributes, Calendar, Contact, Delta, Draft, Event, File, Folder, Label, ManagementAccount, ManagementModelCollection, Message, NylasConnection, Promise, RestfulModel, RestfulModelCollection, RestfulModelInstance, Tag, Thread, _, clone, logOnError, request;

  _ = require('underscore');

  clone = require('clone');

  request = require('request');

  Promise = require('bluebird');

  RestfulModel = require('./models/restful-model');

  RestfulModelCollection = require('./models/restful-model-collection');

  RestfulModelInstance = require('./models/restful-model-instance');

  Account = require('./models/account');

  ManagementAccount = require('./models/management-account');

  ManagementModelCollection = require('./models/management-model-collection');

  Thread = require('./models/thread');

  Contact = require('./models/contact');

  Message = require('./models/message');

  Draft = require('./models/draft');

  File = require('./models/file');

  Calendar = require('./models/calendar');

  Event = require('./models/event');

  Tag = require('./models/tag');

  Delta = require('./models/delta');

  Label = require('./models/folder').Label;

  Folder = require('./models/folder').Folder;

  Attributes = require('./models/attributes');

  module.exports = NylasConnection = (function() {
    function NylasConnection(accessToken) {
      this.accessToken = accessToken;
      this.threads = new RestfulModelCollection(Thread, this);
      this.contacts = new RestfulModelCollection(Contact, this);
      this.messages = new RestfulModelCollection(Message, this);
      this.drafts = new RestfulModelCollection(Draft, this);
      this.files = new RestfulModelCollection(File, this);
      this.calendars = new RestfulModelCollection(Calendar, this);
      this.events = new RestfulModelCollection(Event, this);
      this.tags = new RestfulModelCollection(Tag, this);
      this.deltas = new Delta(this);
      this.labels = new RestfulModelCollection(Label, this);
      this.folders = new RestfulModelCollection(Folder, this);
      this.account = new RestfulModelInstance(Account, this);
    }

    NylasConnection.prototype.requestOptions = function(options) {
      var Nylas, user;
      if (options == null) {
        options = {};
      }
      options = clone(options);
      Nylas = require('./nylas');
      if (options.method == null) {
        options.method = 'GET';
      }
      if (options.path) {
        if (options.url == null) {
          options.url = "" + Nylas.apiServer + options.path;
        }
      }
      if (!options.formData) {
        if (options.body == null) {
          options.body = {};
        }
      }
      if (options.json == null) {
        options.json = true;
      }
      if (options.downloadRequest == null) {
        options.downloadRequest = false;
      }
      user = options.path.substr(0, 3) === '/a/' ? Nylas.appSecret : this.accessToken;
      if (user) {
        options.auth = {
          'user': user,
          'pass': '',
          'sendImmediately': true
        };
      }
      return options;
    };

    NylasConnection.prototype.request = function(options) {
      if (options == null) {
        options = {};
      }
      options = this.requestOptions(options);
      return new Promise(function(resolve, reject) {
        return request(options, function(error, response, body) {
          var e;
          try {
            if (_.isString(body)) {
              body = JSON.parse(body);
            }
          } catch (_error) {
            e = _error;
            if (!error) {
              error = e;
            }
          }
          if (error || response.statusCode > 299) {
            if (!error) {
              if (_.isString(body.message)) {
                error = new Error(body.message);
              } else {
                error = new Error(JSON.stringify(body.message));
              }
            }
            if (body.type) {
              error.code = body.type;
            }
            if (body.server_error) {
              error.server_error = body.server_error;
            }
            logOnError(error, response, body);
            return reject(error);
          } else {
            if (options.downloadRequest) {
              return resolve(response);
            } else {
              return resolve(body);
            }
          }
        });
      });
    };

    return NylasConnection;

  })();

  logOnError = function(error, response, body) {
    console.log('nylas-connection#request error: ', error.toString());
    if (error.code != null) {
      console.log('nylas-connection#request error.code: ', error.code);
    }
    if (error.stack) {
      console.log('nylas-connection#request stack: ', error.stack);
    }
    if (response) {
      console.log('nylas-connection#request response.statusCode: ', response.statusCode);
      console.log('nylas-connection#request response.statusMessage: ', response.statusMessage);
    }
    if (body) {
      return console.log('nylas-connection#request body', body);
    }
  };

}).call(this);
<|endoftext|>


<commit_before>/*
 Copyright 2011 WebDriver committers
 Copyright 2011 Google Inc.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

goog.provide('SyntheticMouse');

goog.require('Utils');
goog.require('bot.ErrorCode');
goog.require('bot.Mouse');
goog.require('bot.action');
goog.require('bot.dom');
goog.require('bot.events');
goog.require('fxdriver.moz');
goog.require('fxdriver.utils');
goog.require('fxdriver.Logger');

var CC = Components.classes;
var CI = Components.interfaces;

SyntheticMouse = function() {
  this.wrappedJSObject = this;

  this.QueryInterface = fxdriver.moz.queryInterface(this,
      [CI.nsISupports, CI.wdIMouse]);

  // Declare the state we'll be using
  this.buttonDown = null;
  this.lastElement = null;
}

SyntheticMouse.newResponse = function(status, message) {
  return {
    status: status,
    message: message,
    QueryInterface: function(iid) {
      if (iid.equals(Components.interfaces.wdIStatus) ||
          iid.equals(Components.interfaces.nsISupports))
        return this;
      throw Components.results.NS_NOINTERFACE;
    }
  };
};

SyntheticMouse.prototype.isElementShown = function(element) {
  if (!bot.dom.isShown(element, /*ignoreOpacity=*/true)) {
    return SyntheticMouse.newResponse(bot.ErrorCode.ELEMENT_NOT_VISIBLE,
        'Element is not currently visible and so may not be interacted with')
  }
};

SyntheticMouse.prototype.getElement_ = function(coords) {
  return coords.auxiliary ?
      fxdriver.moz.unwrap(coords.auxiliary) : this.lastElement;
};

// wdIMouse

SyntheticMouse.prototype.move = function(target, xOffset, yOffset) {
  // TODO(simon): find the current "body" element iff element == null
  var element = target ?
      fxdriver.moz.unwrap(target) : this.lastElement;

   if (goog.isFunction(element.scrollIntoView)) {
     element.scrollIntoView();
  }

  // The following code assumes xOffset, yOffset are absolute in the DOM.
  // If the page was scrolled, the scroll offset should be subtracted
  // from the provided offset since the movement events are generated
  // relative to the viewport.
  var doc = goog.dom.getOwnerDocument(element);
  var currentScroll = goog.dom.getDomHelper(doc).getDocumentScroll();
  xOffset -= currentScroll.x;
  yOffset -= currentScroll.y;

  // If the mouse was already moved within this document, assume the last
  // coordinates of the mouse are the location of lastElement.
  // This only makes sense, of course, if the last element and the current
  // element belong to the same document.
  if (this.lastElement && element && this.lastElement != element &&
      (this.lastElement.ownerDocument == element.ownerDocument)) {
    var currLoc = Utils.getElementLocation(this.lastElement);
    var targetLoc = Utils.getElementLocation(element);
    xOffset += targetLoc['x'] - currLoc['x'];
    yOffset += targetLoc['y'] - currLoc['y'];
  }

  this.lastElement = element;
  var pos = Utils.getElementLocation(element);
  var owner = goog.dom.getOwnerDocument(element);
  var win = goog.dom.getWindow(owner);
  bot.setWindow(win);

  // Are we about to be dragged out of the window?
  var helper = new goog.dom.DomHelper(owner);

  var viewportSize = goog.dom.getViewportSize(win);
  var docHeight = helper.getDocumentHeight();
  var docWidth = owner.body.scrollWidth;

  var maxHeight = docHeight < viewportSize.height ? viewportSize.height : docHeight;
  var maxWidth = docWidth < viewportSize.width ? viewportSize.width : docWidth;

  var targetX = pos.x + xOffset;
  var targetY = pos.y + yOffset;

  // It turns out that OPTION elements are problematic.
  var requiresCheck = !bot.dom.isElement(element, goog.dom.TagName.OPTION);
  if (requiresCheck && (targetX > maxWidth || targetY > maxHeight)) {
    return SyntheticMouse.newResponse(bot.ErrorCode.MOVE_TARGET_OUT_OF_BOUNDS,
        'Requested location (' + targetX + ', ' + targetY +
        ') is outside the bounds of the document (' + maxWidth + ', ' + maxHeight + ')');
  }

  // Which element shall we pretend to be leaving?
  var parent = bot.dom.getParentElement(element);

  // TODO(simon): if no offset is specified, use the centre of the element
  var fireAndCheck = function(e, eventName, opt_coordinates) {
    if (!e) {
      return false;
    }
    bot.events.fire(e, eventName, opt_coordinates);
    return true;
  };

  var button = this.buttonDown;
  var botCoords = {
    'clientX': pos.x,
    'clientY': pos.y,
    'button': button,
    'related': parent
  };

  var intermediateSteps = 3;
  var xInc = Math.floor(xOffset / intermediateSteps);
  var yInc = Math.floor(yOffset / intermediateSteps);
  var currX = pos.x;
  var currY = pos.y;

  var proceed = fireAndCheck(parent, goog.events.EventType.MOUSEOUT, {'related': element}) &&
      fireAndCheck(element, goog.events.EventType.MOUSEOVER, botCoords);
    for (var i = 0; i < intermediateSteps && proceed; i++) {
      botCoords['clientX'] = xInc + currX;  currX += xInc;
      botCoords['clientY'] = yInc + currY;  currY += yInc;
      proceed = fireAndCheck(element, goog.events.EventType.MOUSEMOVE, botCoords);
  }

  botCoords['clientX'] = (pos.x + xOffset);
  botCoords['clientY'] = (pos.y + yOffset);

  proceed = fireAndCheck(element, goog.events.EventType.MOUSEMOVE, botCoords);

  var newPos = Utils.getElementLocation(this.lastElement);
  var xDifference = Math.abs(botCoords['clientX'] - newPos.x);
  var yDifference = Math.abs(botCoords['clientY'] - newPos.y);
  // Allow a 3-pixel deviation, since synthetic events are not as accurate
  // as native ones.
//  if (((origXOffset != 0) || (origYOffset != 0)) &&
//      ((xDifference > 3) || (yDifference > 3))) {
//    return SyntheticMouse.newResponse(bot.ErrorCode.MOVE_TARGET_OUT_OF_BOUNDS,
//        'Move could not be performed as far as requested: (' + newPos.x + ' ' +
//        newPos.y + ') targeted  (' + botCoords['clientX'] + ' ' + botCoords['clientY'] + ')');
//  }

  if (!proceed || !bot.dom.isShown(element, /*ignoreOpacity=*/true)) {
    return SyntheticMouse.newResponse(bot.ErrorCode.SUCCESS, "ok");
  }

  bot.events.fire(element, goog.events.EventType.MOUSEOVER, botCoords);

  return SyntheticMouse.newResponse(bot.ErrorCode.SUCCESS, "ok");
};

SyntheticMouse.prototype.click = function(target) {

  // No need to unwrap the target. All information is provided by the wrapped
  // version, and unwrapping does not work for all firefox versions.
  var element = target ? target : this.lastElement;

  var error = this.isElementShown(element);
  if (error) {
    return error;
  }

  // Check to see if this is an option element. If it is, and the parent isn't a multiple
  // select, then click on the select first.
  var tagName = element.tagName.toLowerCase();
  if ("option" == tagName) {
    var parent = element;
    while (parent.parentNode != null && parent.tagName.toLowerCase() != "select") {
      parent = parent.parentNode;
    }

    if (parent && parent.tagName.toLowerCase() == "select" && !parent.multiple) {
      bot.action.click(parent);
    }
  }

  fxdriver.Logger.dumpn("About to do a bot.action.click on " + element);
  bot.action.click(element);

  return SyntheticMouse.newResponse(bot.ErrorCode.SUCCESS, "ok");
};

SyntheticMouse.prototype.contextClick = function(target) {

  // No need to unwrap the target. All information is provided by the wrapped
  // version, and unwrapping does not work for all firefox versions.
  var element = target ? target : this.lastElement;

  var error = this.isElementShown(element);
  if (error) {
    return error;
  }

  fxdriver.Logger.dumpn("About to do a bot.action.rightClick on " + element);
  bot.action.rightClick(element);

  return SyntheticMouse.newResponse(bot.ErrorCode.SUCCESS, "ok");
};

SyntheticMouse.prototype.doubleClick = function(target) {
  var element = target ? target : this.lastElement;

  var error = this.isElementShown(element);
  if (error) {
    return error;
  }

  fxdriver.Logger.dumpn("About to do a bot.action.doubleClick on " + element);
  bot.action.doubleClick(element);

  return SyntheticMouse.newResponse(bot.ErrorCode.SUCCESS, "ok");
};

SyntheticMouse.prototype.down = function(coordinates) {
  var element = this.getElement_(coordinates);

  var pos = goog.style.getClientPosition(element);

  // TODO(simon): This implementation isn't good enough. Again
  // Defaults to left mouse button, which is right.
  this.buttonDown = bot.Mouse.Button.LEFT;
  var botCoords = {
    'clientX': coordinates['x'] + pos.x,
    'clientY': coordinates['y'] + pos.y,
    'button': bot.Mouse.Button.LEFT
  };
  bot.events.fire(element, goog.events.EventType.MOUSEDOWN, botCoords);

  return SyntheticMouse.newResponse(bot.ErrorCode.SUCCESS, "ok");
};

SyntheticMouse.prototype.up = function(coordinates) {
  var element = this.getElement_(coordinates);

  var pos = goog.style.getClientPosition(element);

  // TODO(simon): This implementation isn't good enough. Again
  // Defaults to left mouse button, which is the correct one.
  var button = this.buttonDown;
  var botCoords = {
    'clientX': coordinates['x'] + pos.x,
    'clientY': coordinates['y'] + pos.y,
    'button': button
  };
  bot.events.fire(element, goog.events.EventType.MOUSEMOVE, botCoords);
  bot.events.fire(element, goog.events.EventType.MOUSEUP, botCoords);

  this.buttonDown = null;

  return SyntheticMouse.newResponse(bot.ErrorCode.SUCCESS, "ok");
};

// And finally, registering
SyntheticMouse.prototype.classDescription = "Pure JS implementation of a mouse";
SyntheticMouse.prototype.contractID = '@googlecode.com/webdriver/syntheticmouse;1';
SyntheticMouse.prototype.classID = Components.ID('{E8F9FEFE-C513-4097-98BE-BE00A41D3645}');

/** @const */ var components = [SyntheticMouse];
var NSGetFactory, NSGetModule;

fxdriver.moz.load('resource://gre/modules/XPCOMUtils.jsm');

if (XPCOMUtils.generateNSGetFactory) {
  NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
} else {
  NSGetModule = XPCOMUtils.generateNSGetModule(components);
}

goog.exportSymbol('SyntheticMouse', SyntheticMouse);
goog.exportSymbol('SyntheticMouse.prototype.down', SyntheticMouse.prototype.down);
goog.exportSymbol('SyntheticMouse.prototype.up', SyntheticMouse.prototype.up);

goog.exportSymbol('SyntheticMouse.prototype.move', SyntheticMouse.prototype.move);

goog.exportSymbol('SyntheticMouse.prototype.click', SyntheticMouse.prototype.click);
goog.exportSymbol('SyntheticMouse.prototype.doubleClick', SyntheticMouse.prototype.doubleClick);
goog.exportSymbol('SyntheticMouse.prototype.contextClick', SyntheticMouse.prototype.contextClick);
<commit_msg>SimonStewart: Picking one of the many available choices for the height of the document in the synthetic mouse<commit_after>/*
 Copyright 2011 WebDriver committers
 Copyright 2011 Google Inc.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

goog.provide('SyntheticMouse');

goog.require('Utils');
goog.require('bot.ErrorCode');
goog.require('bot.Mouse');
goog.require('bot.action');
goog.require('bot.dom');
goog.require('bot.events');
goog.require('fxdriver.moz');
goog.require('fxdriver.utils');
goog.require('fxdriver.Logger');

var CC = Components.classes;
var CI = Components.interfaces;

SyntheticMouse = function() {
  this.wrappedJSObject = this;

  this.QueryInterface = fxdriver.moz.queryInterface(this,
      [CI.nsISupports, CI.wdIMouse]);

  // Declare the state we'll be using
  this.buttonDown = null;
  this.lastElement = null;
};

SyntheticMouse.newResponse = function(status, message) {
  return {
    status: status,
    message: message,
    QueryInterface: function(iid) {
      if (iid.equals(Components.interfaces.wdIStatus) ||
          iid.equals(Components.interfaces.nsISupports))
        return this;
      throw Components.results.NS_NOINTERFACE;
    }
  };
};

SyntheticMouse.prototype.isElementShown = function(element) {
  if (!bot.dom.isShown(element, /*ignoreOpacity=*/true)) {
    return SyntheticMouse.newResponse(bot.ErrorCode.ELEMENT_NOT_VISIBLE,
        'Element is not currently visible and so may not be interacted with')
  }
};

SyntheticMouse.prototype.getElement_ = function(coords) {
  return coords.auxiliary ?
      fxdriver.moz.unwrap(coords.auxiliary) : this.lastElement;
};

// wdIMouse

SyntheticMouse.prototype.move = function(target, xOffset, yOffset) {
  // TODO(simon): find the current "body" element iff element == null
  var element = target ?
      fxdriver.moz.unwrap(target) : this.lastElement;
  var doc = goog.dom.getOwnerDocument(element);

  if (goog.isFunction(element.scrollIntoView)) {
     goog.style.scrollIntoContainerView(element, doc.documentElement);
  }

  // The following code assumes xOffset, yOffset are absolute in the DOM.
  // If the page was scrolled, the scroll offset should be subtracted
  // from the provided offset since the movement events are generated
  // relative to the viewport.
  var currentScroll = goog.dom.getDomHelper(doc).getDocumentScroll();
  xOffset -= currentScroll.x;
  yOffset -= currentScroll.y;

  // If the mouse was already moved within this document, assume the last
  // coordinates of the mouse are the location of lastElement.
  // This only makes sense, of course, if the last element and the current
  // element belong to the same document.
  if (this.lastElement && element && this.lastElement != element &&
      (this.lastElement.ownerDocument == element.ownerDocument)) {
    var currLoc = Utils.getElementLocation(this.lastElement);
    var targetLoc = Utils.getElementLocation(element);
    xOffset += targetLoc['x'] - currLoc['x'];
    yOffset += targetLoc['y'] - currLoc['y'];
  }

  this.lastElement = element;
  var pos = Utils.getElementLocation(element);
  var owner = goog.dom.getOwnerDocument(element);
  var win = goog.dom.getWindow(owner);
  bot.setWindow(win);

  // Are we about to be dragged out of the window?
  var helper = new goog.dom.DomHelper(owner);

  var viewportSize = goog.dom.getViewportSize(win);
  var docHeight = helper.getDocumentHeight();
  var scrollHeight = owner.body.scrollHeight;
  var docWidth = owner.body.scrollWidth;

  var maxHeight = docHeight < viewportSize.height ? viewportSize.height : docHeight;
  maxHeight = maxHeight < scrollHeight ? scrollHeight : maxHeight;
  var maxWidth = docWidth < viewportSize.width ? viewportSize.width : docWidth;

  var targetX = pos.x + xOffset;
  var targetY = pos.y + yOffset;

  // It turns out that OPTION elements are problematic.
  var requiresCheck = !bot.dom.isElement(element, goog.dom.TagName.OPTION);
  if (requiresCheck && (targetX > maxWidth || targetY > maxHeight)) {
    return SyntheticMouse.newResponse(bot.ErrorCode.MOVE_TARGET_OUT_OF_BOUNDS,
        'Requested location (' + targetX + ', ' + targetY +
        ') is outside the bounds of the document (' + maxWidth + ', ' + maxHeight + ')');
  }

  // Which element shall we pretend to be leaving?
  var parent = bot.dom.getParentElement(element);

  // TODO(simon): if no offset is specified, use the centre of the element
  var fireAndCheck = function(e, eventName, opt_coordinates) {
    if (!e) {
      return false;
    }
    bot.events.fire(e, eventName, opt_coordinates);
    return true;
  };

  var button = this.buttonDown;
  var botCoords = {
    'clientX': pos.x,
    'clientY': pos.y,
    'button': button,
    'related': parent
  };

  var intermediateSteps = 3;
  var xInc = Math.floor(xOffset / intermediateSteps);
  var yInc = Math.floor(yOffset / intermediateSteps);
  var currX = pos.x;
  var currY = pos.y;

  var proceed = fireAndCheck(parent, goog.events.EventType.MOUSEOUT, {'related': element}) &&
      fireAndCheck(element, goog.events.EventType.MOUSEOVER, botCoords);
    for (var i = 0; i < intermediateSteps && proceed; i++) {
      botCoords['clientX'] = xInc + currX;  currX += xInc;
      botCoords['clientY'] = yInc + currY;  currY += yInc;
      proceed = fireAndCheck(element, goog.events.EventType.MOUSEMOVE, botCoords);
  }

  botCoords['clientX'] = (pos.x + xOffset);
  botCoords['clientY'] = (pos.y + yOffset);

  proceed = fireAndCheck(element, goog.events.EventType.MOUSEMOVE, botCoords);

  Utils.getElementLocation(this.lastElement);

  if (!proceed || !bot.dom.isShown(element, /*ignoreOpacity=*/true)) {
    return SyntheticMouse.newResponse(bot.ErrorCode.SUCCESS, "ok");
  }

  bot.events.fire(element, goog.events.EventType.MOUSEOVER, botCoords);

  return SyntheticMouse.newResponse(bot.ErrorCode.SUCCESS, "ok");
};

SyntheticMouse.prototype.click = function(target) {

  // No need to unwrap the target. All information is provided by the wrapped
  // version, and unwrapping does not work for all firefox versions.
  var element = target ? target : this.lastElement;

  var error = this.isElementShown(element);
  if (error) {
    return error;
  }

  // Check to see if this is an option element. If it is, and the parent isn't a multiple
  // select, then click on the select first.
  var tagName = element.tagName.toLowerCase();
  if ("option" == tagName) {
    var parent = element;
    while (parent.parentNode != null && parent.tagName.toLowerCase() != "select") {
      parent = parent.parentNode;
    }

    if (parent && parent.tagName.toLowerCase() == "select" && !parent.multiple) {
      bot.action.click(parent);
    }
  }

  fxdriver.Logger.dumpn("About to do a bot.action.click on " + element);
  bot.action.click(element);

  return SyntheticMouse.newResponse(bot.ErrorCode.SUCCESS, "ok");
};

SyntheticMouse.prototype.contextClick = function(target) {

  // No need to unwrap the target. All information is provided by the wrapped
  // version, and unwrapping does not work for all firefox versions.
  var element = target ? target : this.lastElement;

  var error = this.isElementShown(element);
  if (error) {
    return error;
  }

  fxdriver.Logger.dumpn("About to do a bot.action.rightClick on " + element);
  bot.action.rightClick(element);

  return SyntheticMouse.newResponse(bot.ErrorCode.SUCCESS, "ok");
};

SyntheticMouse.prototype.doubleClick = function(target) {
  var element = target ? target : this.lastElement;

  var error = this.isElementShown(element);
  if (error) {
    return error;
  }

  fxdriver.Logger.dumpn("About to do a bot.action.doubleClick on " + element);
  bot.action.doubleClick(element);

  return SyntheticMouse.newResponse(bot.ErrorCode.SUCCESS, "ok");
};

SyntheticMouse.prototype.down = function(coordinates) {
  var element = this.getElement_(coordinates);

  var pos = goog.style.getClientPosition(element);

  // TODO(simon): This implementation isn't good enough. Again
  // Defaults to left mouse button, which is right.
  this.buttonDown = bot.Mouse.Button.LEFT;
  var botCoords = {
    'clientX': coordinates['x'] + pos.x,
    'clientY': coordinates['y'] + pos.y,
    'button': bot.Mouse.Button.LEFT
  };
  bot.events.fire(element, goog.events.EventType.MOUSEDOWN, botCoords);

  return SyntheticMouse.newResponse(bot.ErrorCode.SUCCESS, "ok");
};

SyntheticMouse.prototype.up = function(coordinates) {
  var element = this.getElement_(coordinates);

  var pos = goog.style.getClientPosition(element);

  // TODO(simon): This implementation isn't good enough. Again
  // Defaults to left mouse button, which is the correct one.
  var button = this.buttonDown;
  var botCoords = {
    'clientX': coordinates['x'] + pos.x,
    'clientY': coordinates['y'] + pos.y,
    'button': button
  };
  bot.events.fire(element, goog.events.EventType.MOUSEMOVE, botCoords);
  bot.events.fire(element, goog.events.EventType.MOUSEUP, botCoords);

  this.buttonDown = null;

  return SyntheticMouse.newResponse(bot.ErrorCode.SUCCESS, "ok");
};

// And finally, registering
SyntheticMouse.prototype.classDescription = "Pure JS implementation of a mouse";
SyntheticMouse.prototype.contractID = '@googlecode.com/webdriver/syntheticmouse;1';
SyntheticMouse.prototype.classID = Components.ID('{E8F9FEFE-C513-4097-98BE-BE00A41D3645}');

/** @const */ var components = [SyntheticMouse];
var NSGetFactory, NSGetModule;

fxdriver.moz.load('resource://gre/modules/XPCOMUtils.jsm');

if (XPCOMUtils.generateNSGetFactory) {
  NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
} else {
  NSGetModule = XPCOMUtils.generateNSGetModule(components);
}

goog.exportSymbol('SyntheticMouse', SyntheticMouse);
goog.exportSymbol('SyntheticMouse.prototype.down', SyntheticMouse.prototype.down);
goog.exportSymbol('SyntheticMouse.prototype.up', SyntheticMouse.prototype.up);

goog.exportSymbol('SyntheticMouse.prototype.move', SyntheticMouse.prototype.move);

goog.exportSymbol('SyntheticMouse.prototype.click', SyntheticMouse.prototype.click);
goog.exportSymbol('SyntheticMouse.prototype.doubleClick', SyntheticMouse.prototype.doubleClick);
goog.exportSymbol('SyntheticMouse.prototype.contextClick', SyntheticMouse.prototype.contextClick);
<|endoftext|>


<commit_before>function optionalPrefix(x) {
  return /^(https:)?/.test(x); // NOT OK
}

function mandatoryPrefix(x) {
  return /^https:/.test(x); // NOT OK
}

function httpOrHttps(x) {
  return /^https?:/.test(x); // OK
}

function optionalSuffix(x) {
  return /(\.com)?$/.test(x); // NOT OK
}

function mandatorySuffix(x) {
  return /\.com$/.test(x); // OK
}

function protocol(x) {
  return /^(?:https?:|ftp:|file:)?/.test(x); // NOT OK
}

function doubleAnchored(x) {
  return /^(foo|bar)?$/.test(x); // OK
}

function noAnchor(x) {
  return /(foo|bar)?/.test(x); // NOT OK
}

function altAnchor(x) {
  return /^foo|bar$|(baz)?/.test(x); // NOT OK
}

function wildcard(x) {
  return /.*/.test(x); // OK - obviously intended to match anything
}

function wildcard2(x) {
  return /[\d\D]*/.test(x); // OK - obviously intended to match anything
}

function emptyAlt(x) {
  return /^$|foo|bar/.test(x); // OK
}

function emptyAlt2(x) {
  return /(^$|foo|bar)/.test(x); // OK
}

function emptyAlt3(x) {
  return /((^$|foo|bar))/.test(x); // OK
}

function search(x) {
  return /[a-z]*/.search(x); // NOT OK
}

function search2(x) {
  return /[a-z]/.search(x); // OK
}

function lookahead(x) {
  return /(?!x)/.search(x); // OK
}
<commit_msg>JS: Fix and expand test cases<commit_after>function optionalPrefix(x) {
  return /^(https:)?/.test(x); // NOT OK
}

function mandatoryPrefix(x) {
  return /^https:/.test(x); // OK
}

function httpOrHttps(x) {
  return /^https?:/.test(x); // OK
}

function optionalSuffix(x) {
  return /(\.com)?$/.test(x); // NOT OK
}

function mandatorySuffix(x) {
  return /\.com$/.test(x); // OK
}

function protocol(x) {
  return /^(?:https?:|ftp:|file:)?/.test(x); // NOT OK
}

function doubleAnchored(x) {
  return /^(foo|bar)?$/.test(x); // OK
}

function noAnchor(x) {
  return /(foo|bar)?/.test(x); // NOT OK
}

function altAnchor(x) {
  return /^foo|bar$|(baz)?/.test(x); // NOT OK
}

function wildcard(x) {
  return /.*/.test(x); // OK - obviously intended to match anything
}

function wildcard2(x) {
  return /[\d\D]*/.test(x); // OK - obviously intended to match anything
}

function emptyAlt(x) {
  return /^$|foo|bar/.test(x); // OK
}

function emptyAlt2(x) {
  return /(^$|foo|bar)/.test(x); // OK
}

function emptyAlt3(x) {
  return /((^$|foo|bar))/.test(x); // OK
}

function search(x) {
  return /[a-z]*/.search(x); // NOT OK
}

function search2(x) {
  return /[a-z]/.search(x); // OK
}

function lookahead(x) {
  return /(?!x)/.search(x); // OK
}

function searchPrefix(x) {
  return /^foo?/.search(x); // NOT OK - `foo?` does not affect the returned index
}

function searchSuffix(x) {
  return /foo?$/.search(x); // OK - `foo?` affects the returned index
}
<|endoftext|>


<commit_before>module.exports = function(arrayOfTests, generateTestDetails) {
  arrayOfTests = arrayOfTests || []
  generateTestDetails = generateTestDetails || function() {}

  arrayOfTests.forEach(function(test) {
    test = test || {}

    var testDetails = generateTestDetails(test) || {}

    if (test.only === true) {
      it.only.call(null, testDetails.description, testDetails.body)
    } else if (test.skip === true) {
      it.skip.call(null, testDetails.description, testDetails.body)
    } else {
      it.call(null, testDetails.description, testDetails.body)
    }
  })
}
<commit_msg>Allow all tests to be skipped or only'ed<commit_after>module.exports = function(arrayOfTests, generateTestDetails, options) {
  arrayOfTests = arrayOfTests || []
  generateTestDetails = generateTestDetails || function() {}
  options = options || {}

  var testsName = 'Dynamic tests'
  var runTests = function() {
    arrayOfTests.forEach(function (test) {
      test = test || {}

      var testDetails = generateTestDetails(test) || {}

      if (test.only === true) {
        it.only.call(null, testDetails.description, testDetails.body)
      } else if (test.skip === true) {
        it.skip.call(null, testDetails.description, testDetails.body)
      } else {
        it.call(null, testDetails.description, testDetails.body)
      }
    })
  }

  if (options.only === true) {
    describe.only(testsName, function() {
      runTests()
    })
  } else if (options.skip === true) {
    describe.skip(testsName, function() {
      runTests()
    })
  } else {
    describe(testsName, function() {
      runTests()
    })
  }
}
<|endoftext|>


<commit_before>'use strict';
var hasha = require('hasha');
var opts = {algorithm: 'sha1'};

module.exports = function (src, cb) {
	if (Buffer.isBuffer(src)) {
		setImmediate(cb, null, hasha(src, opts));
	} else {
		hasha.fromFile(src, opts, cb);
	}
};

module.exports.sync = function (src) {
	return Buffer.isBuffer(src) ? hasha(src, opts) : hasha.fromFileSync(src, opts);
};
<commit_msg>Minor tweak<commit_after>'use strict';
var hasha = require('hasha');
var opts = {algorithm: 'sha1'};

module.exports = function (src, cb) {
	if (Buffer.isBuffer(src)) {
		setImmediate(cb, null, hasha(src, opts));
		return;
	}

	hasha.fromFile(src, opts, cb);
};

module.exports.sync = function (src) {
	return Buffer.isBuffer(src) ? hasha(src, opts) : hasha.fromFileSync(src, opts);
};
<|endoftext|>


<commit_before>var PageUtils = require('./page-utils.js');
var CommandWrapper = require('./command-wrapper.js');

/**
 * Class that all pages subclass from
 *
 * @param {Object} options Page options defined in page object
 * @constructor
 */
function Page(options, commandLoader, api, client) {
  this.commandLoader = commandLoader;
  this.api = api;
  this.client = client;
  this.name = options.name;
  this.url = this.getUrl(options.url);

  PageUtils
    .createProps(this, options.props || {})
    .createElements(this, options.elements || {})
    .createSections(this, options.sections || {})
    .addCommands(this, options.commands || []);

  CommandWrapper.addWrappedCommands(this, this.commandLoader);
}

Page.prototype = {
  /**
   * Returns the url passed as an argument (or null if no arguments are passed).
   *  If the supplied url is a function, it invokes that function with the page as its context.
   *
   * @method getUrl
   * @param {string} url
   * @returns {string|null}
   */
  getUrl: function(url) {
    if (typeof url === 'function') {
      return url.call(this);
    } else if (typeof url === 'string') {
      return url;
    }

    return null;
  },

  /**
   * This command is an alias to url and also a convenience method because when called without any arguments
   *  it performs a call to .url() with passing the value of `url` property on the page object.
     * Uses `url` protocol command.
   *
   * @method navigate
   * @param {Object} [url=this.url] Url to navigate to.
   * @returns {*}
   */
  navigate: function(url) {
    var goToUrl = url || this.url;
    if (goToUrl === null) {
      throw new Error('Invalid URL: You must either add a url property to "' +
        this.name + '" or provide a url as an argument');
    }
    this.api.url(goToUrl);
    return this;
  }
};

module.exports = Page;
<commit_msg>Fixed #1046 - adds callback to page object navigate()<commit_after>var PageUtils = require('./page-utils.js');
var CommandWrapper = require('./command-wrapper.js');

/**
 * Class that all pages subclass from
 *
 * @param {Object} options Page options defined in page object
 * @constructor
 */
function Page(options, commandLoader, api, client) {
  this.commandLoader = commandLoader;
  this.api = api;
  this.client = client;
  this.name = options.name;
  this.url = this.getUrl(options.url);

  PageUtils
    .createProps(this, options.props || {})
    .createElements(this, options.elements || {})
    .createSections(this, options.sections || {})
    .addCommands(this, options.commands || []);

  CommandWrapper.addWrappedCommands(this, this.commandLoader);
}

Page.prototype = {
  /**
   * Returns the url passed as an argument (or null if no arguments are passed).
   *  If the supplied url is a function, it invokes that function with the page as its context.
   *
   * @method getUrl
   * @param {string} url
   * @returns {string|null}
   */
  getUrl: function(url) {
    if (typeof url === 'function') {
      return url.call(this);
    } else if (typeof url === 'string') {
      return url;
    }

    return null;
  },

  /**
   * This command is an alias to url and also a convenience method because when called without any arguments
   *  it performs a call to .url() with passing the value of `url` property on the page object.
     * Uses `url` protocol command.
   *
   * @method navigate
   * @param {Object} [url=this.url] Url to navigate to.
   * @returns {*}
   */
  navigate: function(url, callback) {
    var goToUrl = url || this.url;
    if (goToUrl === null) {
      throw new Error('Invalid URL: You must either add a url property to "' +
        this.name + '" or provide a url as an argument');
    }
    this.api.url(goToUrl, callback);
    return this;
  }
};

module.exports = Page;
<|endoftext|>