<commit_before>(function(global) {

  'use strict';

  var fabric = global.fabric || (global.fabric = { }),
      extend = fabric.util.object.extend;

  if (fabric.Rect) {
    fabric.warn('fabric.Rect is already defined');
    return;
  }

  var stateProperties = fabric.Object.prototype.stateProperties.concat();
  stateProperties.push('rx', 'ry', 'x', 'y');

  /**
   * Rectangle class
   * @class fabric.Rect
   * @extends fabric.Object
   * @return {fabric.Rect} thisArg
   * @see {@link fabric.Rect#initialize} for constructor definition
   */
  fabric.Rect = fabric.util.createClass(fabric.Object, /** @lends fabric.Rect.prototype */ {

    /**
     * List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged})
     * as well as for history (undo/redo) purposes
     * @type Array
     */
    stateProperties: stateProperties,

    /**
     * Type of an object
     * @type String
     * @default
     */
    type: 'rect',

    /**
     * Horizontal border radius
     * @type Number
     * @default
     */
    rx:   0,

    /**
     * Vertical border radius
     * @type Number
     * @default
     */
    ry:   0,

    /**
     * Used to specify dash pattern for stroke on this object
     * @type Array
     */
    strokeDashArray: null,

    /**
     * Constructor
     * @param {Object} [options] Options object
     * @return {Object} thisArg
     */
    initialize: function(options) {
      options = options || { };

      this.callSuper('initialize', options);
      this._initRxRy();

    },

    /**
     * Initializes rx/ry attributes
     * @private
     */
    _initRxRy: function() {
      if (this.rx && !this.ry) {
        this.ry = this.rx;
      }
      else if (this.ry && !this.rx) {
        this.rx = this.ry;
      }
    },

    /**
     * @private
     * @param {CanvasRenderingContext2D} ctx Context to render on
     */
    _render: function(ctx, noTransform) {

      // optimize 1x1 case (used in spray brush)
      if (this.width === 1 && this.height === 1) {
        ctx.fillRect(0, 0, 1, 1);
        return;
      }

      var rx = this.rx ? Math.min(this.rx, this.width / 2) : 0,
          ry = this.ry ? Math.min(this.ry, this.height / 2) : 0,
          w = this.width,
          h = this.height,
          x = noTransform ? this.left : -this.width / 2,
          y = noTransform ? this.top : -this.height / 2,
          isRounded = rx !== 0 || ry !== 0,
          k = 1 - 0.5522847498 /* "magic number" for bezier approximations of arcs (http://itc.ktu.lt/itc354/Riskus354.pdf) */;

      ctx.beginPath();

      ctx.moveTo(x + rx, y);

      ctx.lineTo(x + w - rx, y);
      isRounded && ctx.bezierCurveTo(x + w - k * rx, y, x + w, y + k * ry, x + w, y + ry);

      ctx.lineTo(x + w, y + h - ry);
      isRounded && ctx.bezierCurveTo(x + w, y + h - k * ry, x + w - k * rx, y + h, x + w - rx, y + h);

      ctx.lineTo(x + rx, y + h);
      isRounded && ctx.bezierCurveTo(x + k * rx, y + h, x, y + h - k * ry, x, y + h - ry);

      ctx.lineTo(x, y + ry);
      isRounded && ctx.bezierCurveTo(x, y + k * ry, x + k * rx, y, x + rx, y);

      ctx.closePath();

      this._renderFill(ctx);
      this._renderStroke(ctx);
    },

    /**
     * @private
     * @param {CanvasRenderingContext2D} ctx Context to render on
     */
    _renderDashedStroke: function(ctx) {
      var x = -this.width / 2,
          y = -this.height / 2,
          w = this.width,
          h = this.height;

      ctx.beginPath();
      fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray);
      fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray);
      fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray);
      fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray);
      ctx.closePath();
    },

    /**
     * Returns object representation of an instance
     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
     * @return {Object} object representation of an instance
     */
    toObject: function(propertiesToInclude) {
      var object = extend(this.callSuper('toObject', propertiesToInclude), {
        rx: this.get('rx') || 0,
        ry: this.get('ry') || 0
      });
      if (!this.includeDefaultValues) {
        this._removeDefaultValues(object);
      }
      return object;
    },

    /* _TO_SVG_START_ */
    /**
     * Returns svg representation of an instance
     * @param {Function} [reviver] Method for further parsing of svg representation.
     * @return {String} svg representation of an instance
     */
    toSVG: function(reviver) {
      var markup = this._createBaseSVGMarkup(), x = this.left, y = this.top;
      if (!(this.group && this.group.type === 'path-group')) {
        x = -this.width / 2;
        y = -this.height / 2;
      }
      markup.push(
        '<rect ',
          'x="', x, '" y="', y,
          '" rx="', this.get('rx'), '" ry="', this.get('ry'),
          '" width="', this.width, '" height="', this.height,
          '" style="', this.getSvgStyles(),
          '" transform="', this.getSvgTransform(),
          this.getSvgTransformMatrix(),
        '"/>\n');

      return reviver ? reviver(markup.join('')) : markup.join('');
    },
    /* _TO_SVG_END_ */

    /**
     * Returns complexity of an instance
     * @return {Number} complexity
     */
    complexity: function() {
      return 1;
    }
  });

  /* _FROM_SVG_START_ */
  /**
   * List of attribute names to account for when parsing SVG element (used by `fabric.Rect.fromElement`)
   * @static
   * @memberOf fabric.Rect
   * @see: http://www.w3.org/TR/SVG/shapes.html#RectElement
   */
  fabric.Rect.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y rx ry width height'.split(' '));

  /**
   * Returns {@link fabric.Rect} instance from an SVG element
   * @static
   * @memberOf fabric.Rect
   * @param {SVGElement} element Element to parse
   * @param {Object} [options] Options object
   * @return {fabric.Rect} Instance of fabric.Rect
   */
  fabric.Rect.fromElement = function(element, options) {
    if (!element) {
      return null;
    }
    options = options || { };

    var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES);

    parsedAttributes.left = parsedAttributes.left || 0;
    parsedAttributes.top  = parsedAttributes.top  || 0;
    var rect = new fabric.Rect(extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes));
    rect.visible = rect.width > 0 && rect.height > 0;
    return rect;
  };
  /* _FROM_SVG_END_ */

  /**
   * Returns {@link fabric.Rect} instance from an object representation
   * @static
   * @memberOf fabric.Rect
   * @param {Object} object Object to create an instance from
   * @return {Object} instance of fabric.Rect
   */
  fabric.Rect.fromObject = function(object) {
    return new fabric.Rect(object);
  };

})(typeof exports !== 'undefined' ? exports : this);
<commit_msg>Change location of rect in 1x1 case<commit_after>(function(global) {

  'use strict';

  var fabric = global.fabric || (global.fabric = { }),
      extend = fabric.util.object.extend;

  if (fabric.Rect) {
    fabric.warn('fabric.Rect is already defined');
    return;
  }

  var stateProperties = fabric.Object.prototype.stateProperties.concat();
  stateProperties.push('rx', 'ry', 'x', 'y');

  /**
   * Rectangle class
   * @class fabric.Rect
   * @extends fabric.Object
   * @return {fabric.Rect} thisArg
   * @see {@link fabric.Rect#initialize} for constructor definition
   */
  fabric.Rect = fabric.util.createClass(fabric.Object, /** @lends fabric.Rect.prototype */ {

    /**
     * List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged})
     * as well as for history (undo/redo) purposes
     * @type Array
     */
    stateProperties: stateProperties,

    /**
     * Type of an object
     * @type String
     * @default
     */
    type: 'rect',

    /**
     * Horizontal border radius
     * @type Number
     * @default
     */
    rx:   0,

    /**
     * Vertical border radius
     * @type Number
     * @default
     */
    ry:   0,

    /**
     * Used to specify dash pattern for stroke on this object
     * @type Array
     */
    strokeDashArray: null,

    /**
     * Constructor
     * @param {Object} [options] Options object
     * @return {Object} thisArg
     */
    initialize: function(options) {
      options = options || { };

      this.callSuper('initialize', options);
      this._initRxRy();

    },

    /**
     * Initializes rx/ry attributes
     * @private
     */
    _initRxRy: function() {
      if (this.rx && !this.ry) {
        this.ry = this.rx;
      }
      else if (this.ry && !this.rx) {
        this.rx = this.ry;
      }
    },

    /**
     * @private
     * @param {CanvasRenderingContext2D} ctx Context to render on
     */
    _render: function(ctx, noTransform) {

      // optimize 1x1 case (used in spray brush)
      if (this.width === 1 && this.height === 1) {
        ctx.fillRect(-0.5, -0.5, 1, 1);
        return;
      }

      var rx = this.rx ? Math.min(this.rx, this.width / 2) : 0,
          ry = this.ry ? Math.min(this.ry, this.height / 2) : 0,
          w = this.width,
          h = this.height,
          x = noTransform ? this.left : -this.width / 2,
          y = noTransform ? this.top : -this.height / 2,
          isRounded = rx !== 0 || ry !== 0,
          k = 1 - 0.5522847498 /* "magic number" for bezier approximations of arcs (http://itc.ktu.lt/itc354/Riskus354.pdf) */;

      ctx.beginPath();

      ctx.moveTo(x + rx, y);

      ctx.lineTo(x + w - rx, y);
      isRounded && ctx.bezierCurveTo(x + w - k * rx, y, x + w, y + k * ry, x + w, y + ry);

      ctx.lineTo(x + w, y + h - ry);
      isRounded && ctx.bezierCurveTo(x + w, y + h - k * ry, x + w - k * rx, y + h, x + w - rx, y + h);

      ctx.lineTo(x + rx, y + h);
      isRounded && ctx.bezierCurveTo(x + k * rx, y + h, x, y + h - k * ry, x, y + h - ry);

      ctx.lineTo(x, y + ry);
      isRounded && ctx.bezierCurveTo(x, y + k * ry, x + k * rx, y, x + rx, y);

      ctx.closePath();

      this._renderFill(ctx);
      this._renderStroke(ctx);
    },

    /**
     * @private
     * @param {CanvasRenderingContext2D} ctx Context to render on
     */
    _renderDashedStroke: function(ctx) {
      var x = -this.width / 2,
          y = -this.height / 2,
          w = this.width,
          h = this.height;

      ctx.beginPath();
      fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray);
      fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray);
      fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray);
      fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray);
      ctx.closePath();
    },

    /**
     * Returns object representation of an instance
     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
     * @return {Object} object representation of an instance
     */
    toObject: function(propertiesToInclude) {
      var object = extend(this.callSuper('toObject', propertiesToInclude), {
        rx: this.get('rx') || 0,
        ry: this.get('ry') || 0
      });
      if (!this.includeDefaultValues) {
        this._removeDefaultValues(object);
      }
      return object;
    },

    /* _TO_SVG_START_ */
    /**
     * Returns svg representation of an instance
     * @param {Function} [reviver] Method for further parsing of svg representation.
     * @return {String} svg representation of an instance
     */
    toSVG: function(reviver) {
      var markup = this._createBaseSVGMarkup(), x = this.left, y = this.top;
      if (!(this.group && this.group.type === 'path-group')) {
        x = -this.width / 2;
        y = -this.height / 2;
      }
      markup.push(
        '<rect ',
          'x="', x, '" y="', y,
          '" rx="', this.get('rx'), '" ry="', this.get('ry'),
          '" width="', this.width, '" height="', this.height,
          '" style="', this.getSvgStyles(),
          '" transform="', this.getSvgTransform(),
          this.getSvgTransformMatrix(),
        '"/>\n');

      return reviver ? reviver(markup.join('')) : markup.join('');
    },
    /* _TO_SVG_END_ */

    /**
     * Returns complexity of an instance
     * @return {Number} complexity
     */
    complexity: function() {
      return 1;
    }
  });

  /* _FROM_SVG_START_ */
  /**
   * List of attribute names to account for when parsing SVG element (used by `fabric.Rect.fromElement`)
   * @static
   * @memberOf fabric.Rect
   * @see: http://www.w3.org/TR/SVG/shapes.html#RectElement
   */
  fabric.Rect.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y rx ry width height'.split(' '));

  /**
   * Returns {@link fabric.Rect} instance from an SVG element
   * @static
   * @memberOf fabric.Rect
   * @param {SVGElement} element Element to parse
   * @param {Object} [options] Options object
   * @return {fabric.Rect} Instance of fabric.Rect
   */
  fabric.Rect.fromElement = function(element, options) {
    if (!element) {
      return null;
    }
    options = options || { };

    var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES);

    parsedAttributes.left = parsedAttributes.left || 0;
    parsedAttributes.top  = parsedAttributes.top  || 0;
    var rect = new fabric.Rect(extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes));
    rect.visible = rect.width > 0 && rect.height > 0;
    return rect;
  };
  /* _FROM_SVG_END_ */

  /**
   * Returns {@link fabric.Rect} instance from an object representation
   * @static
   * @memberOf fabric.Rect
   * @param {Object} object Object to create an instance from
   * @return {Object} instance of fabric.Rect
   */
  fabric.Rect.fromObject = function(object) {
    return new fabric.Rect(object);
  };

})(typeof exports !== 'undefined' ? exports : this);
<|endoftext|>


