<commit_before>'use strict';

var extend = require('extend');
require('classlist-polyfill');

/**
 * Mobile crumbtrail behaviour
 */
function MobileCrumbs(element, config) {

  var options = {
    leftClass: 'breadcrumbs-at-left',
    rightClass: 'breadcrumbs-at-right',
    enabledClass: 'breadcrumbs-mobile-scrolling-enabled',
    debounceDelay: 150
  };

  extend(options, config);

  // Private variables
  var scrollTimeout = null;
  var resizeTimeout = null;

  /**
   * Set everything up
   */
  function create() {

    // Bail out if we don't have the proper element to act upon
    if (!element) {
      return;
    }

    // element.classList.add(options.enabledClass);

    // Scroll the crumbtrail all the way to the right by default
    element.scrollLeft = element.clientWidth;

    element.addEventListener('scroll', scrollListener);
    window.addEventListener('load', calc);

    window.addEventListener('resize', resizeListener);

  }

  /**
   * Main scroll event listener
   * @param  {Event} e
   */
  function scrollListener() {
    clearTimeout(scrollTimeout);

    scrollTimeout = setTimeout(function() {
      calc();
    }, options.debounceDelay);
  }

  /**
   * Window resize listener
   * Used to "stick" the crumbtrail to the right hand side
   * @param  {Event} e
   */
  function resizeListener() {
    clearTimeout(resizeTimeout);

    resizeTimeout = setTimeout(function() {
      element.scrollLeft = element.clientWidth;

      calc();
    }, options.debounceDelay);
  }

  /**
   * Main calculation handler
   * Called on scroll (debounced) and on window load
   */
  function calc() {

    // If we're too narrow to need peepage
    if(element.clientWidth >= element.scrollWidth) {
      element.classList.remove(options.leftClass);
      element.classList.remove(options.rightClass);
      element.classList.remove(options.enabledClass);

      return;
    }

    // Otherwise, enable the peepage
    element.classList.add(options.enabledClass);

    // If we're at the end
    if(element.scrollLeft === element.scrollWidth - element.offsetWidth) {
      element.classList.add(options.rightClass);
      element.classList.remove(options.leftClass);
    }

    // If we're at the start
    else if(element.scrollLeft === 0) {
      element.classList.add(options.leftClass);
      element.classList.remove(options.rightClass);

    }

    // Otherwise we're somewhere in between
    else {
      element.classList.remove(options.leftClass);
      element.classList.remove(options.rightClass);
    }
  }

  /**
   * Tear everything down again
   */
  function destroy() {
    // Unbind any queued listeners
    clearTimeout(resizeTimeout);
    clearTimeout(scrollTimeout);

    // Unbind events
    element.removeEventListener('scroll', scrollListener);
    window.removeEventListener('load', calc);
    window.removeEventListener('resize', calc);

    // Remove all classes
    element.classList.remove(options.leftClass);
    element.classList.remove(options.rightClass);
    element.classList.remove(options.enabledClass);
  }

  var self = {
    create: create,
    destroy: destroy
  };

  return self;

}

module.exports = MobileCrumbs;
<commit_msg>Removing reference to outdated polyfill<commit_after>'use strict';

var extend = require('extend');

/**
 * Mobile crumbtrail behaviour
 */
function MobileCrumbs(element, config) {

  var options = {
    leftClass: 'breadcrumbs-at-left',
    rightClass: 'breadcrumbs-at-right',
    enabledClass: 'breadcrumbs-mobile-scrolling-enabled',
    debounceDelay: 150
  };

  extend(options, config);

  // Private variables
  var scrollTimeout = null;
  var resizeTimeout = null;

  /**
   * Set everything up
   */
  function create() {

    // Bail out if we don't have the proper element to act upon
    if (!element) {
      return;
    }

    // element.classList.add(options.enabledClass);

    // Scroll the crumbtrail all the way to the right by default
    element.scrollLeft = element.clientWidth;

    element.addEventListener('scroll', scrollListener);
    window.addEventListener('load', calc);

    window.addEventListener('resize', resizeListener);

  }

  /**
   * Main scroll event listener
   * @param  {Event} e
   */
  function scrollListener() {
    clearTimeout(scrollTimeout);

    scrollTimeout = setTimeout(function() {
      calc();
    }, options.debounceDelay);
  }

  /**
   * Window resize listener
   * Used to "stick" the crumbtrail to the right hand side
   * @param  {Event} e
   */
  function resizeListener() {
    clearTimeout(resizeTimeout);

    resizeTimeout = setTimeout(function() {
      element.scrollLeft = element.clientWidth;

      calc();
    }, options.debounceDelay);
  }

  /**
   * Main calculation handler
   * Called on scroll (debounced) and on window load
   */
  function calc() {

    // If we're too narrow to need peepage
    if(element.clientWidth >= element.scrollWidth) {
      element.classList.remove(options.leftClass);
      element.classList.remove(options.rightClass);
      element.classList.remove(options.enabledClass);

      return;
    }

    // Otherwise, enable the peepage
    element.classList.add(options.enabledClass);

    // If we're at the end
    if(element.scrollLeft === element.scrollWidth - element.offsetWidth) {
      element.classList.add(options.rightClass);
      element.classList.remove(options.leftClass);
    }

    // If we're at the start
    else if(element.scrollLeft === 0) {
      element.classList.add(options.leftClass);
      element.classList.remove(options.rightClass);

    }

    // Otherwise we're somewhere in between
    else {
      element.classList.remove(options.leftClass);
      element.classList.remove(options.rightClass);
    }
  }

  /**
   * Tear everything down again
   */
  function destroy() {
    // Unbind any queued listeners
    clearTimeout(resizeTimeout);
    clearTimeout(scrollTimeout);

    // Unbind events
    element.removeEventListener('scroll', scrollListener);
    window.removeEventListener('load', calc);
    window.removeEventListener('resize', calc);

    // Remove all classes
    element.classList.remove(options.leftClass);
    element.classList.remove(options.rightClass);
    element.classList.remove(options.enabledClass);
  }

  var self = {
    create: create,
    destroy: destroy
  };

  return self;

}

module.exports = MobileCrumbs;
<|endoftext|>


<commit_before>//>>excludeStart("exclude", pragmas.exclude);
define([ "shoestring" ], function(){
//>>excludeEnd("exclude");

	shoestring.fn.attr = function( name, val ){
		var nameStr = typeof( name ) === "string";
		if( val !== undefined || !nameStr ){
			return this.each(function(){
				if( nameStr ){
					this.setAttribute( name, val );
				}
				else {
					for( var i in name ){
						if( name.hasOwnProperty( i ) ){
							this.setAttribute( i, name[ i ] );
						}
					}
				}
			});
		}
		else {
			return this[ 0 ] ? this[ 0 ].getAttribute( name ) : undefined;
		}
	};

//>>excludeStart("exclude", pragmas.exclude);
});
//>>excludeEnd("exclude");
<commit_msg>docs for attr<commit_after>//>>excludeStart("exclude", pragmas.exclude);
define([ "shoestring" ], function(){
//>>excludeEnd("exclude");

  /**
	 * Get the value of the first element of the set or set the value of all the elements in the set.
	 *
	 * @param {string} name The attribute name.
	 * @param {string} value The new value for the attribute.
	 * @return {shoestring|string|undefined}
	 * @this {shoestring}
	 */
	shoestring.fn.attr = function( name, value ){
		var nameStr = typeof( name ) === "string";

		if( value !== undefined || !nameStr ){
			return this.each(function(){
				if( nameStr ){
					this.setAttribute( name, value );
				}	else {
					for( var i in name ){
						if( name.hasOwnProperty( i ) ){
							this.setAttribute( i, name[ i ] );
						}
					}
				}
			});
		} else {
			return this[ 0 ] ? this[ 0 ].getAttribute( name ) : undefined;
		}
	};

//>>excludeStart("exclude", pragmas.exclude);
});
//>>excludeEnd("exclude");
<|endoftext|>


<commit_before>'use strict'

//let validator = require('mc-extension-validator')
let glob = require('glob')

const EXT_PATH = process.cwd() + '/node_modules/mc-ext-*'

let registry = {

  _extensions: {},
  _stageTypes: [],
  _typesByFqids: {},

  /**
   * Resolve all `mc-ext-*` modules and register them
   *
   * @param  {string} dir Path mission control extensions
   */
  resolve: function resolve(dir) {
    let modules = glob.sync(dir)

    modules.forEach(module => {
      this.register(require(module))
    })
  },

  /**
   * Reload all extensions
   */
  reload: function reload() {

    // Reset all of our internal registry pieces
    this._extensions = {}
    this._stageTypes = []
    this._typesByFqids = {}

    // Reload the modules
    this.resolve(EXT_PATH)
  },

  /**
   * [register provided module]
   * @param  {Object} module [Module instance]
   */
  register: function register(module) {
    if (typeof this._extensions[module.vendor] !== 'object') {
      this._extensions[module.vendor] = {}
    }

    // TODO: validate extension index

    this._extensions[module.vendor][module.id] = {
      vendor: module.vendor,
      id: module.id,
      name: module.name,
      description: module.description
    }

    this.registerStages(module)
    // TODO: register log types

  },

  registerStages: function registerStages(module) {

    if (Array.isArray(module.stages)) {

      module.stages.forEach(st => {

        // TODO: validate stage type

        // Register the stage as vendor.extension_id.stages.example
        let fqid = module.vendor + '.' + module.id + '.stages.' + st.id
        this._typesByFqids[fqid] = st
        this._stageTypes.push(st)

      })
    }

  },

  /**
   * Get an item/type from the extension via the FQID (full-qualified identifier)
   *
   * @param  {string} name [dot syntax path]
   * @return {object}      [resolved extension path]
   */
  get: function get(name) {
    if (typeof this._typesByFqids[name] !== 'undefined') {
      return this._typesByFqids[name]
    } else {
      throw new Error('Extension FQID "' + name + '" not found')
    }
  },

  /**
   * Get stage types
   *
   * @return {Array}
   */
  getStageTypes: function getStageTypes() {
    return this._stageTypes
  }

}

// Initially load extensions
registry.resolve(EXT_PATH)

module.exports = registry
<commit_msg>Remove _stageTypes and simple loop over full qualified object to get a list of types<commit_after>'use strict'

//let validator = require('mc-extension-validator')
let glob = require('glob')

const EXT_PATH = process.cwd() + '/node_modules/mc-ext-*'