<commit_before>var fs = require('fs'),
    path = require('path'),
    hbs = require('handlebars'),
    helpers = require('../lib/helpers')(hbs),
    Promise = require('promise'),
    admzip = require('adm-zip'),
    temp = require('temp').track(),
    sqlite3 = require('sqlite3').verbose();

module.exports.buildDashDocSet = function (input) {

    return new Promise(function (resolve) {

        var zip = new admzip(),
            tempdb = temp.openSync('temp.sqlite'),
            db = new sqlite3.Database(tempdb.path),
            template = require('../templates/dash/method.hbs');

        input.uid = module.exports.formatStringForUID(input.title);

        input.files.forEach(function (file) {

            file.methods.forEach(function (method) {

                zip.addFile(
                    input.title + '.docset/Contents/Resources/Documents/' + method.uid + '.html',
                    template(method)
                );

            });

        });

        zip.addFile(
            input.title + '.docset/Contents/Info.plist',
            require('../templates/dash/plist.hbs')(input)
        );

        [
            'bootstrap/bootstrap.min.css',
            'highlight.js/github.min.css'
        ].forEach(function (resource) {

            zip.addLocalFile(
                path.join(__dirname, '../templates/dash/resources/' + resource),
                input.title + '.docset/Contents/Resources/Documents/resources/' + path.dirname(resource)
            );

        });

        db.serialize(function () {

            db.run('CREATE TABLE searchIndex(id INTEGER PRIMARY KEY, name TEXT, type TEXT, path TEXT);');
            db.run('CREATE UNIQUE INDEX anchor ON searchIndex (name, type, path);');

            input.files.forEach(function (file) {

                file.methods.forEach(function (method) {

                    db.run('INSERT OR IGNORE INTO searchIndex(name, type, path) VALUES ($name, $type, $path);', {
                        $name: method.name,
                        $type: method.type.replace(/^[a-z]/, function (match) { return match.toUpperCase(); }),
                        $path: method.uid + '.html'
                    });

                    if (method.tags.param) {

                        method.tags.param.forEach(function (param) {

                            db.run('INSERT OR IGNORE INTO searchIndex(name, type, path) VALUES ($name, $type, $path);', {
                                $name: param.name,
                                $type: 'Parameter',
                                $path: method.uid + '.html#//apple_ref/cpp/Parameter/' + param.name
                            });

                        });

                    }

                    if (method.tags.property) {

                        method.tags.property.forEach(function (property) {

                            db.run('INSERT OR IGNORE INTO searchIndex(name, type, path) VALUES ($name, $type, $path);', {
                                $name: property.name,
                                $type: 'Property',
                                $path: method.uid + '.html#//apple_ref/cpp/Property/' + property.name
                            });

                        });

                    }

                });

            });

        });

        db.close(function () {

            zip.addFile(
                input.title + '.docset/Contents/Resources/docSet.dsidx',
                fs.readFileSync(tempdb.path)
            );

            resolve(zip.toBuffer());

        });

    });

};

module.exports.findPackagePath = function (input) {

    var pkg,
        stat;

    if (fs.existsSync(input)) {

        stat = fs.statSync(input);

        if (stat.isDirectory()) {

            pkg = path.normalize(path.resolve(input) + '/package.json');

        } else if (stat.isFile()) {

            pkg = path.normalize(path.resolve(path.dirname(input)) + '/package.json');

        }

    }

    return pkg;

};

module.exports.formatStringForName = function (content) {

    content = String(content);

    content = content.replace(/\.prototype|\(\)/g, '');

    return content;

};

module.exports.formatStringForUID = function (content) {

    content = String(content).toLowerCase();

    content = content.replace(/[^\w\.]+/g, '-');
    content = content.replace(/^-|-$/g, '');

    return content;

};

module.exports.parseData = function (data, file) {

    var methods = [];

    data.forEach(function (item) {

        var method = {},
            params = {
                required: [],
                optional: []
            };

        if (!item.ignore && item.ctx) {

            method.uid = module.exports.formatStringForUID(file + '-' + item.ctx.string);

            method.isPrivate = item.isPrivate;
            method.type = item.ctx.type;
            method.name = module.exports.formatStringForName(item.ctx.string);

            method.description = item.description.summary;
            method.body = item.description.body;

            method.tags = {};
            method.tags.example = [];

            item.tags.forEach(function (tag_data) {

                var tag = {};

                if (method.tags[tag_data.type] === undefined) {

                    method.tags[tag_data.type] = [];

                }

                if (tag_data.types && tag_data.types.length) {

                    if (tag_data.name) {

                        tag.name = tag_data.name.replace(/^\[|\]$/g, '');
                        tag.isOptional = tag_data.optional;

                    }

                    tag.types = tag_data.types;

                    tag.description = tag_data.description;

                    method.tags[tag_data.type].push(tag);

                } else if (tag_data.string) {

                    method.tags[tag_data.type].push(tag_data.string);

                }

            });

            if (method.tags.param) {

                method.tags.param.forEach(function (param) {

                    if (!param.name.match(/\./)) {

                        if (param.isOptional) {

                            params.optional.push(param.name);

                        } else {

                            params.required.push(param.name);

                        }

                    }

                });

                method.params = params.required.join(', ');

                if (params.optional.length) {

                    if (method.params) {

                        method.params += '[, ' + params.optional.join(', ') + ']';

                    } else {

                        method.params += '[' + params.optional.join(', ') + ']';

                    }

                }

            }

            methods.push(method);

        }

    });

    return methods;

};

module.exports.walk = function (dir, options) {

    var files = [];

    if (!options) {

        options = {};

    }

    if (!options.match) {

        options.match = /\.js$/;

    }

    if (!options.exception) {

        options.exception = /\.git|\.min|node_modules|bower_components|test|gruntfile|gulpfile/i;

    }

    if (fs.existsSync(dir) && fs.statSync(dir).isDirectory()) {

        fs.readdirSync(dir).forEach(function (file) {

            var stat;

            file = path.normalize(dir + '/' + file);

            stat = fs.statSync(file);

            if (stat.isDirectory() && !file.match(options.exception)) {

                files = files.concat(module.exports.walk(file, options));

            } else if (stat.isFile() && file.match(options.match) && !file.match(options.exception)) {

                files.push(file);

            }

        });

    }

    return files;

};
<commit_msg>Don't add parameters to Dash search index<commit_after>var fs = require('fs'),
    path = require('path'),
    hbs = require('handlebars'),
    helpers = require('../lib/helpers')(hbs),
    Promise = require('promise'),
    admzip = require('adm-zip'),
    temp = require('temp').track(),
    sqlite3 = require('sqlite3').verbose();