let registry = {

  _extensions: {},
  _typesByFqids: {},

  /**
   * Resolve all `mc-ext-*` modules and register them
   *
   * @param  {string} dir Path mission control extensions
   */
  resolve: function resolve(dir) {
    let modules = glob.sync(dir)

    modules.forEach(module => {
      this.register(require(module))
    })
  },

  /**
   * Reload all extensions
   */
  reload: function reload() {

    // Reset all of our internal registry pieces
    this._extensions = {}
    this._typesByFqids = {}

    // Reload the modules
    this.resolve(EXT_PATH)
  },

  /**
   * [register provided module]
   * @param  {Object} module [Module instance]
   */
  register: function register(module) {
    if (typeof this._extensions[module.vendor] !== 'object') {
      this._extensions[module.vendor] = {}
    }

    // TODO: validate extension index

    this._extensions[module.vendor][module.id] = {
      vendor: module.vendor,
      id: module.id,
      name: module.name,
      description: module.description
    }

    this.registerStages(module)
    // TODO: register log types

  },

  registerStages: function registerStages(module) {

    if (Array.isArray(module.stages)) {

      module.stages.forEach(st => {

        // TODO: validate stage type

        // Register the stage as vendor.extension_id.stages.example
        let fqid = module.vendor + '.' + module.id + '.stages.' + st.id
        this._typesByFqids[fqid] = st

      })
    }

  },

  /**
   * Get an item/type from the extension via the FQID (full-qualified identifier)
   *
   * @param  {string} name [dot syntax path]
   * @return {object}      [resolved extension path]
   */
  get: function get(name) {
    if (typeof this._typesByFqids[name] !== 'undefined') {
      return this._typesByFqids[name]
    } else {
      throw new Error('Extension FQID "' + name + '" not found')
    }
  },

  /**
   * Get stage types
   *
   * @return {Array}
   */
  getStageTypes: function getStageTypes() {
    let stages = []

    for (let fqid in this._typesByFqids) {
      // Shallow clone so we don't mutate the stage object
      let stage = Object.assign({}, this._typesByFqids[fqid])
        stage.fqid = fqid
        stages.push(stage)
    }

    return stages
  }

}

// Initially load extensions
registry.resolve(EXT_PATH)

module.exports = registry
<|endoftext|>


<commit_before>/*
 * Displays collections by key and by time of last update
 * Returns a list of identifier for each artifact in the collection
 */
function(doc) {
    function Synonyms(){
        this.doi = false;
        this.url = false;
        this.pmid = false;
    }
    ret = {};
    var artifactsCount =  doc.artifact_ids.length;
    for (var i = 0; i < artifactsCount; i++ ){
        var artifactId = doc.artifact_ids[i];
        mySynonyms = new Synonyms;
        try {
            var fromCrossRef = doc.sources.CrossRef.artifacts[artifactId];
            mySynonyms.doi = fromCrossRef.doi;
            mySynonyms.url = fromCrossRef.url;
            mySynonyms.pmid = fromCrossRef.pmid;
        }
        catch(e) {}

        ret[artifactId] = mySynonyms;
    }
    emit(doc._id, ret);

}<commit_msg>to_update view works<commit_after>/*
 * Displays collections by key and by time of last update
 * Returns a list of identifier for each artifact in the collection
 */
function(doc) {
    function Synonyms(){
        this.doi = false;
        this.url = false;
        this.pmid = false;
    }
    var sources = [
        "Mendeley",
        "CrossRef",
        "Plosalm",
        "Slideshare",
        "Facebook",
        "ICPSR",
        "Dryad"
    ];

    // setup the return object
    ret = {};
    var artifactsCount =  doc.artifact_ids.length;
    for (var i=0; i<artifactsCount; i++ ){
        var artifactId = doc.artifact_ids[i];
        mySynonyms = new Synonyms;
        try {
            var fromCrossRef = doc.sources.CrossRef.artifacts[artifactId];
            mySynonyms.doi = fromCrossRef.doi;
            mySynonyms.url = fromCrossRef.url;
            mySynonyms.pmid = fromCrossRef.pmid;
        }
        catch(e) {}

        ret[artifactId] = mySynonyms;
    }

    // return it only if it's missing sources

    var sourcesCount = sources.length;
    var key;
    for (var i=0; i<sourcesCount; i++) {
        key = [
            sources[i],
            doc.updates[sources[i]]
        ]

        emit(key, ret);
    }

}<|endoftext|>


<commit_before>var core = require('../core'),
    TextureUvs = require('../core/textures/TextureUvs');

/**
 * A tiling sprite is a fast way of rendering a tiling image
 *
 * @class
 * @extends Sprite
 * @namespace PIXI
 * @param texture {Texture} the texture of the tiling sprite
 * @param width {number}  the width of the tiling sprite
 * @param height {number} the height of the tiling sprite
 */
function TilingSprite(texture, width, height)
{
    core.Sprite.call( this, texture);

    /**
     * The with of the tiling sprite
     *
     * @member {number}
     */
    this._width = width || 100;

    /**
     * The height of the tiling sprite
     *
     * @member {number}
     */
    this._height = height || 100;

    /**
     * The scaling of the image that is being tiled
     *
     * @member {Point}
     */
    this.tileScale = new core.math.Point(1,1);

    /**
     * A point that represents the scale of the texture object
     *
     * @member {Point}
     */
    this.tileScaleOffset = new core.math.Point(1,1);

    /**
     * The offset position of the image that is being tiled
     *
     * @member {Point}
     */
    this.tilePosition = new core.math.Point(0,0);

    /**
     * The blend mode to be applied to the sprite
     *
     * @member {number}
     * @default blendModes.NORMAL;
     */
    this.blendMode = core.CONST.blendModes.NORMAL;

    this.tilingTexture = null;
    this._refreshTexture = false;

    this._uvs = new TextureUvs();
}

TilingSprite.prototype = Object.create(core.Sprite.prototype);
TilingSprite.prototype.constructor = TilingSprite;
module.exports = TilingSprite;

Object.defineProperties(TilingSprite.prototype, {
    /**
     * The width of the sprite, setting this will actually modify the scale to achieve the value set
     *
     * @member {number}
     * @memberof TilingSprite#
     */
    width: {
        get: function ()
        {
            return this._width;
        },
        set: function (value)
        {
            this._width = value;
        }
    },

    /**
     * The height of the TilingSprite, setting this will actually modify the scale to achieve the value set
     *
     * @member {number}
     * @memberof TilingSprite#
     */
    height: {
        get: function ()
        {
            return this._height;
        },
        set: function (value)
        {
            this._height = value;
        }
    }
});

/**
 * When the texture is updated, this event will fire,
 *
 * @private
 */
TilingSprite.prototype._onTextureUpdate = function ()
{
    core.Sprite.prototype._onTextureUpdate.call(this);

    this._refreshTexture = true;
};

/**
 * Renders the object using the WebGL renderer
 *
 * @param renderer {WebGLRenderer}
 */
TilingSprite.prototype._renderWebGL = function (renderer)
{

    if (!this.tilingTexture || this._refreshTexture)
    {
        this.generateTilingTexture(true);

        if (this.tilingTexture && this.tilingTexture.needsUpdate)
        {
            //TODO - tweaking
            renderer.updateTexture(this.tilingTexture.baseTexture);
            this.tilingTexture.needsUpdate = false;
           // this.tilingTexture._uvs = null;
        }

    }
    else
    {
        // tweak our texture temporarily..

        var texture = this.tilingTexture;

        var uvs = this._uvs;

        this.tilePosition.x %= texture.baseTexture.width * this.tileScaleOffset.x;
        this.tilePosition.y %= texture.baseTexture.height * this.tileScaleOffset.y;

        var offsetX =  this.tilePosition.x/(texture.baseTexture.width*this.tileScaleOffset.x);
        var offsetY =  this.tilePosition.y/(texture.baseTexture.height*this.tileScaleOffset.y);

        var scaleX =  (this.width / texture.baseTexture.width)  / (this.tileScale.x * this.tileScaleOffset.x);
        var scaleY =  (this.height / texture.baseTexture.height) / (this.tileScale.y * this.tileScaleOffset.y);

        uvs.x0 = 0 - offsetX;
        uvs.y0 = 0 - offsetY;

        uvs.x1 = (1 * scaleX) - offsetX;
        uvs.y1 = 0 - offsetY;

        uvs.x2 = (1 * scaleX) - offsetX;
        uvs.y2 = (1 * scaleY) - offsetY;

        uvs.x3 = 0 - offsetX;
        uvs.y3 = (1 * scaleY) - offsetY;

        var tempUvs = texture._uvs;
        var tempWidth = texture._frame.width;
        var tempHeight = texture._frame.height;

        texture._uvs = uvs;
        texture._frame.width = this.width;
        texture._frame.height = this.height;

        renderer.setObjectRenderer(renderer.plugins.sprite);
        renderer.plugins.sprite.render(this);

        texture._uvs = tempUvs;
        texture._frame.width = tempWidth;
        texture._frame.height = tempHeight;
    }

};

/**
 * Renders the object using the Canvas renderer
 *
 * @param renderer {CanvasRenderer}
 */
TilingSprite.prototype.renderCanvas = function (renderer)
{
    if (!this.visible || this.alpha <= 0)
    {
        return;
    }

    var context = renderer.context;

    if (this._mask)
    {
        renderer.maskManager.pushMask(this._mask, context);
    }

    context.globalAlpha = this.worldAlpha;

    var transform = this.worldTransform;

    var i,j;

    var resolution = renderer.resolution;

    context.setTransform(transform.a * resolution,
                         transform.b * resolution,
                         transform.c * resolution,
                         transform.d * resolution,
                         transform.tx * resolution,
                         transform.ty * resolution);

    if (!this.__tilePattern ||  this._refreshTexture)
    {
        this.generateTilingTexture(false);

        if (this.tilingTexture)
        {
            this.__tilePattern = context.createPattern(this.tilingTexture.baseTexture.source, 'repeat');
        }
        else
        {
            return;
        }
    }

    // check blend mode
    if (this.blendMode !== renderer.currentBlendMode)
    {
        renderer.currentBlendMode = this.blendMode;
        context.globalCompositeOperation = renderer.blendModes[renderer.currentBlendMode];
    }

    var tilePosition = this.tilePosition;
    var tileScale = this.tileScale;

    tilePosition.x %= this.tilingTexture.baseTexture.width;
    tilePosition.y %= this.tilingTexture.baseTexture.height;

    // offset - make sure to account for the anchor point..
    context.scale(tileScale.x,tileScale.y);
    context.translate(tilePosition.x + (this.anchor.x * -this._width), tilePosition.y + (this.anchor.y * -this._height));

    context.fillStyle = this.__tilePattern;

    context.fillRect(-tilePosition.x,
                    -tilePosition.y,
                    this._width / tileScale.x,
                    this._height / tileScale.y);

    context.translate(-tilePosition.x + (this.anchor.x * this._width), -tilePosition.y + (this.anchor.y * this._height));
    context.scale(1 / tileScale.x, 1 / tileScale.y);

    if (this._mask)
    {
        renderer.maskManager.popMask(renderer.context);
    }

    for (i = 0, j = this.children.length; i < j; ++i)
    {
        this.children[i].renderCanvas(renderer);
    }
};

/**
 * Returns the framing rectangle of the sprite as a Rectangle object
*
 * @return {Rectangle} the framing rectangle
 */