module.exports.buildDashDocSet = function (input) {

    return new Promise(function (resolve) {

        var zip = new admzip(),
            tempdb = temp.openSync('temp.sqlite'),
            db = new sqlite3.Database(tempdb.path),
            template = require('../templates/dash/method.hbs');

        input.uid = module.exports.formatStringForUID(input.title);

        input.files.forEach(function (file) {

            file.methods.forEach(function (method) {

                zip.addFile(
                    input.title + '.docset/Contents/Resources/Documents/' + method.uid + '.html',
                    template(method)
                );

            });

        });

        zip.addFile(
            input.title + '.docset/Contents/Info.plist',
            require('../templates/dash/plist.hbs')(input)
        );

        [
            'bootstrap/bootstrap.min.css',
            'highlight.js/github.min.css'
        ].forEach(function (resource) {

            zip.addLocalFile(
                path.join(__dirname, '../templates/dash/resources/' + resource),
                input.title + '.docset/Contents/Resources/Documents/resources/' + path.dirname(resource)
            );

        });

        db.serialize(function () {

            db.run('CREATE TABLE searchIndex(id INTEGER PRIMARY KEY, name TEXT, type TEXT, path TEXT);');
            db.run('CREATE UNIQUE INDEX anchor ON searchIndex (name, type, path);');

            input.files.forEach(function (file) {

                file.methods.forEach(function (method) {

                    db.run('INSERT OR IGNORE INTO searchIndex(name, type, path) VALUES ($name, $type, $path);', {
                        $name: method.name,
                        $type: method.type.replace(/^[a-z]/, function (match) { return match.toUpperCase(); }),
                        $path: method.uid + '.html'
                    });

                    if (method.tags.property) {

                        method.tags.property.forEach(function (property) {

                            db.run('INSERT OR IGNORE INTO searchIndex(name, type, path) VALUES ($name, $type, $path);', {
                                $name: property.name,
                                $type: 'Property',
                                $path: method.uid + '.html#//apple_ref/cpp/Property/' + property.name
                            });

                        });

                    }

                });

            });

        });

        db.close(function () {

            zip.addFile(
                input.title + '.docset/Contents/Resources/docSet.dsidx',
                fs.readFileSync(tempdb.path)
            );

            resolve(zip.toBuffer());

        });

    });

};

module.exports.findPackagePath = function (input) {

    var pkg,
        stat;

    if (fs.existsSync(input)) {

        stat = fs.statSync(input);

        if (stat.isDirectory()) {

            pkg = path.normalize(path.resolve(input) + '/package.json');

        } else if (stat.isFile()) {

            pkg = path.normalize(path.resolve(path.dirname(input)) + '/package.json');

        }

    }

    return pkg;

};

module.exports.formatStringForName = function (content) {

    content = String(content);

    content = content.replace(/\.prototype|\(\)/g, '');

    return content;

};

module.exports.formatStringForUID = function (content) {

    content = String(content).toLowerCase();

    content = content.replace(/[^\w\.]+/g, '-');
    content = content.replace(/^-|-$/g, '');

    return content;

};

module.exports.parseData = function (data, file) {

    var methods = [];

    data.forEach(function (item) {

        var method = {},
            params = {
                required: [],
                optional: []
            };

        if (!item.ignore && item.ctx) {

            method.uid = module.exports.formatStringForUID(file + '-' + item.ctx.string);

            method.isPrivate = item.isPrivate;
            method.type = item.ctx.type;
            method.name = module.exports.formatStringForName(item.ctx.string);

            method.description = item.description.summary;
            method.body = item.description.body;

            method.tags = {};
            method.tags.example = [];

            item.tags.forEach(function (tag_data) {

                var tag = {};

                if (method.tags[tag_data.type] === undefined) {

                    method.tags[tag_data.type] = [];

                }

                if (tag_data.types && tag_data.types.length) {

                    if (tag_data.name) {

                        tag.name = tag_data.name.replace(/^\[|\]$/g, '');
                        tag.isOptional = tag_data.optional;

                    }

                    tag.types = tag_data.types;

                    tag.description = tag_data.description;

                    method.tags[tag_data.type].push(tag);

                } else if (tag_data.string) {

                    method.tags[tag_data.type].push(tag_data.string);

                }

            });

            if (method.tags.param) {

                method.tags.param.forEach(function (param) {

                    if (!param.name.match(/\./)) {

                        if (param.isOptional) {

                            params.optional.push(param.name);

                        } else {

                            params.required.push(param.name);

                        }

                    }

                });

                method.params = params.required.join(', ');

                if (params.optional.length) {

                    if (method.params) {

                        method.params += '[, ' + params.optional.join(', ') + ']';

                    } else {

                        method.params += '[' + params.optional.join(', ') + ']';

                    }

                }

            }

            methods.push(method);

        }

    });

    return methods;

};

module.exports.walk = function (dir, options) {

    var files = [];

    if (!options) {

        options = {};

    }

    if (!options.match) {

        options.match = /\.js$/;

    }

    if (!options.exception) {

        options.exception = /\.git|\.min|node_modules|bower_components|test|gruntfile|gulpfile/i;

    }

    if (fs.existsSync(dir) && fs.statSync(dir).isDirectory()) {

        fs.readdirSync(dir).forEach(function (file) {

            var stat;

            file = path.normalize(dir + '/' + file);

            stat = fs.statSync(file);

            if (stat.isDirectory() && !file.match(options.exception)) {

                files = files.concat(module.exports.walk(file, options));

            } else if (stat.isFile() && file.match(options.match) && !file.match(options.exception)) {

                files.push(file);

            }

        });

    }

    return files;

};
<|endoftext|>


<commit_before>module.exports = walker;

// Dependencies
var assert = require("assert");
var Map = require('es6-map');

/**
 * glTF top-level dictionary objects in a useful order in terms of dependencies
 * @type {string[]}
 */
var categories = ["buffers", "bufferViews", "images", "videos", "samplers", "textures", "shaders", "programs",
    "techniques", "materials", "accessors", "meshes", "cameras", "lights", "skins", "nodes", "scenes", "animations"];

function walker(json, functionTable, ctx) {
    console.log(json);
    assert(typeof json == 'object', "no json resource given");
    assert(functionTable, "no functionTable given");
    var currentCategory = -1;
    var referenceMap = new Map();

    function next() {
        currentCategory++;
        if (currentCategory >= categories.length) {
            return false;
        }
        if (json[categories[currentCategory]]) {
            return true;
        }
        return next();
    }

    while (next()) {
        var category = categories[currentCategory];
        var data = json[category];
        var fn = functionTable[category] || functionTable.default;

        //console.log(category, data);
        var keys = Object.keys(data).map(function(id) {
            referenceMap.set(id, data[desc]);
        });
        for (var i = 0; i < keys.length; i++) {
            var id = keys[i];
            var desc = data[id];
            resolveReferences(category, desc, referenceMap);
            if(fn) {
                fn.call(desc, id, ctx);
            }
        }
    }
}

/**
 *
 * @param {string} category The current category (e.g. "materials")
 * @param {object} desc The descriptor of the current object
 * @param {Map} map The map containing all named references that have been already resolved.
 */
function resolveReferences(category, desc, map) {

    var ref = function (obj, name) {
        var id = obj[name];
        assert(id);
        var resolved = map.get(id);
        assert(resolved, "could not resolve reference with id: " + id);
        obj[name] = resolved;
    };

    var refArray = function (arr) {
        var l = arr ? arr.length : 0;
        for (var i = 0; i < l; i++) {
            ref(arr, i);
        }
    };

    // Resolve IDs into references to the referenced objects
    switch (category) {
        case "bufferViews":
            // The ID of the buffer.
            ref(desc, "buffer");
            break;
        case "materials":
            // The ID of the technique
            ref(desc, "technique");
            break;
        case "accessors":
            // The ID of the bufferView.
            ref(desc, "bufferView");
            break;
        case "meshes":
            // An array of primitives, each defining geometry to be rendered with a material
            for (var i = 0; i < desc.primitives.length; i++) {
                var p = desc.primitives[i];
                // A dictionary object of strings, where each string is the ID of the
                // accessor containing an attribute.
                for (var name in p.attributes) {
                    ref(p.attributes, name);
                }
                // The ID of the accessor that contains the indices
                ref(p, "indices");
                // The ID of the material to apply to this primitive when rendering
                ref(p, "material");
            }
            break;
        case "nodes":
            // TODO: camera, skeletons, skin and jointName
            // The IDs of this node's children
            refArray(desc.children);
            // The IDs of the meshes in this node
            refArray(desc.meshes);
            break;
        case "scenes":
            // The IDs of each root node.
            refArray(desc.nodes);
    }
}
<commit_msg>Support for textures and references in materials.<commit_after>module.exports = walker;

// Dependencies
var assert = require("assert");

/**
 * glTF top-level dictionary objects in a useful order in terms of dependencies
 * @type {string[]}
 */
var CATEGORIES = ["buffers", "bufferViews", "images", "videos", "samplers", "textures", "shaders", "programs",
    "techniques", "materials", "accessors", "meshes", "cameras", "lights", "skins", "nodes", "scenes", "animations"];

function walker(json, functionTable, ctx) {
    console.log(json);
    assert(typeof json == 'object', "no json resource given");
    assert(functionTable, "no functionTable given");
    var currentCategory = -1;
    var referenceMap = new Map();

    function next() {
        currentCategory++;
        if (currentCategory >= CATEGORIES.length) {
            return false;
        }
        if (json[CATEGORIES[currentCategory]]) {
            return true;
        }
        return next();
    }

    while (next()) {
        var category = CATEGORIES[currentCategory];
        var data = json[category];
        var fn = functionTable[category] || functionTable.default;

        //console.log(category, data);
        var keys = Object.keys(data).map(function (id) {
            referenceMap.set(id, data[id]);
            return id;
        });
        for (var i = 0; i < keys.length; i++) {
            var id = keys[i];
            var desc = data[id];
            resolveReferences(category, desc, referenceMap);
            if (fn) {
                fn.call(desc, id, ctx);
            }
        }
    }
}

/**
 *
 * @param {string} category The current category (e.g. "materials")
 * @param {object} desc The descriptor of the current object
 * @param {Map} map The map containing all named references that have been already resolved.
 */
function resolveReferences(category, desc, map) {

    var ref = function (obj, name) {
        var id = obj[name];
        assert(id);
        var resolved = map.get(id);
        assert(resolved, "could not resolve reference with id: " + id);
        resolved._id = id;
        obj[name] = resolved;
    };

    var refArray = function (arr) {
        var l = arr ? arr.length : 0;
        for (var i = 0; i < l; i++) {
            ref(arr, i);
        }
    };

    // Resolve IDs into references to the referenced objects
    switch (category) {
        case "bufferViews":
            // The ID of the buffer.
            ref(desc, "buffer");
            break;
        case "materials":
            // The ID of the technique
            ref(desc, "technique");
            for (var name in desc.values) {
                var value = desc.values[name];
                if (typeof value == "string") {
                    ref(desc.values, name);
                }
            }
            break;
        case "accessors":
            // The ID of the bufferView.
            ref(desc, "bufferView");
            break;
        case "meshes":
            // An array of primitives, each defining geometry to be rendered with a material
            for (var i = 0; i < desc.primitives.length; i++) {
                var p = desc.primitives[i];
                // A dictionary object of strings, where each string is the ID of the
                // accessor containing an attribute.
                for (var name in p.attributes) {
                    ref(p.attributes, name);
                }
                // The ID of the accessor that contains the indices
                ref(p, "indices");
                // The ID of the material to apply to this primitive when rendering
                ref(p, "material");
            }
            break;
        case "nodes":
            // TODO: camera, skeletons, skin and jointName
            // The IDs of this node's children
            refArray(desc.children);
            // The IDs of the meshes in this node
            refArray(desc.meshes);
            break;
        case "scenes":
            // The IDs of each root node.
            refArray(desc.nodes);
            break;
        case "textures":
            // The IDs of each root node.
            ref(desc, "source");
            ref(desc, "sampler");
    }
}
<|endoftext|>


<commit_before>// Node modules
var fs = require('fs')
var config = require('config')
var p = require('path')
var _ = require('lodash')
var async = require('async')
var sqwk = require('sqwk')
var chalk = require('chalk')
var humanize = require('humanize')
var archiver = require('archiver')
var zlib = require('zlib')
var spawn    = require('child_process').spawn
var aws = require('aws-sdk')
aws.config.update(config.destination.s3)

// App modules
var util = require('./util')

// Begin module
module.exports = function() {

  // Globals
  var subject, archive

  if(config.format == 'zip') {
    archive = archiver.create('zip', {})
  }
  else if(config.format == 'tar.gz') {
    archive = archiver('tar', {
      gzip: true,
      gzipOptions: config.gzip_options
    })
  }
  else if(config.format == 'tar') {
    archive = archiver('tar', {})
  }
  else {
    throw Error('Invalid archive format in config')
  }

  // Begin async
  async.waterfall([
    function(callback) { // Read source parent directory

      fs.readdir(config.source.parent_directory, callback)

    },
    function(files, callback) { // INPUT: Select source directory

      sqwk.write('Select a directory for ' + config.target + ' backup', files, callback)

    },

    function(dir_name, index, callback) { // Load .env

      source = {
        name: dir_name,
        directory: p.join(config.source.parent_directory, dir_name)
      }

      var env_path = function(dir) {
        return p.join(source.directory, dir, '.env')
      }

      // Check whether a .env file exists
      // @todo fs.exists will be deprecated so we may need to change this eventually
      async.detect(_.map([''].concat(config.dotenv_directories), env_path), fs.exists, function(env_path) {

        // If there are .env vars load them
        if(env_path) {
          // Load .env variables
          require('dotenv').config({ path: env_path })
        }

        // If there is a database callback true else callback false
        var env = process.env
        if(env_path && env.DB_DATABASE && env.DB_USERNAME && env.DB_PASSWORD) {
          callback(null, true)
        }
        else {
          callback(null, false)
        }
      })

    },
    function(db_found, callback) { // INPUT: Backup MySQL?

      if(db_found) {
        sqwk.write('A database was found. Would you like to include it in the backup?', ['Yes', 'No'], callback)
      }
      else {
        callback(null, 'No', 1)
      }

    },
    function(backup_database, index, callback) { // Backup directory & MySQL

      // Start timers
      util.timer(true)

      // Output file name
      var output = {
        name: p.join(source.name + '-' + util.machine_date() + '.' + config.format)
      }

      sqwk.write([
        'Running ' + config.target + ' backup',
        chalk.dim(output.name)
      ])

      // Add filters to source directory
      var src = [source.directory + '/**'].concat(_.map(config.exclude_directories, function(str) {
        return '!**/' + str + '/**'
      }))

      archive.bulk([{
        src: src
      }])

      archive.on('error', function(err) {
        callback(err)
      })

      // If database include it in backup
      if(backup_database == 'Yes') {
        // Run mysqldump
        var mysqldump = spawn('mysqldump', [
          '-u', process.env.DB_USERNAME,
          '-p' + process.env.DB_PASSWORD,
          // '-p', process.env.DB_PASSWORD,
          process.env.DB_DATABASE
        ])

        // @todo mysqldump error method

        // Stream mysqldump to a new .sql file
        archive.append(mysqldump.stdout, {
          name: process.env.DB_DATABASE + '.sql'
        })
      }

      if(config.target == 'local') {

        output.path = p.join(config.destination.local.directory, output.name)
        output.stream = fs.createWriteStream(output.path)

        output.stream.on('close', function() {
          callback(null, output.name, humanize.filesize(archive.pointer()), util.timer())
        })

      }
      else if(config.target == 's3') {

        var upload_size

        output.stream = require('s3-upload-stream')(new aws.S3()).upload({
          "Bucket": config.destination.s3.bucket,
          "Key": output.name
        })

        /* Handle progress. Example details object:
           { ETag: '"f9ef956c83756a80ad62f54ae5e7d34b"',
             PartNumber: 5,
             receivedSize: 29671068,
             uploadedSize: 29671068 }
        */
        output.stream.on('part', function(details) {
          upload_size = humanize.filesize(details.uploadedSize) + ' uploaded'
          sqwk.write([
            'Running ' + config.target + ' backup',
            chalk.dim(output.name),
            chalk.dim(upload_size) + ' so far'
          ])
        })

        /* Handle upload completion. Example details object:
           { Location: 'https://bucketName.s3.amazonaws.com/filename.ext',
             Bucket: 'bucketName',
             Key: 'filename.ext',
             ETag: '"bf2acbedf84207d696c8da7dbb205b9f-5"' }
        */
        output.stream.on('uploaded', function(details) {
          callback(null, output.name, upload_size, util.timer())
        })

      }
      else {
        callback(Error('Invalid backup target in config'))
      }

      output.stream.on('error', function(err) {
        callback(err)
      })

      archive.pipe(output.stream)

      archive.finalize()

    }
  ], function(err, file, size, time) {

    if(err){
      if(err.message == 'Cancelled by user') {
        // Do nothing
      }
      else if(err.code == 'ENOENT') {
        sqwk.write(['Could not create archive', chalk.dim('Check directory exists')])
      }
      else if(_.isString(err) && err.substr(0, 41) === 'Failed to create a multipart upload on S3') {
        sqwk.write(['Error occured connecting to S3', chalk.dim('Check your AWS credentials')])
      }
      else {
        sqwk.end(err)
      }
    }
    else {
      sqwk.write([
        util.uppercase_first(config.target + ' backup complete'),
        chalk.dim(file),
        chalk.dim(size),
        chalk.dim(time)
      ])
    }

    sqwk.end()

  })
}
<commit_msg>Fixed exclude filter on linux<commit_after>// Node modules
var fs = require('fs')
var config = require('config')
var p = require('path')
var _ = require('lodash')
var async = require('async')
var sqwk = require('sqwk')
var chalk = require('chalk')
var humanize = require('humanize')
var archiver = require('archiver')
var zlib = require('zlib')
var spawn    = require('child_process').spawn
var aws = require('aws-sdk')
aws.config.update(config.destination.s3)

// App modules
var util = require('./util')