TilingSprite.prototype.getBounds = function ()
{
    var width = this._width;
    var height = this._height;

    var w0 = width * (1-this.anchor.x);
    var w1 = width * -this.anchor.x;

    var h0 = height * (1-this.anchor.y);
    var h1 = height * -this.anchor.y;

    var worldTransform = this.worldTransform;

    var a = worldTransform.a;
    var b = worldTransform.b;
    var c = worldTransform.c;
    var d = worldTransform.d;
    var tx = worldTransform.tx;
    var ty = worldTransform.ty;

    var x1 = a * w1 + c * h1 + tx;
    var y1 = d * h1 + b * w1 + ty;

    var x2 = a * w0 + c * h1 + tx;
    var y2 = d * h1 + b * w0 + ty;

    var x3 = a * w0 + c * h0 + tx;
    var y3 = d * h0 + b * w0 + ty;

    var x4 =  a * w1 + c * h0 + tx;
    var y4 =  d * h0 + b * w1 + ty;

    var minX,
        maxX,
        minY,
        maxY;

    minX = x1;
    minX = x2 < minX ? x2 : minX;
    minX = x3 < minX ? x3 : minX;
    minX = x4 < minX ? x4 : minX;

    minY = y1;
    minY = y2 < minY ? y2 : minY;
    minY = y3 < minY ? y3 : minY;
    minY = y4 < minY ? y4 : minY;

    maxX = x1;
    maxX = x2 > maxX ? x2 : maxX;
    maxX = x3 > maxX ? x3 : maxX;
    maxX = x4 > maxX ? x4 : maxX;

    maxY = y1;
    maxY = y2 > maxY ? y2 : maxY;
    maxY = y3 > maxY ? y3 : maxY;
    maxY = y4 > maxY ? y4 : maxY;

    var bounds = this._bounds;

    bounds.x = minX;
    bounds.width = maxX - minX;

    bounds.y = minY;
    bounds.height = maxY - minY;

    // store a reference so that if this function gets called again in the render cycle we do not have to recalculate
    this._currentBounds = bounds;

    return bounds;
};

/**
 * When the texture is updated, this event will fire to update the scale and frame
 *
 * @param event
 * @private
 */
TilingSprite.prototype.onTextureUpdate = function ()
{
   // overriding the sprite version of this!
};

/**
 *
 * @param forcePowerOfTwo {boolean} Whether we want to force the texture to be a power of two
 */
TilingSprite.prototype.generateTilingTexture = function (forcePowerOfTwo)
{
    if (!this.texture.baseTexture.hasLoaded)
    {
        return;
    }

    var texture = this.originalTexture || this.texture;
    var frame = texture.frame;
    var targetWidth, targetHeight;

    //  Check that the frame is the same size as the base texture.
    var isFrame = frame.width !== texture.baseTexture.width || frame.height !== texture.baseTexture.height;

    var newTextureRequired = false;

    if (!forcePowerOfTwo)
    {
        if (isFrame)
        {
            targetWidth = frame.width;
            targetHeight = frame.height;

            newTextureRequired = true;
        }
    }
    else
    {
        targetWidth = core.utils.getNextPowerOfTwo(frame.width);
        targetHeight = core.utils.getNextPowerOfTwo(frame.height);

        //  If the BaseTexture dimensions don't match the texture frame then we need a new texture anyway because it's part of a texture atlas
        if (frame.width !== targetWidth || frame.height !== targetHeight || texture.baseTexture.width !== targetWidth || texture.baseTexture.height || targetHeight)
        {
            newTextureRequired = true;
        }
    }

    if (newTextureRequired)
    {
        var canvasBuffer;

        if (this.tilingTexture && this.tilingTexture.isTiling)
        {
            canvasBuffer = this.tilingTexture.canvasBuffer;
            canvasBuffer.resize(targetWidth, targetHeight);
            this.tilingTexture.baseTexture.width = targetWidth;
            this.tilingTexture.baseTexture.height = targetHeight;
            this.tilingTexture.needsUpdate = true;
        }
        else
        {
            canvasBuffer = new core.CanvasBuffer(targetWidth, targetHeight);

            this.tilingTexture = core.Texture.fromCanvas(canvasBuffer.canvas);
            this.tilingTexture.canvasBuffer = canvasBuffer;
            this.tilingTexture.isTiling = true;
        }

        canvasBuffer.context.drawImage(texture.baseTexture.source,
                               texture.crop.x,
                               texture.crop.y,
                               texture.crop.width,
                               texture.crop.height,
                               0,
                               0,
                               targetWidth,
                               targetHeight);

        this.tileScaleOffset.x = frame.width / targetWidth;
        this.tileScaleOffset.y = frame.height / targetHeight;
    }
    else
    {
        //  TODO - switching?
        if (this.tilingTexture && this.tilingTexture.isTiling)
        {
            // destroy the tiling texture!
            // TODO could store this somewhere?
            this.tilingTexture.destroy(true);
        }

        this.tileScaleOffset.x = 1;
        this.tileScaleOffset.y = 1;
        this.tilingTexture = texture;
    }

    this._refreshTexture = false;

    this.originalTexture = this.texture;
    this.texture = this.tilingTexture;

    this.tilingTexture.baseTexture._powerOf2 = true;
};

TilingSprite.prototype.destroy = function () {
    core.Sprite.prototype.destroy.call(this);

    this.tileScale = null;
    this.tileScaleOffset = null;
    this.tilePosition = null;

    this.tilingTexture.destroy(true);
    this.tilingTexture = null;

    this._uvs = null;
};
<commit_msg>maskManager expects renderer not context<commit_after>var core = require('../core'),
    TextureUvs = require('../core/textures/TextureUvs');

/**
 * A tiling sprite is a fast way of rendering a tiling image
 *
 * @class
 * @extends Sprite
 * @namespace PIXI
 * @param texture {Texture} the texture of the tiling sprite
 * @param width {number}  the width of the tiling sprite
 * @param height {number} the height of the tiling sprite
 */
function TilingSprite(texture, width, height)
{
    core.Sprite.call( this, texture);

    /**
     * The with of the tiling sprite
     *
     * @member {number}
     */
    this._width = width || 100;

    /**
     * The height of the tiling sprite
     *
     * @member {number}
     */
    this._height = height || 100;

    /**
     * The scaling of the image that is being tiled
     *
     * @member {Point}
     */
    this.tileScale = new core.math.Point(1,1);

    /**
     * A point that represents the scale of the texture object
     *
     * @member {Point}
     */
    this.tileScaleOffset = new core.math.Point(1,1);

    /**
     * The offset position of the image that is being tiled
     *
     * @member {Point}
     */
    this.tilePosition = new core.math.Point(0,0);

    /**
     * The blend mode to be applied to the sprite
     *
     * @member {number}
     * @default blendModes.NORMAL;
     */
    this.blendMode = core.CONST.blendModes.NORMAL;

    this.tilingTexture = null;
    this._refreshTexture = false;

    this._uvs = new TextureUvs();
}

TilingSprite.prototype = Object.create(core.Sprite.prototype);
TilingSprite.prototype.constructor = TilingSprite;
module.exports = TilingSprite;

Object.defineProperties(TilingSprite.prototype, {
    /**
     * The width of the sprite, setting this will actually modify the scale to achieve the value set
     *
     * @member {number}
     * @memberof TilingSprite#
     */
    width: {
        get: function ()
        {
            return this._width;
        },
        set: function (value)
        {
            this._width = value;
        }
    },

    /**
     * The height of the TilingSprite, setting this will actually modify the scale to achieve the value set
     *
     * @member {number}
     * @memberof TilingSprite#
     */
    height: {
        get: function ()
        {
            return this._height;
        },
        set: function (value)
        {
            this._height = value;
        }
    }
});

/**
 * When the texture is updated, this event will fire,
 *
 * @private
 */
TilingSprite.prototype._onTextureUpdate = function ()
{
    core.Sprite.prototype._onTextureUpdate.call(this);

    this._refreshTexture = true;
};

/**
 * Renders the object using the WebGL renderer
 *
 * @param renderer {WebGLRenderer}
 */
TilingSprite.prototype._renderWebGL = function (renderer)
{

    if (!this.tilingTexture || this._refreshTexture)
    {
        this.generateTilingTexture(true);

        if (this.tilingTexture && this.tilingTexture.needsUpdate)
        {
            //TODO - tweaking
            renderer.updateTexture(this.tilingTexture.baseTexture);
            this.tilingTexture.needsUpdate = false;
           // this.tilingTexture._uvs = null;
        }

    }
    else
    {
        // tweak our texture temporarily..

        var texture = this.tilingTexture;

        var uvs = this._uvs;

        this.tilePosition.x %= texture.baseTexture.width * this.tileScaleOffset.x;
        this.tilePosition.y %= texture.baseTexture.height * this.tileScaleOffset.y;

        var offsetX =  this.tilePosition.x/(texture.baseTexture.width*this.tileScaleOffset.x);
        var offsetY =  this.tilePosition.y/(texture.baseTexture.height*this.tileScaleOffset.y);

        var scaleX =  (this.width / texture.baseTexture.width)  / (this.tileScale.x * this.tileScaleOffset.x);
        var scaleY =  (this.height / texture.baseTexture.height) / (this.tileScale.y * this.tileScaleOffset.y);

        uvs.x0 = 0 - offsetX;
        uvs.y0 = 0 - offsetY;

        uvs.x1 = (1 * scaleX) - offsetX;
        uvs.y1 = 0 - offsetY;

        uvs.x2 = (1 * scaleX) - offsetX;
        uvs.y2 = (1 * scaleY) - offsetY;

        uvs.x3 = 0 - offsetX;
        uvs.y3 = (1 * scaleY) - offsetY;

        var tempUvs = texture._uvs;
        var tempWidth = texture._frame.width;
        var tempHeight = texture._frame.height;

        texture._uvs = uvs;
        texture._frame.width = this.width;
        texture._frame.height = this.height;

        renderer.setObjectRenderer(renderer.plugins.sprite);
        renderer.plugins.sprite.render(this);

        texture._uvs = tempUvs;
        texture._frame.width = tempWidth;
        texture._frame.height = tempHeight;
    }

};

/**
 * Renders the object using the Canvas renderer
 *
 * @param renderer {CanvasRenderer}
 */
TilingSprite.prototype.renderCanvas = function (renderer)
{
    if (!this.visible || this.alpha <= 0)
    {
        return;
    }

    var context = renderer.context;

    if (this._mask)
    {
        renderer.maskManager.pushMask(this._mask, renderer);
    }

    context.globalAlpha = this.worldAlpha;

    var transform = this.worldTransform;

    var i,j;

    var resolution = renderer.resolution;

    context.setTransform(transform.a * resolution,
                         transform.b * resolution,
                         transform.c * resolution,
                         transform.d * resolution,
                         transform.tx * resolution,
                         transform.ty * resolution);

    if (!this.__tilePattern ||  this._refreshTexture)
    {
        this.generateTilingTexture(false);

        if (this.tilingTexture)
        {
            this.__tilePattern = context.createPattern(this.tilingTexture.baseTexture.source, 'repeat');
        }
        else
        {
            return;
        }
    }

    // check blend mode
    if (this.blendMode !== renderer.currentBlendMode)
    {
        renderer.currentBlendMode = this.blendMode;
        context.globalCompositeOperation = renderer.blendModes[renderer.currentBlendMode];
    }

    var tilePosition = this.tilePosition;
    var tileScale = this.tileScale;

    tilePosition.x %= this.tilingTexture.baseTexture.width;
    tilePosition.y %= this.tilingTexture.baseTexture.height;

    // offset - make sure to account for the anchor point..
    context.scale(tileScale.x,tileScale.y);
    context.translate(tilePosition.x + (this.anchor.x * -this._width), tilePosition.y + (this.anchor.y * -this._height));

    context.fillStyle = this.__tilePattern;

    context.fillRect(-tilePosition.x,
                    -tilePosition.y,
                    this._width / tileScale.x,
                    this._height / tileScale.y);

    context.translate(-tilePosition.x + (this.anchor.x * this._width), -tilePosition.y + (this.anchor.y * this._height));
    context.scale(1 / tileScale.x, 1 / tileScale.y);

    if (this._mask)
    {
        renderer.maskManager.popMask(renderer);
    }

    for (i = 0, j = this.children.length; i < j; ++i)
    {
        this.children[i].renderCanvas(renderer);
    }
};