// Begin module
module.exports = function() {

  // Globals
  var subject, archive

  if(config.format == 'zip') {
    archive = archiver.create('zip', {})
  }
  else if(config.format == 'tar.gz') {
    archive = archiver('tar', {
      gzip: true,
      gzipOptions: config.gzip_options
    })
  }
  else if(config.format == 'tar') {
    archive = archiver('tar', {})
  }
  else {
    throw Error('Invalid archive format in config')
  }

  // Begin async
  async.waterfall([
    function(callback) { // Read source parent directory

      fs.readdir(config.source.parent_directory, callback)

    },
    function(files, callback) { // INPUT: Select source directory

      sqwk.write('Select a directory for ' + config.target + ' backup', files, callback)

    },

    function(dir_name, index, callback) { // Load .env

      source = {
        name: dir_name,
        directory: p.join(config.source.parent_directory, dir_name)
      }

      var env_path = function(dir) {
        return p.join(source.directory, dir, '.env')
      }

      // Check whether a .env file exists
      // @todo fs.exists will be deprecated so we may need to change this eventually
      async.detect(_.map([''].concat(config.dotenv_directories), env_path), fs.exists, function(env_path) {

        // If there are .env vars load them
        if(env_path) {
          // Load .env variables
          require('dotenv').config({ path: env_path })
        }

        // If there is a database callback true else callback false
        var env = process.env
        if(env_path && env.DB_DATABASE && env.DB_USERNAME && env.DB_PASSWORD) {
          callback(null, true)
        }
        else {
          callback(null, false)
        }
      })

    },
    function(db_found, callback) { // INPUT: Backup MySQL?

      if(db_found) {
        sqwk.write('A database was found. Would you like to include it in the backup?', ['Yes', 'No'], callback)
      }
      else {
        callback(null, 'No', 1)
      }

    },
    function(backup_database, index, callback) { // Backup directory & MySQL

      // Start timers
      util.timer(true)

      // Output file name
      var output = {
        name: p.join(source.name + '-' + util.machine_date() + '.' + config.format)
      }

      sqwk.write([
        'Running ' + config.target + ' backup',
        chalk.dim(output.name)
      ])

      // Add filters to source directory
      var src = [source.directory + '/**'].concat(_.map(config.exclude_directories, function(str) {
        return '!' + source.directory + '/**/' + str + '/**'
      }))

      archive.bulk([{
        src: src
      }])

      archive.on('error', function(err) {
        callback(err)
      })

      // If database include it in backup
      if(backup_database == 'Yes') {
        // Run mysqldump
        var mysqldump = spawn('mysqldump', [
          '-u', process.env.DB_USERNAME,
          '-p' + process.env.DB_PASSWORD,
          // '-p', process.env.DB_PASSWORD,
          process.env.DB_DATABASE
        ])

        // @todo mysqldump error method

        // Stream mysqldump to a new .sql file
        archive.append(mysqldump.stdout, {
          name: process.env.DB_DATABASE + '.sql'
        })
      }

      if(config.target == 'local') {

        output.path = p.join(config.destination.local.directory, output.name)
        output.stream = fs.createWriteStream(output.path)

        output.stream.on('close', function() {
          callback(null, output.name, humanize.filesize(archive.pointer()), util.timer())
        })

      }
      else if(config.target == 's3') {

        var upload_size

        output.stream = require('s3-upload-stream')(new aws.S3()).upload({
          "Bucket": config.destination.s3.bucket,
          "Key": output.name
        })

        /* Handle progress. Example details object:
           { ETag: '"f9ef956c83756a80ad62f54ae5e7d34b"',
             PartNumber: 5,
             receivedSize: 29671068,
             uploadedSize: 29671068 }
        */
        output.stream.on('part', function(details) {
          upload_size = humanize.filesize(details.uploadedSize) + ' uploaded'
          sqwk.write([
            'Running ' + config.target + ' backup',
            chalk.dim(output.name),
            chalk.dim(upload_size) + ' so far'
          ])
        })

        /* Handle upload completion. Example details object:
           { Location: 'https://bucketName.s3.amazonaws.com/filename.ext',
             Bucket: 'bucketName',
             Key: 'filename.ext',
             ETag: '"bf2acbedf84207d696c8da7dbb205b9f-5"' }
        */
        output.stream.on('uploaded', function(details) {
          callback(null, output.name, upload_size, util.timer())
        })

      }
      else {
        callback(Error('Invalid backup target in config'))
      }

      output.stream.on('error', function(err) {
        callback(err)
      })

      archive.pipe(output.stream)

      archive.finalize()

    }
  ], function(err, file, size, time) {

    if(err){
      if(err.message == 'Cancelled by user') {
        // Do nothing
      }
      else if(err.code == 'ENOENT') {
        sqwk.write(['Could not create archive', chalk.dim('Check directory exists')])
      }
      else if(_.isString(err) && err.substr(0, 41) === 'Failed to create a multipart upload on S3') {
        sqwk.write(['Error occured connecting to S3', chalk.dim('Check your AWS credentials')])
      }
      else {
        sqwk.end(err)
      }
    }
    else {
      sqwk.write([
        util.uppercase_first(config.target + ' backup complete'),
        chalk.dim(file),
        chalk.dim(size),
        chalk.dim(time)
      ])
    }

    sqwk.end()

  })
}
<|endoftext|>


<commit_before><commit_msg>Update request info for annotatePDF service in console<commit_after><|endoftext|>


<commit_before>// Karma configuration
module.exports = function(config) {

    var configObj = {

        //Karma jQuery
        //https://github.com/scf2k/karma-jquery

        // base path that will be used to resolve all patterns (eg. files, exclude)
        basePath: '',

        // frameworks to use
        // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
        frameworks: ['mocha', 'chai'],

        // list of files / patterns to load in the browser
        files: [
            'test/*Spec.js',
            '_source/scripts/**/*.js'
        ],

        // list of files to exclude
        exclude: [
        ],

        // preprocess matching files before serving them to the browser
        // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
        preprocessors: {
        },

        // test results reporter to use
        // possible values: 'dots', 'progress'
        // available reporters: https://npmjs.org/browse/keyword/karma-reporter
        // reporters: ['progress'],
        reporters: ['mocha'],

        // web server port
        port: 9876,

        // enable / disable colors in the output (reporters and logs)
        colors: true,

        // level of logging
        // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
        logLevel: config.LOG_INFO,

        // enable / disable watching file and executing tests whenever any file changes
        autoWatch: false,

        // start these browsers
        // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
        //
        // IE, Chrome, SlimerJS, PhantomJS, TrifleJS, BrowserStack
        browsers: ['PhantomJS'],

        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        singleRun: true
    };

    config.set(configObj);
};
<commit_msg>feat: delete karma.conf file from cartridge<commit_after><|endoftext|>


<commit_before>import Ember from 'ember';
import NodeActionsMixin from 'ember-osf/mixins/node-actions';

export default Ember.Controller.extend(NodeActionsMixin, {
    toast: Ember.inject.service(),
    _url: null,
    openModal: false,
    resolve: null,
    latestFileName: null,
    preprint: null,
    dropzoneOptions: {
        uploadMultiple: false,
        method: 'PUT'
    },
    canEdit: Ember.computed('isAdmin', 'isRegistration', function() {
        return this.get('isAdmin') && !(this.get('model').get('registration'));
    }),
    isAdmin: Ember.computed(function() {
        return this.get('model').get('currentUserPermissions').indexOf('admin') >= 0;
    }),
    searchResults: [],
    actions: {
        preUpload(comp, drop, file) {
            this.set('latestFileName', file.name);
            return new Ember.RSVP.Promise(resolve => {
                this.set('resolve', resolve);
            });
        },
        // Save metadata in Jam
        // TODO: Check if this works with proper permissions (will get 401 if not set properly)
        success(ignore, dropzone, file, response) {
            let path = response.path.slice(1);
            let preprint = this.get('preprint');
            let preprintMetadata = this.get('store').createRecord('preprint', {
                    id: path, // TODO: change to guid
                    attributes: {
                        title: preprint.title,
                        abstract: preprint.abstract,
                        authors: preprint.authors,
                        date: new Date(),
                        subject: preprint.subject,
                        tags: preprint.tags,
                        journal: preprint.journal,
                        doi: preprint.doi,
                        path: path
                    }
                });

            preprintMetadata.save().then(() =>
                this.transitionToRoute('preprints', path)
            ).catch(error => {
                console.error(error);
                this.get('toast').error('Could not save preprint metadata!');
            });
        },
        error(ignore, dropzone, file, errorMessage) {
            console.error(errorMessage);
            this.get('toast').error(`Error uploading file:${errorMessage}`);
        },
        buildUrl() {
            return this.get('_url');
        },
        uploadNewPreprintToNewProject(title, abstract, authors, subject, tags, journal, doi) {
            //Create new public project
            let node = this.get('store').createRecord('node', {
                title: title,
                category: 'project',
                description: abstract || null,
                public: true
            });

            this.set('preprint', {
                title: title,
                abstract: abstract,
                authors: authors,
                subject: subject,
                tags: tags,
                journal: journal,
                doi: doi
            });

            // TODO: Add logic for if you're not uploading a file
            // Upload a new file to the new project
            node.save().then(() => {
                this.set('_url', `https://test-files.osf.io/file?path=/${this.get('latestFileName')}&nid=${node.id}&provider=osfstorage`);
                this.set('openModal', false);
                this.get('resolve')();
            }).catch(error => {
                console.error(error);
                this.get('toast').error('Could not create preprint project!');
            });
            //TODO: eventually make a call to set an OSF file as a preprint (will probably need a flag for such)
        },
        /**
         * findContributors method.  Queries APIv2 users endpoint on full_name.  Fetches specified page of results.
         * TODO will eventually need to be changed to multifield query.
         *
         * @method findContributors
         * @param {String} query ID of user that will be a contributor on the node
         * @param {Integer} page Page number of results requested
         * @return {Record} Returns specified page of user records matching full_name query
         */
        findContributors(query, page) {
            var _this = this;
            return _this.store.query('user', { filter: { full_name: query }, page: page }).then(function(contributors) {
                _this.set('searchResults', contributors);
                return contributors;
            });
        },
        /**
         * Overrides addContributor method on NodeActionsMixin for manual management of contributors list.
         *
         * @method addContributor
         * @param {String} userId ID of user that will be a contributor on the node
         * @param {String} permission User permission level. One of "read", "write", or "admin". Default: "write".
         * @param {Boolean} isBibliographic Whether user will be included in citations for the node. "default: true"
         * @return {Promise} Returns a promise that resolves to the updated node
         * with the new contributor relationship.
         */
        addContributor(userId, permission, isBibliographic) {
            var node = this.get('_node');
            var contributor = this.store.createRecord('contributor', {
                id: `${node.get('id')}-${userId}`,
                permission: permission,
                bibliographic: isBibliographic
            });
            // For now, fetching contributors with loadAll method.  This requires some manual management of the contributors list.
            node.get('contributors').pushObject(contributor);
            this.get('contributors').pushObject(contributor);
            return node.save();

        }
    }
});
<commit_msg>Fetch nested values in single get.<commit_after>import Ember from 'ember';
import NodeActionsMixin from 'ember-osf/mixins/node-actions';
import permissions from 'ember-osf/const/permissions';