/**
 * Returns the framing rectangle of the sprite as a Rectangle object
*
 * @return {Rectangle} the framing rectangle
 */
TilingSprite.prototype.getBounds = function ()
{
    var width = this._width;
    var height = this._height;

    var w0 = width * (1-this.anchor.x);
    var w1 = width * -this.anchor.x;

    var h0 = height * (1-this.anchor.y);
    var h1 = height * -this.anchor.y;

    var worldTransform = this.worldTransform;

    var a = worldTransform.a;
    var b = worldTransform.b;
    var c = worldTransform.c;
    var d = worldTransform.d;
    var tx = worldTransform.tx;
    var ty = worldTransform.ty;

    var x1 = a * w1 + c * h1 + tx;
    var y1 = d * h1 + b * w1 + ty;

    var x2 = a * w0 + c * h1 + tx;
    var y2 = d * h1 + b * w0 + ty;

    var x3 = a * w0 + c * h0 + tx;
    var y3 = d * h0 + b * w0 + ty;

    var x4 =  a * w1 + c * h0 + tx;
    var y4 =  d * h0 + b * w1 + ty;

    var minX,
        maxX,
        minY,
        maxY;

    minX = x1;
    minX = x2 < minX ? x2 : minX;
    minX = x3 < minX ? x3 : minX;
    minX = x4 < minX ? x4 : minX;

    minY = y1;
    minY = y2 < minY ? y2 : minY;
    minY = y3 < minY ? y3 : minY;
    minY = y4 < minY ? y4 : minY;

    maxX = x1;
    maxX = x2 > maxX ? x2 : maxX;
    maxX = x3 > maxX ? x3 : maxX;
    maxX = x4 > maxX ? x4 : maxX;

    maxY = y1;
    maxY = y2 > maxY ? y2 : maxY;
    maxY = y3 > maxY ? y3 : maxY;
    maxY = y4 > maxY ? y4 : maxY;

    var bounds = this._bounds;

    bounds.x = minX;
    bounds.width = maxX - minX;

    bounds.y = minY;
    bounds.height = maxY - minY;

    // store a reference so that if this function gets called again in the render cycle we do not have to recalculate
    this._currentBounds = bounds;

    return bounds;
};

/**
 * When the texture is updated, this event will fire to update the scale and frame
 *
 * @param event
 * @private
 */
TilingSprite.prototype.onTextureUpdate = function ()
{
   // overriding the sprite version of this!
};

/**
 *
 * @param forcePowerOfTwo {boolean} Whether we want to force the texture to be a power of two
 */
TilingSprite.prototype.generateTilingTexture = function (forcePowerOfTwo)
{
    if (!this.texture.baseTexture.hasLoaded)
    {
        return;
    }

    var texture = this.originalTexture || this.texture;
    var frame = texture.frame;
    var targetWidth, targetHeight;

    //  Check that the frame is the same size as the base texture.
    var isFrame = frame.width !== texture.baseTexture.width || frame.height !== texture.baseTexture.height;

    var newTextureRequired = false;

    if (!forcePowerOfTwo)
    {
        if (isFrame)
        {
            targetWidth = frame.width;
            targetHeight = frame.height;

            newTextureRequired = true;
        }
    }
    else
    {
        targetWidth = core.utils.getNextPowerOfTwo(frame.width);
        targetHeight = core.utils.getNextPowerOfTwo(frame.height);

        //  If the BaseTexture dimensions don't match the texture frame then we need a new texture anyway because it's part of a texture atlas
        if (frame.width !== targetWidth || frame.height !== targetHeight || texture.baseTexture.width !== targetWidth || texture.baseTexture.height || targetHeight)
        {
            newTextureRequired = true;
        }
    }

    if (newTextureRequired)
    {
        var canvasBuffer;

        if (this.tilingTexture && this.tilingTexture.isTiling)
        {
            canvasBuffer = this.tilingTexture.canvasBuffer;
            canvasBuffer.resize(targetWidth, targetHeight);
            this.tilingTexture.baseTexture.width = targetWidth;
            this.tilingTexture.baseTexture.height = targetHeight;
            this.tilingTexture.needsUpdate = true;
        }
        else
        {
            canvasBuffer = new core.CanvasBuffer(targetWidth, targetHeight);

            this.tilingTexture = core.Texture.fromCanvas(canvasBuffer.canvas);
            this.tilingTexture.canvasBuffer = canvasBuffer;
            this.tilingTexture.isTiling = true;
        }

        canvasBuffer.context.drawImage(texture.baseTexture.source,
                               texture.crop.x,
                               texture.crop.y,
                               texture.crop.width,
                               texture.crop.height,
                               0,
                               0,
                               targetWidth,
                               targetHeight);

        this.tileScaleOffset.x = frame.width / targetWidth;
        this.tileScaleOffset.y = frame.height / targetHeight;
    }
    else
    {
        //  TODO - switching?
        if (this.tilingTexture && this.tilingTexture.isTiling)
        {
            // destroy the tiling texture!
            // TODO could store this somewhere?
            this.tilingTexture.destroy(true);
        }

        this.tileScaleOffset.x = 1;
        this.tileScaleOffset.y = 1;
        this.tilingTexture = texture;
    }

    this._refreshTexture = false;

    this.originalTexture = this.texture;
    this.texture = this.tilingTexture;

    this.tilingTexture.baseTexture._powerOf2 = true;
};

TilingSprite.prototype.destroy = function () {
    core.Sprite.prototype.destroy.call(this);

    this.tileScale = null;
    this.tileScaleOffset = null;
    this.tilePosition = null;

    this.tilingTexture.destroy(true);
    this.tilingTexture = null;

    this._uvs = null;
};
<|endoftext|>


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