export default Ember.Controller.extend(NodeActionsMixin, {
    toast: Ember.inject.service(),
    _url: null,
    openModal: false,
    resolve: null,
    latestFileName: null,
    preprint: null,
    dropzoneOptions: {
        uploadMultiple: false,
        method: 'PUT'
    },
    canEdit: Ember.computed('isAdmin', 'isRegistration', function() {
        return this.get('isAdmin') && !(this.get('model').get('registration'));
    }),
    isAdmin: Ember.computed(function() {
        return this.get('model.currentUserPermissions').indexOf(permissions.ADMIN) >= 0;
    }),
    searchResults: [],
    actions: {
        preUpload(comp, drop, file) {
            this.set('latestFileName', file.name);
            return new Ember.RSVP.Promise(resolve => {
                this.set('resolve', resolve);
            });
        },
        // Save metadata in Jam
        // TODO: Check if this works with proper permissions (will get 401 if not set properly)
        success(ignore, dropzone, file, response) {
            let path = response.path.slice(1);
            let preprint = this.get('preprint');
            let preprintMetadata = this.get('store').createRecord('preprint', {
                    id: path, // TODO: change to guid
                    attributes: {
                        title: preprint.title,
                        abstract: preprint.abstract,
                        authors: preprint.authors,
                        date: new Date(),
                        subject: preprint.subject,
                        tags: preprint.tags,
                        journal: preprint.journal,
                        doi: preprint.doi,
                        path: path
                    }
                });

            preprintMetadata.save().then(() =>
                this.transitionToRoute('preprints', path)
            ).catch(error => {
                console.error(error);
                this.get('toast').error('Could not save preprint metadata!');
            });
        },
        error(ignore, dropzone, file, errorMessage) {
            console.error(errorMessage);
            this.get('toast').error(`Error uploading file:${errorMessage}`);
        },
        buildUrl() {
            return this.get('_url');
        },
        uploadNewPreprintToNewProject(title, abstract, authors, subject, tags, journal, doi) {
            //Create new public project
            let node = this.get('store').createRecord('node', {
                title: title,
                category: 'project',
                description: abstract || null,
                public: true
            });

            this.set('preprint', {
                title: title,
                abstract: abstract,
                authors: authors,
                subject: subject,
                tags: tags,
                journal: journal,
                doi: doi
            });

            // TODO: Add logic for if you're not uploading a file
            // Upload a new file to the new project
            node.save().then(() => {
                this.set('_url', `https://test-files.osf.io/file?path=/${this.get('latestFileName')}&nid=${node.id}&provider=osfstorage`);
                this.set('openModal', false);
                this.get('resolve')();
            }).catch(error => {
                console.error(error);
                this.get('toast').error('Could not create preprint project!');
            });
            //TODO: eventually make a call to set an OSF file as a preprint (will probably need a flag for such)
        },
        /**
         * findContributors method.  Queries APIv2 users endpoint on full_name.  Fetches specified page of results.
         * TODO will eventually need to be changed to multifield query.
         *
         * @method findContributors
         * @param {String} query ID of user that will be a contributor on the node
         * @param {Integer} page Page number of results requested
         * @return {Record} Returns specified page of user records matching full_name query
         */
        findContributors(query, page) {
            var _this = this;
            return _this.store.query('user', { filter: { full_name: query }, page: page }).then(function(contributors) {
                _this.set('searchResults', contributors);
                return contributors;
            });
        },
        /**
         * Overrides addContributor method on NodeActionsMixin for manual management of contributors list.
         *
         * @method addContributor
         * @param {String} userId ID of user that will be a contributor on the node
         * @param {String} permission User permission level. One of "read", "write", or "admin". Default: "write".
         * @param {Boolean} isBibliographic Whether user will be included in citations for the node. "default: true"
         * @return {Promise} Returns a promise that resolves to the updated node
         * with the new contributor relationship.
         */
        addContributor(userId, permission, isBibliographic) {
            var node = this.get('_node');
            var contributor = this.store.createRecord('contributor', {
                id: `${node.get('id')}-${userId}`,
                permission: permission,
                bibliographic: isBibliographic
            });
            // For now, fetching contributors with loadAll method.  This requires some manual management of the contributors list.
            node.get('contributors').pushObject(contributor);
            this.get('contributors').pushObject(contributor);
            return node.save();

        }
    }
});
<|endoftext|>


<commit_before>import $ from "cheerio";

const RECTANGULAR_SEQUENCE = ["M", "L", "L", "L", "L"];
const CIRCULAR_SEQUENCE = ["M", "m", "a", "a"];

const SvgTestHelper = {
  expectIsRectangular(wrapper) {
    expect(exhibitsShapeSequence(wrapper, RECTANGULAR_SEQUENCE)).to.be.true;
  },

  expectIsCircular(wrapper) {
    expect(exhibitsShapeSequence(wrapper, CIRCULAR_SEQUENCE)).to.be.true;
  }
};

function exhibitsShapeSequence(wrapper, shapeSequence) {
  const commands = getPathCommandsFromWrapper(wrapper);
  return commands.every((command, index) => {
    return command.name === shapeSequence[index];
  });
}

function getPathCommandsFromWrapper(wrapper) {
  const commandStr = $(wrapper.html()).attr("d");
  return parseSvgPathCommands(commandStr);
}

function parseSvgPathCommands(commandStr) {
  const matches = commandStr.match(
    /[MmLlHhVvCcSsQqTtAaZz]+[^MmLlHhVvCcSsQqTtAaZz]*/g
  );

  return matches.map(match => {
    const name = match.charAt(0);
    const args = match.substring(1).split(",").map(arg => parseFloat(arg, 10));

    return {
      raw: match,
      name,
      args
    }
  });
}

export default SvgTestHelper;
<commit_msg>Split helpers into expectations and helpers<commit_after>import $ from "cheerio";

const RECTANGULAR_SEQUENCE = ["M", "L", "L", "L", "L"];
const CIRCULAR_SEQUENCE = ["M", "m", "a", "a"];

const expectations = {
  expectIsRectangular(wrapper) {
    expect(exhibitsShapeSequence(wrapper, RECTANGULAR_SEQUENCE)).to.be.true;
  },

  expectIsCircular(wrapper) {
    expect(exhibitsShapeSequence(wrapper, CIRCULAR_SEQUENCE)).to.be.true;
  }
};

const helpers = {
  getBarHeight(wrapper) {
    expectations.expectIsRectangular(wrapper);
    const commands = getPathCommandsFromWrapper(wrapper);
    return Math.abs(commands[0].args[1] - commands[1].args[1]);
  }
};

const SvgTestHelper = Object.assign({}, expectations, helpers);

function exhibitsShapeSequence(wrapper, shapeSequence) {
  const commands = getPathCommandsFromWrapper(wrapper);
  return commands.every((command, index) => {
    return command.name === shapeSequence[index];
  });
}

function getPathCommandsFromWrapper(wrapper) {
  const commandStr = $(wrapper.html()).attr("d");
  return parseSvgPathCommands(commandStr);
}

function parseSvgPathCommands(commandStr) {
  const matches = commandStr.match(
    /[MmLlHhVvCcSsQqTtAaZz]+[^MmLlHhVvCcSsQqTtAaZz]*/g
  );

  return matches.map(match => {
    const name = match.charAt(0);
    const args = match.substring(1).split(",").map(arg => parseFloat(arg, 10));

    return {
      raw: match,
      name,
      args
    }
  });
}

export default SvgTestHelper;
<|endoftext|>


<commit_before>const path = require('path');
const fs = require('fs');
const request = require('request');
const isPlainObject = require('lodash/isPlainObject');
const logger = require('./logger');

const result = (fn, ...args) => (typeof fn === 'function' ? fn(...args) : fn);

const objectToString = (obj) => {
    return Object.keys(obj).reduce((arr, key) => {
        return arr.concat(`${key}: ${obj[key]}`);
    }, []).join(', ');
};