foam.CLASS({
  package: 'foam.u2',
  name: 'ModalHeader',
  extends: 'foam.u2.View',

  documentation: 'Modal Container close/title use in modal class to append title & close buttons.',

  imports: [
    'stack',
    'closeDialog'
  ],

  properties: [
    'title'
  ],

  css: `
    ^ {
      height: 40.8px;
      width: 448px;
      background-color: /*%PRIMARY1%*/ #202341;
      border-radius: 2px 2px 0 0;
      margin: auto;
    }
    ^ .title{
      height: 40px;
      font-family: Roboto;
      font-size: 14px;
      line-height: 2.86;
      text-align: left;
      color: #ffffff;
      margin-left: 25px;
      display: inline-block;
    }
    ^ .close{
      background: 0;
      width: 24px;
      height: 24px;
      margin-top: 5px;
      cursor: pointer;
      position: relative;
      top: -3px;
      right: 20px;
      float: right;
    }
    ^ .foam-u2-ActionView-closeModal{
      position: relative;
      right: 0px;
      width: 50px;
      height: 40px;
      background: transparent;
      margin-top: 0;
      top: 0;
      right: 0;
      border: none;
    }
  `,

  methods: [
    function initE() {
    this.SUPER();

    this
      .addClass(this.myClass())
      .start().addClass('title').add(this.title).end()
      .start(this.CLOSE_MODAL).addClass('close').end();
    }
  ],

  actions: [
    {
      name: 'closeModal',
      icon: 'images/ic-cancelwhite.svg',
      label: '',
      code: function(X) {
        X.closeDialog();
      }
    }
  ]
});
<commit_msg>removed a border of close<commit_after>/**
 * @license
 * Copyright 2018 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.u2',
  name: 'ModalHeader',
  extends: 'foam.u2.View',

  documentation: 'Modal Container close/title use in modal class to append title & close buttons.',

  imports: [
    'stack',
    'closeDialog'
  ],

  properties: [
    'title'
  ],

  css: `
    ^ {
      height: 40.8px;
      width: 448px;
      background-color: /*%PRIMARY1%*/ #202341;
      border-radius: 2px 2px 0 0;
      margin: auto;
    }
    ^ .title{
      height: 40px;
      font-family: Roboto;
      font-size: 14px;
      line-height: 2.86;
      text-align: left;
      color: #ffffff;
      margin-left: 25px;
      display: inline-block;
    }
    ^ .close{
      background: 0;
      width: 24px;
      height: 24px;
      margin-top: 5px;
      cursor: pointer;
      position: relative;
      top: -3px;
      right: 20px;
      float: right;
      border: 0;
    }
    ^ .foam-u2-ActionView-closeModal{
      position: relative;
      right: 0px;
      width: 50px;
      height: 40px;
      background: transparent;
      margin-top: 0;
      top: 0;
      right: 0;
      border: none;
    }
  `,

  methods: [
    function initE() {
    this.SUPER();

    this
      .addClass(this.myClass())
      .start().addClass('title').add(this.title).end()
      .start(this.CLOSE_MODAL).addClass('close').end();
    }
  ],

  actions: [
    {
      name: 'closeModal',
      icon: 'images/ic-cancelwhite.svg',
      label: '',
      code: function(X) {
        X.closeDialog();
      }
    }
  ]
});
<|endoftext|>


<commit_before>var sensorData = (function () {
    var maxNumOfElements = 1000;
    var plot;
    var data = []; // private
    var pub = {}; // public object - returned at end of module

    pub.addData = function(value) {
        if (data.length > maxNumOfElements) {
            data.shift();
        }
        data.push(value);
    };

    pub.clearData = function() {
        data = [];
    };

    pub.plotData = function() {
        if (! plot) {
            plot = $.plot("#placeholder", [], {
                xaxis: {
                    show: false,
                    min: 0,
                    max: maxNumOfElements
                }
            });
        }
        var points = [];
		for (var i = 0; i < data.length; ++i) {
			points.push([i, data[i]]);
		}
        plot.setData([points]);
        plot.draw();
    };

    return pub; // expose externally
}());

function updateGraph() {
    $.get('./sensors/dummy', function(data, status) {
        data = JSON.parse(data);
        sensorData.addData(data.parameter)});
    sensorData.plotData();
    }

$( document ).ready(function() {
    setInterval(updateGraph, 100);
});
<commit_msg>Get intervalls right<commit_after>"use strict";

var updateInterval = 100;

var sensorData = (function () {
    var maxNumOfElements = 1000;
    var plot;
    var data = []; // private
    var pub = {}; // public object - returned at end of module

    pub.addData = function(value) {
        if (data.length > maxNumOfElements) {
            data.shift();
        }
        data.push(value);
    };

    pub.clearData = function() {
        data = [];
    };

    pub.initPlot = function (min, max) {
        plot = $.plot("#placeholder", [[0, 0]], {
            yaxis: {
                min: min,
                max: max
            },
            xaxis: {
                show: false,
                min: 0,
                max: maxNumOfElements
            }
        });
    };

    pub.plotData = function() {
        if (! plot) {

        }
        var points = [];
		for (var i = 0; i < data.length; ++i) {
			points.push([i, data[i]]);
		}
        plot.setData([points]);
        plot.draw();
    };

    return pub; // expose externally
}());

function readSensor() {
    $.getJSON('./sensors/dummy', function(data, status) {
    sensorData.addData(data.parameter)});
}

function updateGraph() {
    readSensor();
    sensorData.plotData();
    }

$( document ).ready(function() {
    $.when( $.getJSON('./sensors/dummy') ).done(function(data, status) {
        sensorData.initPlot(data.minimum, data.maximum);
        setInterval(updateGraph, updateInterval);
    });
});
<|endoftext|>


<commit_before>import BinarySocket   from '../../_common/base/socket_base';
import {
    cloneObject,
    getPropertyValue,
    isDeepEqual,
    isEmptyObject }   from '../../_common/utility';

/**
 * A layer over BinarySocket to handle subscribing to streaming calls
 * in order to keep track of subscriptions, manage forget, prevent multiple subscription at the same time, ...
 *
 * structure of the the subscription object is:
 * {
 *     1: { msg_type: 'proposal', request: { ... }, stream_id: '...', subscribers: [ ... ] },
 *     2: ...
 * }
 * object keys: subscription_id that assigned to each subscription
 * msg_type   : msg_type of the request for faster filtering
 * request    : the request object, used to subscribe to the same stream when there is a new subscribe request with exactly the same values
 * stream_id  : id of the stream which stored from its response and used to forget the stream when needed
 * subscribers: an array of callbacks to dispatch the response to
 */
const SubscriptionManager = (() => {
    const subscriptions    = {};
    const forget_requested = {};

    let subscription_id = 0;

    /**
     * To submit request for a new subscription
     *
     * @param {String}   msg_type             msg_type of the request
     * @param {Object}   request_obj          the whole object of the request to be made
     * @param {Function} fncCallback          callback function to pass the responses to
     * @param {Boolean}  should_forget_first  when it's true: forgets the previous subscription, then subscribes after receiving the forget response (if any)
     */
    const subscribe = (msg_type, request_obj, fncCallback, should_forget_first = false) => {
        if (should_forget_first) {
            forget(msg_type, fncCallback).then(() => {
                subscribe(msg_type, request_obj, fncCallback);
            });
            return;
        }

        let sub_id = Object.keys(subscriptions).find(id => isDeepEqual(request_obj, subscriptions[id].request));

        if (!sub_id) {
            sub_id = ++subscription_id;

            subscriptions[sub_id] = {
                msg_type,
                request    : cloneObject(request_obj),
                stream_id  : '',             // stream_id will be updated after receiving the response
                subscribers: [fncCallback],
            };

            BinarySocket.send(request_obj, {
                callback: ((id) => (response) => { dispatch(response, id); })(sub_id),
            });
        } else if (!hasCallbackFunction(sub_id, fncCallback)) {
            // there is already an active subscription for the very same request which fncCallback is not subscribed to it yet
            subscriptions[sub_id].subscribers.push(fncCallback);
        }
    };

    // dispatches the response to subscribers of the specific subscription id (internal use only)
    const dispatch = (response, sub_id) => {
        const stream_id = getPropertyValue(response, [response.msg_type, 'id']);

        if (!subscriptions[sub_id]) {
            if (!forget_requested[stream_id]) {
                forgetStream(stream_id);
            }
            return;
        }

        const sub_info = subscriptions[sub_id];
        // set the stream_id
        if (!sub_info.stream_id && stream_id) {
            sub_info.stream_id = stream_id;
        }

        // callback subscribers
        const subscribers = sub_info.subscribers;
        if (subscribers.length) {
            if (response.error && !sub_info.stream_id) { // first response returned error
                delete subscriptions[sub_id];
            }
            sub_info.subscribers.forEach((fnc) => {
                fnc(response);
            });
        } else {
            delete subscriptions[sub_id];
            forgetStream(sub_info.stream_id);
        }
    };

    /**
     * To forget a subscription which submitted for a specific callback function
     *
     * @param  {String}   msg_type      msg_type to forget
     * @param  {Function} fncCallback   the same function passed to subscribe()
     *     (this is the way to distinguish between different subscribers of the same stream at the same time)
     * @param  {Object}   match_values  optional, to only forget subscriptions having request that "contains" provided values
     * @return {Promise}  the promise object of all possible forget requests
     */
    const forget = (msg_type, fncCallback, match_values) => {
        if (typeof fncCallback !== 'function') {
            throw new Error(`Missing callback function. To forget all subscriptions of msg_type: ${msg_type}, please call forgetAll().`);
        }

        // find corresponding id(s)
        const sub_ids = Object.keys(subscriptions).filter(id => (
            subscriptions[id].msg_type === msg_type &&
            hasCallbackFunction(id, fncCallback)
        ));

        const forgets_list = [];
        sub_ids.forEach((id) => {
            if (match_values && !hasValues(subscriptions[id].request, match_values)) {
                return;
            }
            const stream_id = subscriptions[id].stream_id;
            if (stream_id && subscriptions[id].subscribers.length === 1) {
                delete subscriptions[id];
                forgets_list.push(forgetStream(stream_id));
            } else {
                // there are other subscribers, or for some reason there is no stream_id:
                // (i.e. returned an error, or forget() being called before the first response)
                subscriptions[id].subscribers.splice(subscriptions[id].subscribers.indexOf(fncCallback), 1);
            }
        });
        return Promise.all(forgets_list);
    };

    /**
     * To forget all active subscriptions of a list of msg_types
     *
     * @param  {String}  msg_types  list of msg_types to forget
     * @return {Promise} the promise object of all possible forget_all requests
     */
    const forgetAll = (...msg_types) => {
        const types_to_forget = {};

        msg_types.forEach((msg_type) => {
            const sub_ids = Object.keys(subscriptions).filter(id => subscriptions[id].msg_type === msg_type);
            if (sub_ids.length) {
                sub_ids.forEach((id) => {
                    delete subscriptions[id];
                });
                types_to_forget[msg_type] = true;
            }
        });

        return Promise.resolve(
            !isEmptyObject(types_to_forget) ?
                BinarySocket.send({ forget_all: Object.keys(types_to_forget) }) :
                {}
        );
    };

    const forgetStream = (stream_id) => {
        forget_requested[stream_id] = true; // to prevent forgetting multiple times
        return Promise.resolve(
            stream_id ?
                BinarySocket.send({ forget: stream_id }).then(() => { delete forget_requested[stream_id]; }) :
                {}
        );
    };

    const hasCallbackFunction = (sub_id, fncCallback) =>
        (subscriptions[sub_id] && subscriptions[sub_id].subscribers.indexOf(fncCallback) !== -1);

    const hasValues = (request_obj, values_obj) => (
        typeof request_obj === 'object' &&
        typeof values_obj  === 'object' &&
        Object.keys(values_obj).every(key => request_obj[key] === values_obj[key])
    );

    return {
        subscribe,
        forget,
        forgetAll,
    };
})();

export default SubscriptionManager;
<commit_msg>refactor line<commit_after>import BinarySocket   from '../../_common/base/socket_base';
import {
    cloneObject,
    getPropertyValue,
    isDeepEqual,
    isEmptyObject }   from '../../_common/utility';

/**
 * A layer over BinarySocket to handle subscribing to streaming calls
 * in order to keep track of subscriptions, manage forget, prevent multiple subscription at the same time, ...
 *
 * structure of the the subscription object is:
 * {
 *     1: { msg_type: 'proposal', request: { ... }, stream_id: '...', subscribers: [ ... ] },
 *     2: ...
 * }
 * object keys: subscription_id that assigned to each subscription
 * msg_type   : msg_type of the request for faster filtering
 * request    : the request object, used to subscribe to the same stream when there is a new subscribe request with exactly the same values
 * stream_id  : id of the stream which stored from its response and used to forget the stream when needed
 * subscribers: an array of callbacks to dispatch the response to
 */
const SubscriptionManager = (() => {
    const subscriptions    = {};
    const forget_requested = {};

    let subscription_id = 0;

    /**
     * To submit request for a new subscription
     *
     * @param {String}   msg_type             msg_type of the request
     * @param {Object}   request_obj          the whole object of the request to be made
     * @param {Function} fncCallback          callback function to pass the responses to
     * @param {Boolean}  should_forget_first  when it's true: forgets the previous subscription, then subscribes after receiving the forget response (if any)
     */
    const subscribe = (msg_type, request_obj, fncCallback, should_forget_first = false) => {
        if (should_forget_first) {
            forget(msg_type, fncCallback).then(() => {
                subscribe(msg_type, request_obj, fncCallback);
            });
            return;
        }

        let sub_id = Object.keys(subscriptions).find(id => isDeepEqual(request_obj, subscriptions[id].request));

        if (!sub_id) {
            sub_id = ++subscription_id;

            subscriptions[sub_id] = {
                msg_type,
                request    : cloneObject(request_obj),
                stream_id  : '',             // stream_id will be updated after receiving the response
                subscribers: [fncCallback],
            };

            BinarySocket.send(request_obj, {
                callback: (response) => dispatch(response, sub_id),
            });
        } else if (!hasCallbackFunction(sub_id, fncCallback)) {
            // there is already an active subscription for the very same request which fncCallback is not subscribed to it yet
            subscriptions[sub_id].subscribers.push(fncCallback);
        }
    };

    // dispatches the response to subscribers of the specific subscription id (internal use only)
    const dispatch = (response, sub_id) => {
        const stream_id = getPropertyValue(response, [response.msg_type, 'id']);

        if (!subscriptions[sub_id]) {
            if (!forget_requested[stream_id]) {
                forgetStream(stream_id);
            }
            return;
        }

        const sub_info = subscriptions[sub_id];
        // set the stream_id
        if (!sub_info.stream_id && stream_id) {
            sub_info.stream_id = stream_id;
        }

        // callback subscribers
        const subscribers = sub_info.subscribers;
        if (subscribers.length) {
            if (response.error && !sub_info.stream_id) { // first response returned error
                delete subscriptions[sub_id];
            }
            sub_info.subscribers.forEach((fnc) => {
                fnc(response);
            });
        } else {
            delete subscriptions[sub_id];
            forgetStream(sub_info.stream_id);
        }
    };

    /**
     * To forget a subscription which submitted for a specific callback function
     *
     * @param  {String}   msg_type      msg_type to forget
     * @param  {Function} fncCallback   the same function passed to subscribe()
     *     (this is the way to distinguish between different subscribers of the same stream at the same time)
     * @param  {Object}   match_values  optional, to only forget subscriptions having request that "contains" provided values
     * @return {Promise}  the promise object of all possible forget requests
     */
    const forget = (msg_type, fncCallback, match_values) => {
        if (typeof fncCallback !== 'function') {
            throw new Error(`Missing callback function. To forget all subscriptions of msg_type: ${msg_type}, please call forgetAll().`);
        }

        // find corresponding id(s)
        const sub_ids = Object.keys(subscriptions).filter(id => (
            subscriptions[id].msg_type === msg_type &&
            hasCallbackFunction(id, fncCallback)
        ));

        const forgets_list = [];
        sub_ids.forEach((id) => {
            if (match_values && !hasValues(subscriptions[id].request, match_values)) {
                return;
            }
            const stream_id = subscriptions[id].stream_id;
            if (stream_id && subscriptions[id].subscribers.length === 1) {
                delete subscriptions[id];
                forgets_list.push(forgetStream(stream_id));
            } else {
                // there are other subscribers, or for some reason there is no stream_id:
                // (i.e. returned an error, or forget() being called before the first response)
                subscriptions[id].subscribers.splice(subscriptions[id].subscribers.indexOf(fncCallback), 1);
            }
        });
        return Promise.all(forgets_list);
    };

    /**
     * To forget all active subscriptions of a list of msg_types
     *
     * @param  {String}  msg_types  list of msg_types to forget
     * @return {Promise} the promise object of all possible forget_all requests
     */
    const forgetAll = (...msg_types) => {
        const types_to_forget = {};

        msg_types.forEach((msg_type) => {
            const sub_ids = Object.keys(subscriptions).filter(id => subscriptions[id].msg_type === msg_type);
            if (sub_ids.length) {
                sub_ids.forEach((id) => {
                    delete subscriptions[id];
                });
                types_to_forget[msg_type] = true;
            }
        });

        return Promise.resolve(
            !isEmptyObject(types_to_forget) ?
                BinarySocket.send({ forget_all: Object.keys(types_to_forget) }) :
                {}
        );
    };

    const forgetStream = (stream_id) => {
        forget_requested[stream_id] = true; // to prevent forgetting multiple times
        return Promise.resolve(
            stream_id ?
                BinarySocket.send({ forget: stream_id }).then(() => { delete forget_requested[stream_id]; }) :
                {}
        );
    };

    const hasCallbackFunction = (sub_id, fncCallback) =>
        (subscriptions[sub_id] && subscriptions[sub_id].subscribers.indexOf(fncCallback) !== -1);

    const hasValues = (request_obj, values_obj) => (
        typeof request_obj === 'object' &&
        typeof values_obj  === 'object' &&
        Object.keys(values_obj).every(key => request_obj[key] === values_obj[key])
    );

    return {
        subscribe,
        forget,
        forgetAll,
    };
})();

export default SubscriptionManager;
<|endoftext|>


<commit_before>'use strict';

angular.module('app')
    .controller('rgiNewRefDialogCtrl', function (
        $q,
        $scope,
        $rootScope,
        $route,
        $timeout,
        $http,
        ngDialog,
        rgiAllowedFileExtensionGuideSrvc,
        rgiDialogFactory,
        rgiNotifier,
        FileUploader,
        rgiUtilsSrvc,
        rgiFileUploaderSrvc,
        rgiRequestSubmitterSrvc,
        rgiAnswerMethodSrvc,
        rgiAssessmentSrvc,
        rgiIntervieweeSrvc,
        rgiIntervieweeMethodSrvc,
        rgiIdentitySrvc
    ) {
        /////////////
        //INTERVIEWEE
        /////////////
        $scope.current_user = rgiIdentitySrvc.currentUser;
        $scope.editorContentMaxLength = $scope.$root.editorContentMaxLength;
        $scope.taToolbarOptions = $scope.$root.taToolbarOptions;

        $scope.role_opts = [
            {text: 'Government', value: 'government'},
            {text: 'CSO', value: 'cso'},
            {text: 'Industry', value: 'industry'},
            {text: 'Expert', value: 'expert'},
            {text: 'Other', value: 'other'}];
        $scope.salutation_opts = ['mr.', 'mrs.', 'ms.'];
        //Datepicker opts
        var today = new Date();
        $scope.date_default = today;
        $scope.date_max_limit = today;
        $scope.date_options = {
            formatYear: 'yy',
            startingDay: 1
        };
        $scope.date_formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate'];
        $scope.date_format = $scope.date_formats[0];
        $scope.status = {
            opened: false
        };
        $scope.calendarOpen = function () {
            $scope.status.opened = true;
        };
        $scope.maxDate = today;

        $scope.answer_update = $scope.$parent.answer;
        $scope.interviewee_list = [];
        //rgiIntervieweeSrvc.get({assessment_ID: 'DZ-2015-PI'}, function (interviewees) {
        rgiIntervieweeSrvc.query({}, function (interviewees) {
            interviewees.forEach(function (interviewee) {
                var interviewee_add = {
                    firstName: interviewee.firstName,
                    lastName: interviewee.lastName,
                    id: interviewee._id,
                    assessments: interviewee.assessments,
                    email: interviewee.email,
                    assessment_countries: []
                };
                interviewee.assessments.forEach(function (assessment_ID) {
                    rgiAssessmentSrvc.get({assessment_ID: assessment_ID}, function (assessment) {
                        interviewee_add.assessment_countries.push(assessment.country);
                    });
                });
                $scope.interviewee_list.push(interviewee_add);
            });
        });

        $scope.intervieweeSelect = function (selection) {
            $scope.interviewee_selection = selection;
        };

        $scope.interviewRefSubmit = function (selected_interviewee) {
            var contact_date, email_domain, new_ref_data, selected_interviewee_ID,
                new_answer_data = $scope.answer_update,
                current_user = $scope.current_user;

            //error handling
            if (!new_answer_data.human_ref_comment) {
                rgiNotifier.error('You must enter interview content!');
            } else if (!new_answer_data.human_ref_contact_date) {
                rgiNotifier.error('You must enter interview date!');
            } else if (!selected_interviewee) {
                rgiNotifier.error('You must select an existing contact or create a new one!');
            } else {
                contact_date = new Date(new_answer_data.human_ref_contact_date).toISOString();

                if ($scope.interviewee_selection==='new') {
                    if (!selected_interviewee.firstName || !selected_interviewee.lastName) {
                        rgiNotifier.error('You must enter a first and last name for new interviewees!');
                    } else if (!selected_interviewee.role) {
                        rgiNotifier.error('You must select a type of organization for new interviewees!');
                    } else if (!selected_interviewee.organization) {
                        rgiNotifier.error('You must enter an organization for new interviewees!');
                    } else {
                        if (!selected_interviewee.email && !selected_interviewee.phone) {
                            rgiNotifier.error('You must enter a valid email address or phone number!');
                        } else {
                            selected_interviewee.answers = [new_answer_data.answer_ID];
                            selected_interviewee.assessments = [new_answer_data.assessment_ID];
                            selected_interviewee.questions = [new_answer_data.question_ID];
                            selected_interviewee.users = [current_user._id];
                            rgiIntervieweeMethodSrvc.createInterviewee(selected_interviewee)
                                .then(function (interviewee) {
                                    new_ref_data = {
                                        citation_type: 'interview',
                                        interviewee_ID: interviewee._id,
                                        contact_date: contact_date,
                                        comment: new_answer_data.human_ref_comment,
                                        author: current_user._id
                                    };
                                    new_answer_data.references.push(new_ref_data);
                                    rgiAnswerMethodSrvc.updateAnswer(new_answer_data);
                                })
                                .then(function () {
                                    $scope.closeThisDialog();
                                    $rootScope.$broadcast('RESET_REFERENCE_ACTION');
                                    rgiNotifier.notify('Reference added');
                                }, function (reason) {
                                    rgiNotifier.notify(reason);
                                });
                            //email_domain = 'http://' + selected_interviewee.email.split('@')[1];
                            //if (email_domain === 'http://undefined') {
                            //    rgiNotifier.error('You must enter a valid email address!');
                            //} else {
                            //    selected_interviewee.answers = [new_answer_data.answer_ID];
                            //    selected_interviewee.assessments = [new_answer_data.assessment_ID];
                            //    selected_interviewee.questions = [new_answer_data.question_ID];
                            //    selected_interviewee.users = [current_user._id];
                            //    rgiIntervieweeMethodSrvc.createInterviewee(selected_interviewee)
                            //        .then(function (interviewee) {
                            //            new_ref_data = {
                            //                citation_type: 'interview',
                            //                interviewee_ID: interviewee._id,
                            //                contact_date: contact_date,
                            //                comment: new_answer_data.human_ref_comment,
                            //                author: current_user._id
                            //            };
                            //            new_answer_data.references.push(new_ref_data);
                            //            rgiAnswerMethodSrvc.updateAnswer(new_answer_data);
                            //        })
                            //        .then(function () {
                            //            $scope.closeThisDialog();
                            //            $rootScope.$broadcast('RESET_REFERENCE_ACTION');
                            //            rgiNotifier.notify('Reference added');
                            //        }, function (reason) {
                            //            rgiNotifier.notify(reason);
                            //        });
                            //}
                        }
                    }
                } else if ($scope.interviewee_selection==='existing') {
                    selected_interviewee_ID = selected_interviewee.originalObject.id;
                    new_ref_data = {
                        citation_type: 'interview',
                        interviewee_ID: selected_interviewee_ID,
                        contact_date: contact_date,
                        comment: new_answer_data.human_ref_comment,
                        author: current_user._id
                    };
                    new_answer_data.references.push(new_ref_data);

                    rgiIntervieweeSrvc.get({_id: selected_interviewee_ID}, function (interviewee) {
                        ['answer', 'assessment', 'question'].forEach(function (el) {
                            if (interviewee[el+'s'] !== undefined && interviewee[el+'s'].indexOf(new_answer_data[el+'_ID']) < 0) {
                                interviewee[el+'s'].push(new_answer_data[el+'_ID']);
                            } else if (interviewee[el+'s'] === undefined) {
                                interviewee[el+'s'] = [new_answer_data[el+'_ID']];
                            }
                        });
                        if (interviewee.users !== undefined && interviewee.users.indexOf(current_user._id) < 0) {
                            interviewee.users.push(current_user._id);
                        } else if (interviewee.users === undefined) {
                            interviewee.users = [current_user._id];
                        }
                        rgiAnswerMethodSrvc.updateAnswer(new_answer_data).then(function () {
                            rgiIntervieweeMethodSrvc.updateInterviewee(interviewee);
                            $scope.closeThisDialog();
                            $rootScope.$broadcast('RESET_REFERENCE_ACTION');
                            rgiNotifier.notify('Reference added!');

                        }, function (reason) {
                            rgiNotifier.error(reason);
                        });
                    });
                } else {
                    rgiNotifier.error('Something happened assigning interviewees!');
                }
            }
        };

        $scope.closeDialog = function () {
            ngDialog.close();
            $rootScope.$broadcast('RESET_SELECTED_REFERENCE_ACTION');
        };

        ///////////////
        //FILE UPLOAD
        ///////////////
        $scope.fileUploading = false;
        $scope.answer_update = $scope.$parent.answer;
        var uploader = $scope.uploader = rgiFileUploaderSrvc.get({
            isHTML5: true,
            withCredentials: true,
            url: 'file-upload'
        });

        uploader.filters.push({
            name: 'singleFile',
            fn: function () {
                return this.queue.length < 1;
            }
        });

        $scope.isAllowedFileExtension = function(fileName) {
            var allowedExtensionFound = false;

            rgiAllowedFileExtensionGuideSrvc.getList().forEach(function(extension) {
                var dottedExtension = '.' + extension;
                var extensionPosition = fileName.indexOf(dottedExtension);

                if((extensionPosition !== -1) && ((fileName.length - dottedExtension.length) === extensionPosition)) {
                    allowedExtensionFound = true;
                }
            });

            return allowedExtensionFound;
        };

        uploader.filters.push({
            name: 'allowedExtension',
            fn: function (fileItem) {
                var fileExtensionAllowed = $scope.isAllowedFileExtension(fileItem.name);

                if(!fileExtensionAllowed) {
                    rgiNotifier.error('Only ' + rgiAllowedFileExtensionGuideSrvc.getSerializedList() + ' files can be uploaded');
                }

                return fileExtensionAllowed;
            }
        });

        uploader.onCompleteItem = function (fileItem, response, status) {
            $scope.uploader.queue = [];
            if (status === 400) {
                rgiNotifier.error(response.reason);
            } else {// TODO add cancel upload after initial document pass
                $scope.new_document = response;
                $scope.value = true;
                var scope = $scope.$parent;
                scope.new_document = $scope.new_document;
                //rgiDialogFactory[scope.ref_selection + 'Create']($scope);
                if (scope.ref_selection === 'document') {
                    rgiDialogFactory.documentCreate(scope);
                } else if (scope.ref_selection === 'webpage') {
                    rgiDialogFactory.webpageCreate(scope);
                }
            }
        };

        $scope.uploadFileByUrl = function (fileUrl) {
            var handleFileUploadStatus = function (responseStatus) {
                $scope.uploader.queue[$scope.uploader.queue.length - 1].progress = responseStatus.data.completion * 100;

                if (responseStatus.data.completion < 1) {
                    $timeout(function () {
                        rgiRequestSubmitterSrvc.get('/api/remote-file/upload-progress/' + responseStatus.data._id).then(handleFileUploadStatus);
                    }, 1000);
                } else {
                    rgiRequestSubmitterSrvc.get('/api/remote-file/document/' + responseStatus.data._id).then(function (responseDocument) {
                        $scope.fileUploading = false;
                        uploader.onCompleteItem({}, responseDocument.data, responseDocument.status);
                    });
                }
            };

            $scope.fileUploading = true;
            rgiRequestSubmitterSrvc.get('/api/remote-file-upload?url=' + encodeURIComponent(fileUrl)).then(function (response) {
                if (response.data.reason) {
                    $scope.fileUploading = false;
                    rgiNotifier.error('The file cannot be uploaded');
                } else {
                    $scope.uploader.queue.push({
                        file: {
                            name: fileUrl.split('/')[fileUrl.split('/').length - 1],
                            size: response.data.size
                        },
                        isUploading: true,
                        progress: response.data.completion * 100
                    });
                    handleFileUploadStatus(response);
                }
            });

        };
    });
<commit_msg>SAVEPOINT<commit_after>'use strict';

angular.module('app')
    .controller('rgiNewRefDialogCtrl', function (
        $q,
        $scope,
        $rootScope,
        $route,
        $timeout,
        $http,
        ngDialog,
        rgiAllowedFileExtensionGuideSrvc,
        rgiDialogFactory,
        rgiNotifier,
        FileUploader,
        rgiUtilsSrvc,
        rgiFileUploaderSrvc,
        rgiRequestSubmitterSrvc,
        rgiAnswerMethodSrvc,
        rgiAssessmentSrvc,
        rgiIntervieweeSrvc,
        rgiIntervieweeMethodSrvc,
        rgiIdentitySrvc
    ) {
        /////////////
        //INTERVIEWEE
        /////////////
        $scope.current_user = rgiIdentitySrvc.currentUser;
        $scope.editorContentMaxLength = $scope.$root.editorContentMaxLength;
        $scope.taToolbarOptions = $scope.$root.taToolbarOptions;

        $scope.role_opts = [
            {text: 'Government', value: 'government'},
            {text: 'CSO', value: 'cso'},
            {text: 'Industry', value: 'industry'},
            {text: 'Expert', value: 'expert'},
            {text: 'Other', value: 'other'}];
        $scope.salutation_opts = ['mr.', 'mrs.', 'ms.'];
        //Datepicker opts
        var today = new Date();
        $scope.date_default = today;
        $scope.date_max_limit = today;
        $scope.date_options = {
            formatYear: 'yy',
            startingDay: 1
        };
        $scope.date_formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate'];
        $scope.date_format = $scope.date_formats[0];
        $scope.status = {
            opened: false
        };
        $scope.calendarOpen = function () {
            $scope.status.opened = true;
        };
        $scope.maxDate = today;

        $scope.answer_update = $scope.$parent.answer;
        $scope.interviewee_list = [];
        rgiIntervieweeSrvc.query({}, function (interviewees) {
            interviewees.forEach(function (interviewee) {
                var interviewee_add = {
                    firstName: interviewee.firstName,
                    lastName: interviewee.lastName,
                    id: interviewee._id,
                    assessments: interviewee.assessments,
                    email: interviewee.email,
                    assessment_countries: []
                };
                interviewee.assessments.forEach(function (assessment_ID) {
                    rgiAssessmentSrvc.get({assessment_ID: assessment_ID}, function (assessment) {
                        interviewee_add.assessment_countries.push(assessment.country);
                    });
                });
                $scope.interviewee_list.push(interviewee_add);
            });
        });

        $scope.intervieweeSelect = function (selection) {
            $scope.interviewee_selection = selection;
        };

        $scope.interviewRefSubmit = function (selected_interviewee) {
            var contact_date, email_domain, new_ref_data, selected_interviewee_ID,
                new_answer_data = $scope.answer_update,
                current_user = $scope.current_user;

            //error handling
            if (!new_answer_data.human_ref_comment) {
                rgiNotifier.error('You must enter interview content!');
            } else if (!new_answer_data.human_ref_contact_date) {
                rgiNotifier.error('You must enter interview date!');
            } else if (!selected_interviewee) {
                rgiNotifier.error('You must select an existing contact or create a new one!');
            } else {
                contact_date = new Date(new_answer_data.human_ref_contact_date).toISOString();

                if ($scope.interviewee_selection==='new') {
                    if (!selected_interviewee.firstName || !selected_interviewee.lastName) {
                        rgiNotifier.error('You must enter a first and last name for new interviewees!');
                    } else if (!selected_interviewee.role) {
                        rgiNotifier.error('You must select a type of organization for new interviewees!');
                    } else if (!selected_interviewee.organization) {
                        rgiNotifier.error('You must enter an organization for new interviewees!');
                    } else {
                        if (!selected_interviewee.email && !selected_interviewee.phone) {
                            rgiNotifier.error('You must enter a valid email address or phone number!');
                        } else {
                            selected_interviewee.answers = [new_answer_data.answer_ID];
                            selected_interviewee.assessments = [new_answer_data.assessment_ID];
                            selected_interviewee.questions = [new_answer_data.question_ID];
                            selected_interviewee.users = [current_user._id];
                            rgiIntervieweeMethodSrvc.createInterviewee(selected_interviewee)
                                .then(function (interviewee) {
                                    new_ref_data = {
                                        citation_type: 'interview',
                                        interviewee_ID: interviewee._id,
                                        contact_date: contact_date,
                                        comment: new_answer_data.human_ref_comment,
                                        author: current_user._id
                                    };
                                    new_answer_data.references.push(new_ref_data);
                                    rgiAnswerMethodSrvc.updateAnswer(new_answer_data);
                                })
                                .then(function () {
                                    $scope.closeThisDialog();
                                    $rootScope.$broadcast('RESET_REFERENCE_ACTION');
                                    rgiNotifier.notify('Reference added');
                                }, function (reason) {
                                    rgiNotifier.notify(reason);
                                });
                            //email_domain = 'http://' + selected_interviewee.email.split('@')[1];
                            //if (email_domain === 'http://undefined') {
                            //    rgiNotifier.error('You must enter a valid email address!');
                            //} else {
                            //    selected_interviewee.answers = [new_answer_data.answer_ID];
                            //    selected_interviewee.assessments = [new_answer_data.assessment_ID];
                            //    selected_interviewee.questions = [new_answer_data.question_ID];
                            //    selected_interviewee.users = [current_user._id];
                            //    rgiIntervieweeMethodSrvc.createInterviewee(selected_interviewee)
                            //        .then(function (interviewee) {
                            //            new_ref_data = {
                            //                citation_type: 'interview',
                            //                interviewee_ID: interviewee._id,
                            //                contact_date: contact_date,
                            //                comment: new_answer_data.human_ref_comment,
                            //                author: current_user._id
                            //            };
                            //            new_answer_data.references.push(new_ref_data);
                            //            rgiAnswerMethodSrvc.updateAnswer(new_answer_data);
                            //        })
                            //        .then(function () {
                            //            $scope.closeThisDialog();
                            //            $rootScope.$broadcast('RESET_REFERENCE_ACTION');
                            //            rgiNotifier.notify('Reference added');
                            //        }, function (reason) {
                            //            rgiNotifier.notify(reason);
                            //        });
                            //}
                        }
                    }
                } else if ($scope.interviewee_selection==='existing') {
                    selected_interviewee_ID = selected_interviewee.originalObject.id;
                    new_ref_data = {
                        citation_type: 'interview',
                        interviewee_ID: selected_interviewee_ID,
                        contact_date: contact_date,
                        comment: new_answer_data.human_ref_comment,
                        author: current_user._id
                    };
                    new_answer_data.references.push(new_ref_data);

                    rgiIntervieweeSrvc.get({_id: selected_interviewee_ID}, function (interviewee) {
                        ['answer', 'assessment', 'question'].forEach(function (el) {
                            if (interviewee[el+'s'] !== undefined && interviewee[el+'s'].indexOf(new_answer_data[el+'_ID']) < 0) {
                                interviewee[el+'s'].push(new_answer_data[el+'_ID']);
                            } else if (interviewee[el+'s'] === undefined) {
                                interviewee[el+'s'] = [new_answer_data[el+'_ID']];
                            }
                        });
                        if (interviewee.users !== undefined && interviewee.users.indexOf(current_user._id) < 0) {
                            interviewee.users.push(current_user._id);
                        } else if (interviewee.users === undefined) {
                            interviewee.users = [current_user._id];
                        }
                        rgiAnswerMethodSrvc.updateAnswer(new_answer_data).then(function () {
                            rgiIntervieweeMethodSrvc.updateInterviewee(interviewee);
                            $scope.closeThisDialog();
                            $rootScope.$broadcast('RESET_REFERENCE_ACTION');
                            rgiNotifier.notify('Reference added!');

                        }, function (reason) {
                            rgiNotifier.error(reason);
                        });
                    });
                } else {
                    rgiNotifier.error('Something happened assigning interviewees!');
                }
            }
        };

        $scope.closeDialog = function () {
            ngDialog.close();
            $rootScope.$broadcast('RESET_SELECTED_REFERENCE_ACTION');
        };

        ///////////////
        //FILE UPLOAD
        ///////////////
        $scope.fileUploading = false;
        $scope.answer_update = $scope.$parent.answer;
        var uploader = $scope.uploader = rgiFileUploaderSrvc.get({
            isHTML5: true,
            withCredentials: true,
            url: 'file-upload'
        });

        uploader.filters.push({
            name: 'singleFile',
            fn: function () {
                return this.queue.length < 1;
            }
        });

        $scope.isAllowedFileExtension = function(fileName) {
            var allowedExtensionFound = false;

            rgiAllowedFileExtensionGuideSrvc.getList().forEach(function(extension) {
                var dottedExtension = '.' + extension;
                var extensionPosition = fileName.indexOf(dottedExtension);

                if((extensionPosition !== -1) && ((fileName.length - dottedExtension.length) === extensionPosition)) {
                    allowedExtensionFound = true;
                }
            });

            return allowedExtensionFound;
        };

        uploader.filters.push({
            name: 'allowedExtension',
            fn: function (fileItem) {
                var fileExtensionAllowed = $scope.isAllowedFileExtension(fileItem.name);

                if(!fileExtensionAllowed) {
                    rgiNotifier.error('Only ' + rgiAllowedFileExtensionGuideSrvc.getSerializedList() + ' files can be uploaded');
                }

                return fileExtensionAllowed;
            }
        });

        uploader.onCompleteItem = function (fileItem, response, status) {
            $scope.uploader.queue = [];
            if (status === 400) {
                rgiNotifier.error(response.reason);
            } else {// TODO add cancel upload after initial document pass
                $scope.new_document = response;
                $scope.value = true;
                var scope = $scope.$parent;
                scope.new_document = $scope.new_document;
                //rgiDialogFactory[scope.ref_selection + 'Create']($scope);
                if (scope.ref_selection === 'document') {
                    rgiDialogFactory.documentCreate(scope);
                } else if (scope.ref_selection === 'webpage') {
                    rgiDialogFactory.webpageCreate(scope);
                }
            }
        };

        $scope.uploadFileByUrl = function (fileUrl) {
            var handleFileUploadStatus = function (responseStatus) {
                $scope.uploader.queue[$scope.uploader.queue.length - 1].progress = responseStatus.data.completion * 100;

                if (responseStatus.data.completion < 1) {
                    $timeout(function () {
                        rgiRequestSubmitterSrvc.get('/api/remote-file/upload-progress/' + responseStatus.data._id).then(handleFileUploadStatus);
                    }, 1000);
                } else {
                    rgiRequestSubmitterSrvc.get('/api/remote-file/document/' + responseStatus.data._id).then(function (responseDocument) {
                        $scope.fileUploading = false;
                        uploader.onCompleteItem({}, responseDocument.data, responseDocument.status);
                    });
                }
            };

            $scope.fileUploading = true;
            rgiRequestSubmitterSrvc.get('/api/remote-file-upload?url=' + encodeURIComponent(fileUrl)).then(function (response) {
                if (response.data.reason) {
                    $scope.fileUploading = false;
                    rgiNotifier.error('The file cannot be uploaded');
                } else {
                    $scope.uploader.queue.push({
                        file: {
                            name: fileUrl.split('/')[fileUrl.split('/').length - 1],
                            size: response.data.size
                        },
                        isUploading: true,
                        progress: response.data.completion * 100
                    });
                    handleFileUploadStatus(response);
                }
            });

        };
    });
<|endoftext|>


<commit_before>import Vector3 from '../../math/Vector3';
import L_Element from '../L_Element';
import Matrix44 from '../../math/Matrix44';

export default class L_AbstractCamera extends L_Element {
  constructor(glBoostContext, toRegister, lookat) {
    super(glBoostContext, toRegister);

    if (this.constructor === L_AbstractCamera) {
      throw new TypeError('Cannot construct AbstractCamera instances directly.');
    }

    this._translate = lookat.eye;
    this._center = lookat.center;
    this._up = lookat.up;

    this._cameraController = null;

    this._dirtyView = true;

    this._middleLevelCamera = null;
  }

  set cameraController(controller) {
    this._cameraController = controller;
    if (this._middleLevelCamera !== null) {
      controller.addCamera(this._middleLevelCamera);
    } else {
      controller.addCamera(this);
    }
  }

  get cameraController() {
    return this._cameraController;
  }

  _affectedByCameraController() {
    if (this._cameraController !== null) {
      let results = this._cameraController.convert(this);
      this._translateInner = results[0];
      this._centerInner = results[1];
      this._upInner = results[2];
      this._zNearInner = results[3];
      this._zFarInner = results[4];
    } else {
      this._translateInner = super.translate.clone();
      this._centerInner = this._center.clone();
      this._upInner = this._up.clone();
      this._zNearInner = this.this._zFar.clone();
      this._zFarInner = this.this._zNear.clone();
    }
  }

  get middleLevelCamera() {
    return this._middleLevelCamera;
  }

  _needUpdateView(withTryingResetOfCameraController = true) {
    if (this._cameraController !== null && withTryingResetOfCameraController) {
      this._cameraController.tryReset();
    }
    this._dirtyView = true;
  }

  lookAtRHMatrix() {
    if (this._dirtyView) {
      this._affectedByCameraController();
      this._viewMatrix = L_AbstractCamera.lookAtRHMatrix(this.translateInner, this.centerInner, this.upInner);
      this._dirtyView = false;
      return this._viewMatrix.clone();
    } else {
      return this._viewMatrix.clone();
    }
  }

  static lookAtRHMatrix(eye, center, up) {

    var f = Vector3.normalize(Vector3.subtract(center, eye));
    var s = Vector3.normalize(Vector3.cross(f, up));
    var u = Vector3.cross(s, f);

    return new Matrix44(s.x, s.y, s.z, -Vector3.dotProduct(s,eye),
      u.x, u.y, u.z, -Vector3.dotProduct(u,eye),
      -f.x, -f.y, -f.z, Vector3.dotProduct(f,eye),
      0, 0, 0, 1);
  }

  setAsMainCamera(scene) {
    L_AbstractCamera._mainCamera[scene.toString()] = this;
  }

  isMainCamera(scene) {
    return L_AbstractCamera._mainCamera[scene.toString()] === this;
  }

  set translate(vec) {
    super.translate = vec;
    this._needUpdateView();
  }

  get translate() {
    return this._translate;
  }

  get translateInner() {
    return this._translateInner;
  }

  set eye(vec) {
    super.translate = vec;
    this._needUpdateView();
  }

  get eye() {
    return this._translate;
  }

  get eyeInner() {
    return this._translateInner;
  }

  set center(vec) {
    if (this._center.isEqual(vec)) {
      return;
    }
    this._center = vec;
    this._needUpdateView();
  }

  get center() {
    return this._center;
  }

  get centerInner() {
    return this._centerInner;
  }

  set up(vec) {
    if (this._up.isEqual(vec)) {
      return;
    }
    this._up = vec;
    this._needUpdateView();
  }

  get up() {
    return this._up;
  }

  get upInner() {
    return this._upInner;
  }

  set texture(texture) {
    this._texture = texture;
  }

  get texture() {
    return this._texture;
  }
}

L_AbstractCamera._mainCamera = {};
<commit_msg>Fix L_AbstractCamera<commit_after>import Vector3 from '../../math/Vector3';
import L_Element from '../L_Element';
import Matrix44 from '../../math/Matrix44';

export default class L_AbstractCamera extends L_Element {
  constructor(glBoostContext, toRegister, lookat) {
    super(glBoostContext, toRegister);

    if (this.constructor === L_AbstractCamera) {
      throw new TypeError('Cannot construct AbstractCamera instances directly.');
    }

    this._translate = lookat.eye;
    this._center = lookat.center;
    this._up = lookat.up;

    this._cameraController = null;

    this._dirtyView = true;

    this._middleLevelCamera = null;
  }

  set cameraController(controller) {
    this._cameraController = controller;
    if (this._middleLevelCamera !== null) {
      controller.addCamera(this._middleLevelCamera);
    } else {
      controller.addCamera(this);
    }
  }

  get cameraController() {
    return this._cameraController;
  }

  _affectedByCameraController() {
    if (this._cameraController !== null) {
      let results = this._cameraController.convert(this);
      this._translateInner = results[0];
      this._centerInner = results[1];
      this._upInner = results[2];
      this._zNearInner = results[3];
      this._zFarInner = results[4];
    } else {
      this._translateInner = super.translate.clone();
      this._centerInner = this._center.clone();
      this._upInner = this._up.clone();
      this._zNearInner = this._zFar;
      this._zFarInner = this._zNear;
    }
  }

  get middleLevelCamera() {
    return this._middleLevelCamera;
  }

  _needUpdateView(withTryingResetOfCameraController = true) {
    if (this._cameraController !== null && withTryingResetOfCameraController) {
      this._cameraController.tryReset();
    }
    this._dirtyView = true;
  }

  lookAtRHMatrix() {
    if (this._dirtyView) {
      this._affectedByCameraController();
      this._viewMatrix = L_AbstractCamera.lookAtRHMatrix(this.translateInner, this.centerInner, this.upInner);
      this._dirtyView = false;
      return this._viewMatrix.clone();
    } else {
      return this._viewMatrix.clone();
    }
  }

  static lookAtRHMatrix(eye, center, up) {

    var f = Vector3.normalize(Vector3.subtract(center, eye));
    var s = Vector3.normalize(Vector3.cross(f, up));
    var u = Vector3.cross(s, f);

    return new Matrix44(s.x, s.y, s.z, -Vector3.dotProduct(s,eye),
      u.x, u.y, u.z, -Vector3.dotProduct(u,eye),
      -f.x, -f.y, -f.z, Vector3.dotProduct(f,eye),
      0, 0, 0, 1);
  }

  setAsMainCamera(scene) {
    L_AbstractCamera._mainCamera[scene.toString()] = this;
  }

  isMainCamera(scene) {
    return L_AbstractCamera._mainCamera[scene.toString()] === this;
  }

  set translate(vec) {
    super.translate = vec;
    this._needUpdateView();
  }

  get translate() {
    return this._translate;
  }

  get translateInner() {
    return this._translateInner;
  }

  set eye(vec) {
    super.translate = vec;
    this._needUpdateView();
  }

  get eye() {
    return this._translate;
  }

  get eyeInner() {
    return this._translateInner;
  }

  set center(vec) {
    if (this._center.isEqual(vec)) {
      return;
    }
    this._center = vec;
    this._needUpdateView();
  }

  get center() {
    return this._center;
  }

  get centerInner() {
    return this._centerInner;
  }

  set up(vec) {
    if (this._up.isEqual(vec)) {
      return;
    }
    this._up = vec;
    this._needUpdateView();
  }

  get up() {
    return this._up;
  }

  get upInner() {
    return this._upInner;
  }

  set texture(texture) {
    this._texture = texture;
  }

  get texture() {
    return this._texture;
  }
}

L_AbstractCamera._mainCamera = {};
<|endoftext|>