const tmpDir = (str) => {
    return path.join(require('user-home'), '.umeboshi-cli', str.replace(/[/#:]+/g, '-'));
};

const listFolders = (folder) => {
    return fs.readdirSync(folder).filter((f) => (
        fs.statSync(path.join(folder, f)).isDirectory()
    ));
};

const getJSON = (uri) => {
    return new Promise((resolve, reject) => {
        request.get({
            uri,
            headers: {
                'User-Agent': 'request'
            },
            json: true
        }, (err, res, results) => {

            if (err || (res.statusCode < 200 || res.statusCode >= 400)) {

                const errStatus = res ? `(status: ${res.statusCode})` : `(error: ${err.message})`;
                reject(errStatus, err, res);
                return;
            }

            resolve(results, err, res);
        });
    });
};

const getLatestTag = (templateName) => {

    const uri = `https://api.github.com/repos/${templateName}/tags`;

    return getJSON(uri).then(
        (tags) => (tags.length > 0 ? tags[0].name : 'master'),
        (errStatus) => { logger.verbose(`Unable retrieve github tags from ${uri}. ${errStatus}`); }
    );

};

const deleteFile = (files, filepath) => {
    if (files[filepath]) {
        files[filepath] = null; //eslint-disable-line no-param-reassign
        delete files[filepath]; //eslint-disable-line no-param-reassign
        logger.verbose(`File ${filepath} removed.`);
    }
};

const getFileContents = (files, filepath) => {
    if (files[filepath]) {
        return files[filepath].contents.toString();
    }
    return null;
};

const fileToJSON = (files, filepath) => {
    const contents = getFileContents(files, filepath);
    if (contents) { return JSON.parse(contents); }
    return {};
};

const JSONtoBuffer = (json) => new Buffer(JSON.stringify(json, null, 2));

const resolveRepoUrl = (templateName, version) => {
    if (typeof version === 'string' && version !== 'latest') {
        return Promise.resolve(`github:${templateName}#${version}`);
    }
    return getLatestTag(templateName).then((v) => `github:${templateName}#${v}`);
};

function Injector(files) {
    this.files = files;
}

Injector.prototype.at = function injectorAt(file, tag, content = '') {
    if (this.files[file]) {
        const template = this.files[file];

        if (isPlainObject(tag)) {
            Object.keys(tag).forEach((t) => {
                this.at(file, t, tag[t]);
            });
            return;
        }

        template.contents = new Buffer(
            template.contents.toString().replace(`{{!-- ${tag} --}}`, `${content}{{!-- ${tag} --}}`)
        );
    }
};

module.exports = {
    Injector,
    getLatestTag,
    listFolders,
    objectToString,
    tmpDir,
    deleteFile,
    result,
    JSONtoBuffer,
    getFileContents,
    fileToJSON,
    resolveRepoUrl
};<commit_msg>feat(githubtags): semver support for versions<commit_after>const path = require('path');
const fs = require('fs');
const request = require('request');
const isPlainObject = require('lodash/isPlainObject');
const semver = require('semver');
const logger = require('./logger');

const result = (fn, ...args) => (typeof fn === 'function' ? fn(...args) : fn);

const objectToString = (obj) => {
    return Object.keys(obj).reduce((arr, key) => {
        return arr.concat(`${key}: ${obj[key]}`);
    }, []).join(', ');
};

const tmpDir = (str) => {
    return path.join(require('user-home'), '.umeboshi-cli', str.replace(/[/#:]+/g, '-'));
};

const listFolders = (folder) => {
    return fs.readdirSync(folder).filter((f) => (
        fs.statSync(path.join(folder, f)).isDirectory()
    ));
};

const getJSON = (uri) => {
    return new Promise((resolve, reject) => {
        request.get({
            uri,
            headers: {
                'User-Agent': 'request'
            },
            json: true
        }, (err, res, results) => {

            if (err || (res.statusCode < 200 || res.statusCode >= 400)) {

                const errStatus = res ? `(status: ${res.statusCode})` : `(error: ${err.message})`;
                reject(errStatus, err, res);
                return;
            }

            resolve(results, err, res);
        });
    });
};

const getTags = (templateName) => {
    const uri = `https://api.github.com/repos/${templateName}/tags`;

    return getJSON(uri).then(
        (tags) => tags.map(({ name }) => name),
        (errStatus) => { logger.verbose(`Unable retrieve github tags from ${uri}. ${errStatus}`); }
    );
};

const getLatestTag = (templateName) => {

    return getTags(templateName).then(
        (tags) => (tags.length > 0 ? tags[0] : 'master')
    );

};

const deleteFile = (files, filepath) => {
    if (files[filepath]) {
        files[filepath] = null; //eslint-disable-line no-param-reassign
        delete files[filepath]; //eslint-disable-line no-param-reassign
        logger.verbose(`File ${filepath} removed.`);
    }
};

const getFileContents = (files, filepath) => {
    if (files[filepath]) {
        return files[filepath].contents.toString();
    }
    return null;
};

const fileToJSON = (files, filepath) => {
    const contents = getFileContents(files, filepath);
    if (contents) { return JSON.parse(contents); }
    return {};
};

const JSONtoBuffer = (json) => new Buffer(JSON.stringify(json, null, 2));

const resolveRepoUrl = (templateName, version) => {
    if (typeof version === 'string' && version !== 'latest') {
        //master or develop?
        if (semver.valid(version) === null) {
            return Promise.resolve(`github:${templateName}#${version}`);
        }
        return getTags(templateName).then((tags) => {
            const maxVersion = semver.maxSatisfying(tags, version);
            if (maxVersion) {
                return Promise.resolve(`github:${templateName}#${maxVersion}`);
            }
            return Promise.reject(new Error(`No repository releases matches semver "${version}"`));
        });
    }
    return getLatestTag(templateName).then((v) => `github:${templateName}#${v}`);
};

function Injector(files) {
    this.files = files;
}

Injector.prototype.at = function injectorAt(file, tag, content = '') {
    if (this.files[file]) {
        const template = this.files[file];

        if (isPlainObject(tag)) {
            Object.keys(tag).forEach((t) => {
                this.at(file, t, tag[t]);
            });
            return;
        }

        template.contents = new Buffer(
            template.contents.toString().replace(`{{!-- ${tag} --}}`, `${content}{{!-- ${tag} --}}`)
        );
    }
};

module.exports = {
    Injector,
    getLatestTag,
    listFolders,
    objectToString,
    tmpDir,
    deleteFile,
    result,
    JSONtoBuffer,
    getFileContents,
    fileToJSON,
    resolveRepoUrl
};<|endoftext|>


<commit_before>import { describeComponent, it } from 'ember-mocha';
import { beforeEach, afterEach } from 'mocha';
import { expect } from 'chai';
import hbs from 'htmlbars-inline-precompile';
import page from './page';

describeComponent('ember-webcam', 'Integration: EmberWebcamComponent', {
  integration: true
}, () => {
  beforeEach(function () {
    page.setContext(this);
  });

  afterEach(() => {
    page.removeContext();
  });

  it('renders', () => {
    page.render(hbs`{{ember-webcam}}`);
    expect(page.viewer.isVisible).to.be.true;
  });

  it('takes a snapshot', done => {
    let isDone = false;
    page.context.setProperties({
      didError(errorMessage) {
        expect(errorMessage).to.be.ok;
        if (!isDone) {
          done();
          isDone = true;
        }
      }
    });
    page.render(hbs`
      {{#ember-webcam didError=(action didError) as |camera|}}
        <button {{action camera.snap}}>
          Take Snapshot!
        </button>
      {{/ember-webcam}}
    `);
    page.button.click();
  });
});
<commit_msg>Improve component test when fails to take snapshot<commit_after>import { describeComponent, it } from 'ember-mocha';
import { beforeEach, afterEach } from 'mocha';
import { expect } from 'chai';
import hbs from 'htmlbars-inline-precompile';
import page from './page';

describeComponent('ember-webcam', 'Integration: EmberWebcamComponent', {
  integration: true
}, () => {
  beforeEach(function () {
    page.setContext(this);
  });

  afterEach(() => {
    page.removeContext();
  });

  it('renders', () => {
    page.render(hbs`{{ember-webcam}}`);
    expect(page.viewer.isVisible).to.be.true;
  });

  it('takes a snapshot', done => {
    let isDone = false;
    page.context.setProperties({
      didError(error) {
        // Should fail because camera is not available in test environment.
        expect(error.name).to.equal('WebcamError');
        if (!isDone) {
          done();
          isDone = true;
        }
      }
    });
    page.render(hbs`
      {{#ember-webcam didError=(action didError) as |camera|}}
        <button {{action camera.snap}}>
          Take Snapshot!
        </button>
      {{/ember-webcam}}
    `);
    page.button.click();
  });
});
<|endoftext|>


<commit_before>
/*
 *  Guacamole - Clientless Remote Desktop
 *  Copyright (C) 2010  Michael Jumper
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

function GuacamoleMouse(element) {

	/*****************************************/
	/*** Mouse Handler                     ***/
	/*****************************************/

    var mouseIndex = 0;

    var mouseLeftButton   = 0;
    var mouseMiddleButton = 0;
    var mouseRightButton  = 0;

    var mouseX = 0;
    var mouseY = 0;

    var absoluteMouseX = 0;
    var absoluteMouseY = 0;

    function getMouseState(up, down) {
        var mouseState = new MouseEvent(mouseX, mouseY,
                mouseLeftButton, mouseMiddleButton, mouseRightButton, up, down);

        return mouseState;
    }

    // Block context menu so right-click gets sent properly
    element.oncontextmenu = function(e) {return false;};

    element.onmousemove = function(e) {

        e.stopPropagation();

        absoluteMouseX = e.pageX;
        absoluteMouseY = e.pageY;

        mouseX = absoluteMouseX - element.offsetLeft;
        mouseY = absoluteMouseY - element.offsetTop;

        // This is all JUST so we can get the mouse position within the element
        var parent = element.offsetParent;
        while (parent) {
            if (parent.offsetLeft && parent.offsetTop) {
                mouseX -= parent.offsetLeft;
                mouseY -= parent.offsetTop;
            }
            parent = parent.offsetParent;
        }

        movementHandler(getMouseState(0, 0));
    };

    element.onmousedown = function(e) {

        e.stopPropagation();

        switch (e.button) {
            case 0:
                mouseLeftButton = 1;
                break;
            case 1:
                mouseMiddleButton = 1;
                break;
            case 2:
                mouseRightButton = 1;
                break;
        }

        buttonPressedHandler(getMouseState(0, 0));
    };

    element.onmouseup = function(e) {

        e.stopPropagation();

        switch (e.button) {
            case 0:
                mouseLeftButton = 0;
                break;
            case 1:
                mouseMiddleButton = 0;
                break;
            case 2:
                mouseRightButton = 0;
                break;
        }

        buttonReleasedHandler(getMouseState(0, 0));
    };

    element.onmouseout = function(e) {

        e.stopPropagation();

        // Release all buttons
        if (mouseLeftButton || mouseMiddleButton || mouseRightButton) {
            mouseLeftButton = 0;
            mouseMiddleButton = 0;
            mouseRightButton = 0;

            buttonReleasedHandler(getMouseState(0, 0));
        }

    };

    // Override selection on mouse event element.
    element.onselectstart = function() {
        return false;
    };

    // Scroll wheel support
    function handleScroll(e) {

        var delta = 0;
        if (e.detail)
            delta = e.detail;
        else if (e.wheelDelta)
            delta = -event.wheelDelta;

        // Up
        if (delta < 0) {
            buttonPressedHandler(getMouseState(1, 0));
            buttonReleasedHandler(getMouseState(0, 0));
        }

        // Down
        if (delta > 0) {
            buttonPressedHandler(getMouseState(0, 1));
            buttonReleasedHandler(getMouseState(0, 0));
        }

        if (e.preventDefault)
            e.preventDefault();

        e.returnValue = false;
    }

    element.addEventListener('DOMMouseScroll', handleScroll, false);

    element.onmousewheel = function(e) {
        handleScroll(e);
    }

	var buttonPressedHandler = null;
	var buttonReleasedHandler = null;
	var movementHandler = null;

	this.setButtonPressedHandler  = function(mh) {buttonPressedHandler = mh;};
	this.setButtonReleasedHandler = function(mh) {buttonReleasedHandler = mh;};
	this.setMovementHandler = function(mh) {movementHandler = mh;};

    this.getX = function() {return mouseX;};
    this.getY = function() {return mouseY;};
    this.getLeftButton = function() {return mouseLeftButton;};
    this.getMiddleButton = function() {return mouseMiddleButton;};
    this.getRightButton = function() {return mouseRightButton;};

}

function MouseEvent(x, y, left, middle, right, up, down) {

    this.getX = function() {
        return x;
    };

    this.getY = function() {
        return y;
    };

    this.getLeft = function() {
        return left;
    };

    this.getMiddle = function() {
        return middle;
    };

    this.getRight = function() {
        return right;
    };

    this.getUp = function() {
        return up;
    };

    this.getDown = function() {
        return down;
    };

}
<commit_msg>Experimental working touch-based mouse.<commit_after>
/*
 *  Guacamole - Clientless Remote Desktop
 *  Copyright (C) 2010  Michael Jumper
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

function GuacamoleMouse(element) {

	/*****************************************/
	/*** Mouse Handler                     ***/
	/*****************************************/

    var mouseIndex = 0;

    var mouseLeftButton   = 0;
    var mouseMiddleButton = 0;
    var mouseRightButton  = 0;

    var mouseX = 0;
    var mouseY = 0;

    var absoluteMouseX = 0;
    var absoluteMouseY = 0;

    function getMouseState(up, down) {
        var mouseState = new MouseEvent(mouseX, mouseY,
                mouseLeftButton, mouseMiddleButton, mouseRightButton, up, down);

        return mouseState;
    }

    function moveMouse(pageX, pageY) {

        absoluteMouseX = pageX;
        absoluteMouseY = pageY;

        mouseX = absoluteMouseX - element.offsetLeft;
        mouseY = absoluteMouseY - element.offsetTop;

        // This is all JUST so we can get the mouse position within the element
        var parent = element.offsetParent;
        while (parent) {
            if (parent.offsetLeft && parent.offsetTop) {
                mouseX -= parent.offsetLeft;
                mouseY -= parent.offsetTop;
            }
            parent = parent.offsetParent;
        }

        movementHandler(getMouseState(0, 0));

    }

    // Block context menu so right-click gets sent properly
    element.oncontextmenu = function(e) {return false;};

    element.onmousemove = function(e) {

        e.stopPropagation();

        moveMouse(e.pageX, e.pageY);

    };

    element.ontouchend = function(e) {

        e.stopPropagation();
        e.preventDefault();

        // Release all buttons (FIXME: for now...)
        if (mouseLeftButton || mouseMiddleButton || mouseRightButton) {
            mouseLeftButton = 0;
            mouseMiddleButton = 0;
            mouseRightButton = 0;

            buttonReleasedHandler(getMouseState(0, 0));
        }

    }

    element.ontouchstart = function(e) {

        e.stopPropagation();
        e.preventDefault();

        if (e.touches.length == 1)
            element.ontouchmove(e);

        else {

            var button = e.touches[0];
            var pointer = e.touches[1];

            if (pointer.pageX < button.pageX)
                mouseLeftButton = 1;
            else
                mouseRightButton = 1;

            buttonPressedHandler(getMouseState(0, 0));
        }

    };

    element.ontouchmove = function(e) {

        e.stopPropagation();
        e.preventDefault();

        var touch = e.touches[0];
        moveMouse(touch.pageX, touch.pageY);

    };

    element.onmousedown = function(e) {

        e.stopPropagation();

        switch (e.button) {
            case 0:
                mouseLeftButton = 1;
                break;
            case 1:
                mouseMiddleButton = 1;
                break;
            case 2:
                mouseRightButton = 1;
                break;
        }

        buttonPressedHandler(getMouseState(0, 0));
    };

    element.onmouseup = function(e) {

        e.stopPropagation();

        switch (e.button) {
            case 0:
                mouseLeftButton = 0;
                break;
            case 1:
                mouseMiddleButton = 0;
                break;
            case 2:
                mouseRightButton = 0;
                break;
        }

        buttonReleasedHandler(getMouseState(0, 0));
    };

    element.onmouseout = function(e) {

        e.stopPropagation();

        // Release all buttons
        if (mouseLeftButton || mouseMiddleButton || mouseRightButton) {
            mouseLeftButton = 0;
            mouseMiddleButton = 0;
            mouseRightButton = 0;

            buttonReleasedHandler(getMouseState(0, 0));
        }

    };

    // Override selection on mouse event element.
    element.onselectstart = function() {
        return false;
    };

    // Scroll wheel support
    function handleScroll(e) {

        var delta = 0;
        if (e.detail)
            delta = e.detail;
        else if (e.wheelDelta)
            delta = -event.wheelDelta;

        // Up
        if (delta < 0) {
            buttonPressedHandler(getMouseState(1, 0));
            buttonReleasedHandler(getMouseState(0, 0));
        }

        // Down
        if (delta > 0) {
            buttonPressedHandler(getMouseState(0, 1));
            buttonReleasedHandler(getMouseState(0, 0));
        }

        if (e.preventDefault)
            e.preventDefault();

        e.returnValue = false;
    }

    element.addEventListener('DOMMouseScroll', handleScroll, false);

    element.onmousewheel = function(e) {
        handleScroll(e);
    }

	var buttonPressedHandler = null;
	var buttonReleasedHandler = null;
	var movementHandler = null;

	this.setButtonPressedHandler  = function(mh) {buttonPressedHandler = mh;};
	this.setButtonReleasedHandler = function(mh) {buttonReleasedHandler = mh;};
	this.setMovementHandler = function(mh) {movementHandler = mh;};

    this.getX = function() {return mouseX;};
    this.getY = function() {return mouseY;};
    this.getLeftButton = function() {return mouseLeftButton;};
    this.getMiddleButton = function() {return mouseMiddleButton;};
    this.getRightButton = function() {return mouseRightButton;};

}

function MouseEvent(x, y, left, middle, right, up, down) {

    this.getX = function() {
        return x;
    };

    this.getY = function() {
        return y;
    };

    this.getLeft = function() {
        return left;
    };

    this.getMiddle = function() {
        return middle;
    };

    this.getRight = function() {
        return right;
    };

    this.getUp = function() {
        return up;
    };

    this.getDown = function() {
        return down;
    };

}
<|endoftext|>


<commit_before>const tsconfig = require('./tsconfig.json');

module.exports = function(config) {
    config.set({
        frameworks: ['mocha', 'chai', 'sinon', 'karma-typescript'],
        files: [
            { pattern: 'src/**/*.ts' }, // *.tsx for React Jsx
            { pattern: 'test/unit/**/*.spec.ts' }, // *.tsx for React Jsx
        ],
        preprocessors: {
            '**/*.ts': ['karma-typescript'], // *.tsx for React Jsx
        },
        reporters: ['progress', 'karma-typescript'],
        karmaTypescriptConfig: {
            'compilerOptions': tsconfig.compilerOptions,
            reports: {
                'html': '.coverage',
                'text-summary': '',
                'text-lcov': ''
            },
        },
        browsers: ['ChromeHeadless'],
    });
};<commit_msg>removed redundant comma.<commit_after>const tsconfig = require('./tsconfig.json');

module.exports = function(config) {
    config.set({
        frameworks: ['mocha', 'chai', 'sinon', 'karma-typescript'],
        files: [
            { pattern: 'src/**/*.ts' }, // *.tsx for React Jsx
            { pattern: 'test/unit/**/*.spec.ts' }, // *.tsx for React Jsx
        ],
        preprocessors: {
            '**/*.ts': ['karma-typescript'], // *.tsx for React Jsx
        },
        reporters: ['progress', 'karma-typescript'],
        karmaTypescriptConfig: {
            'compilerOptions': tsconfig.compilerOptions,
            reports: {
                'html': '.coverage',
                'text-summary': '',
                'text-lcov': ''
            }
        },
        browsers: ['ChromeHeadless'],
    });
};<|endoftext|>