<commit_before>var RegionRenderer = require('./regionrenderer');

module.exports = WorldRenderer;

var TILES_X = 32;
var TILES_Y = 32;
var TILES_PER_REGION = TILES_X * TILES_Y;

var HEADER_BYTES = 3;
var BYTES_PER_TILE = 23;
var BYTES_PER_ROW = BYTES_PER_TILE * TILES_X;
var BYTES_PER_REGION = BYTES_PER_TILE * TILES_PER_REGION;

var TILE_WIDTH = 8;
var TILE_HEIGHT = 8;

var REGION_WIDTH = TILE_WIDTH * TILES_X;
var REGION_HEIGHT = TILE_HEIGHT * TILES_Y;

function WorldRenderer(viewport, worldManager, assetsManager) {
  // Ensure that canvases can be anchored to the viewport.
  var position = getComputedStyle(viewport).getPropertyValue('position');
  if (position != 'absolute' && position != 'relative') {
    viewport.style.position = 'relative';
  }

  this.viewport = viewport;
  this.world = worldManager;
  this.assets = assetsManager;

  this.centerX = 0;
  this.centerY = 0;

  this.materials = assetsManager.getResourceLoader('.material');
  this.matmods = assetsManager.getResourceLoader('.matmod');
  this.objects = assetsManager.getResourceLoader('.object');

  // TODO: Fat arrows.
  var self = this;
  this.materials.on('images', function () { self.requestRender(); });
  this.matmods.on('images', function () { self.requestRender(); });

  this._canvasPool = [];
  this._regions = {};

  this._bounds = viewport.getBoundingClientRect();
  this._regionsX = 0;
  this._regionsY = 0;
  this._fromRegionX = 0;
  this._fromRegionY = 0;
  this._toRegionX = 0;
  this._toRegionY = 0;
  this._originX = 0;
  this._originY = 0;
  this._visibleRegionsX = 0;
  this._visibleRegionsY = 0;

  this._loaded = false;
  this._requestingRender = false;
  this._setup = false;

  // Set up information about the world when it's available.
  if (worldManager.metadata) {
    this._loadMetadata(worldManager.metadata);
  }

  worldManager.on('load', function (event) {
    self._loadMetadata(worldManager.metadata);
  });
}

/**
 * Centers the renderer viewport on the specified coordinates.
 * @param {number} tileX The X in-game coordinate to center on.
 * @param {number} tileY The Y in-game coordinate to center on.
 */
WorldRenderer.prototype.center = function (tileX, tileY) {
  this.centerX = tileX;
  this.centerY = tileY;
  this._calculateViewport();
};

WorldRenderer.prototype.getRegion = function (regionX, regionY, opt_skipNeighbors) {
  if (!this._loaded) return null;

  // Wrap the X axis.
  if (regionX >= this._regionsX) {
    regionX -= this._regionsX;
  } else if (regionX < 0) {
    regionX += this._regionsX;
  }

  // The Y axis doesn't wrap.
  if (regionY < 0 || regionY >= this._regionsY) {
    return null;
  }

  var key = regionX + ':' + regionY;

  // Get or create the region.
  var region;
  if (key in this._regions) {
    region = this._regions[key];
  } else {
    region = new RegionRenderer(regionX, regionY);
    this._regions[key] = region;
  }

  // Load the region data if it has not been initialized yet.
  if (region.state == RegionRenderer.STATE_UNINITIALIZED) {
    region.state = RegionRenderer.STATE_LOADING;

    // TODO: Switch to fat arrows when Chrome supports it.
    var self = this;
    this.world.getRegion(regionX, regionY, function (err, regionData) {
      if (err) {
        region.state = RegionRenderer.STATE_ERROR;
        if (err.message != 'Key not found') {
          console.error(err.stack);
        }
        return;
      }

      region.entities = regionData.entities;
      region.tileView = new DataView(regionData.buffer);
      region.state = RegionRenderer.STATE_READY;

      // Ensure that the graphics for all the tiles in this region are loaded.
      var ids = region.getResourceIds();
      self.materials.loadImages(ids.materials);
      self.matmods.loadImages(ids.matmods);

      region.dirty = true;
      self.requestRender();
    });
  }

  // If the region should not get neighbors, return now.
  if (opt_skipNeighbors) return region;

  // Add references to surrounding regions.
  if (!region.neighbors) {
    region.neighbors = [
      this.getRegion(regionX, regionY + 1, true),
      this.getRegion(regionX + 1, regionY, true),
      this.getRegion(regionX, regionY - 1, true),
      this.getRegion(regionX - 1, regionY, true)
    ];

    for (var i = 0; i < 4; i++) {
      var neighbor = region.neighbors[i];
      if (!neighbor) continue;
      neighbor.dirty = true;
    }

    region.dirty = true;
    this.requestRender();
  }

  return region;
};

WorldRenderer.prototype.isRegionVisible = function (region) {
  if (!region) return false;

  var fromX = this._fromRegionX, toX = this._toRegionX,
      fromY = this._fromRegionY, toY = this._toRegionY;

  var visibleY = region.y >= fromY && region.y < toY;
  var visibleX = (region.x >= fromX && region.x < toX) ||
    (region.x >= fromX - this._regionsX && region.x < toX - this._regionsX) ||
    (region.x >= fromX + this._regionsX && region.x < toX + this._regionsX);

  return visibleX && visibleY;
};

// Start loading the resource indexes.
WorldRenderer.prototype.preload = function () {
  this.materials.loadIndex();
  this.matmods.loadIndex();
  this.objects.loadIndex();
};

// TODO: When Chrome and Firefox support CanvasProxy offload rendering to the
//       worker.
WorldRenderer.prototype.render = function () {
  if (!this._loaded) return;

  if (!this._setup) {
    this._calculateViewport();
    return;
  }

  // TODO: Create a more intelligent render loop.
  for (var regionY = this._fromRegionY; regionY < this._toRegionY; regionY++) {
    for (var regionX = this._fromRegionX; regionX < this._toRegionX; regionX++) {
      var region = this.getRegion(regionX, regionY);
      if (!region) continue;

      // Attempt to find a canvas that is already assigned to the current region.
      var canvas = null, freeItem = null, rerender = false;
      for (var i = 0; i < this._canvasPool.length; i++) {
        var poolItem = this._canvasPool[i];

        var poolRegion = poolItem.region;
        if (poolRegion == region) {
          canvas = poolItem.canvas;
          break;
        }

        // Remember one item in the pool that is free in case we need it.
        if (!freeItem && (!poolRegion || !this.isRegionVisible(poolRegion))) {
          freeItem = poolItem;
        }
      }

      // If the loop didn't break, no canvas was found. Claim one that is free.
      if (i == this._canvasPool.length) {
        freeItem.region = region;
        canvas = freeItem.canvas;

        // Indicate that we need to force rerender.
        rerender = true;
      }

      // Position the canvas correctly.
      var screenX = regionX * REGION_WIDTH,
          screenY = (this._regionsY - regionY) * REGION_HEIGHT - this._bounds.height;
      canvas.style.left = (screenX - this._originX) + 'px';
      canvas.style.top = (screenY - this._originY) + 'px';
      canvas.style.visibility = (region.state == RegionRenderer.STATE_READY ? 'visible' : 'hidden');

      // Render to the canvas if necessary.
      if (region.dirty || rerender) {
        region.render(this, canvas);
      }
    }
  }
};

WorldRenderer.prototype.requestRender = function () {
  if (!this._loaded || this._requestingRender) return;
  this._requestingRender = true;

  var self = this;
  process.nextTick(function () {
    self.render();
    self._requestingRender = false;
  });
};

WorldRenderer.prototype.scroll = function (deltaX, deltaY) {
  this.centerX += deltaX;
  this.centerY += deltaY;

  if (this.centerX < 0) {
    this.centerX += this._regionsX * TILES_X;
  } else if (this.centerX >= this._regionsX * TILES_X) {
    this.centerX -= this._regionsX * TILES_X;
  }

  this._calculateRegions();
};

WorldRenderer.prototype._calculateRegions = function () {
  if (!this._loaded) return;

  this._fromRegionX = Math.floor(this.centerX / TILES_X - this._bounds.width / 2 / REGION_WIDTH);
  this._fromRegionY = Math.floor(this.centerY / TILES_Y - this._bounds.height / 2 / REGION_HEIGHT);
  this._toRegionX = this._fromRegionX + this._visibleRegionsX;
  this._toRegionY = this._fromRegionY + this._visibleRegionsY;

  this._originX = this.centerX * TILE_WIDTH - this._bounds.width / 2,
  this._originY = ((this._regionsY - 1) * TILES_Y - this.centerY) * TILE_HEIGHT - this._bounds.height / 2;

  this.requestRender();
};

WorldRenderer.prototype._calculateViewport = function () {
  if (!this._loaded) return;

  this._setup = true;

  this._bounds = this.viewport.getBoundingClientRect();
  this._visibleRegionsX = Math.ceil(this._bounds.width / REGION_WIDTH + 1);
  this._visibleRegionsY = Math.ceil(this._bounds.height / REGION_HEIGHT + 1);

  // Ensure that there are enough canvas elements to render the screen.
  var requiredCanvases = this._visibleRegionsX * this._visibleRegionsY;
  for (var i = this._canvasPool.length; i < requiredCanvases; i++) {
    var canvas = document.createElement('canvas');
    canvas.style.position = 'absolute';
    canvas.style.visibility = 'hidden';
    canvas.width = REGION_WIDTH;
    canvas.height = REGION_HEIGHT;

    this._canvasPool.push({canvas: canvas, region: null});
    this.viewport.appendChild(canvas);
  }

  this._calculateRegions();
};

WorldRenderer.prototype._loadMetadata = function (metadata) {
  var spawn, size;
  switch (metadata.__version__) {
    case 1:
      spawn = metadata.playerStart;
      size = metadata.planet.size;
      break;
    case 2:
      spawn = metadata.playerStart;
      size = metadata.worldTemplate.size;
      break;
    default:
      throw new Error('Unsupported metadata version ' + metadata.__version__);
  }

  this.centerX = spawn[0];
  this.centerY = spawn[1];

  this._regionsX = size[0] / TILES_X;
  this._regionsY = size[1] / TILES_Y;

  this._loaded = true;
};
<commit_msg>Add support for zooming<commit_after>var RegionRenderer = require('./regionrenderer');

module.exports = WorldRenderer;

var TILES_X = 32;
var TILES_Y = 32;
var TILES_PER_REGION = TILES_X * TILES_Y;

var HEADER_BYTES = 3;
var BYTES_PER_TILE = 23;
var BYTES_PER_ROW = BYTES_PER_TILE * TILES_X;
var BYTES_PER_REGION = BYTES_PER_TILE * TILES_PER_REGION;

var TILE_WIDTH = 8;
var TILE_HEIGHT = 8;

var REGION_WIDTH = TILE_WIDTH * TILES_X;
var REGION_HEIGHT = TILE_HEIGHT * TILES_Y;

var MIN_ZOOM = .1;
var MAX_ZOOM = 3;

function WorldRenderer(viewport, worldManager, assetsManager) {
  // Ensure that canvases can be anchored to the viewport.
  var position = getComputedStyle(viewport).getPropertyValue('position');
  if (position != 'absolute' && position != 'relative') {
    viewport.style.position = 'relative';
  }

  this.viewport = viewport;
  this.world = worldManager;
  this.assets = assetsManager;

  this.centerX = 0;
  this.centerY = 0;
  this.zoom = 1;

  this.materials = assetsManager.getResourceLoader('.material');
  this.matmods = assetsManager.getResourceLoader('.matmod');
  this.objects = assetsManager.getResourceLoader('.object');

  // TODO: Fat arrows.
  var self = this;
  this.materials.on('images', function () { self.requestRender(); });
  this.matmods.on('images', function () { self.requestRender(); });

  this._canvasPool = [];
  this._regions = {};

  this._bounds = viewport.getBoundingClientRect();
  this._regionsX = 0;
  this._regionsY = 0;
  this._fromRegionX = 0;
  this._fromRegionY = 0;
  this._toRegionX = 0;
  this._toRegionY = 0;
  this._originX = 0;
  this._originY = 0;
  this._visibleRegionsX = 0;
  this._visibleRegionsY = 0;

  this._loaded = false;
  this._requestingRender = false;
  this._setup = false;

  // Set up information about the world when it's available.
  if (worldManager.metadata) {
    this._loadMetadata(worldManager.metadata);
  }

  worldManager.on('load', function (event) {
    self._loadMetadata(worldManager.metadata);
  });
}

/**
 * Centers the renderer viewport on the specified coordinates.
 * @param {number} tileX The X in-game coordinate to center on.
 * @param {number} tileY The Y in-game coordinate to center on.
 */
WorldRenderer.prototype.center = function (tileX, tileY) {
  this.centerX = tileX;
  this.centerY = tileY;
  this._calculateViewport();
};

WorldRenderer.prototype.getRegion = function (regionX, regionY, opt_skipNeighbors) {
  if (!this._loaded) return null;

  // Wrap the X axis.
  if (regionX >= this._regionsX) {
    regionX -= this._regionsX;
  } else if (regionX < 0) {
    regionX += this._regionsX;
  }

  // The Y axis doesn't wrap.
  if (regionY < 0 || regionY >= this._regionsY) {
    return null;
  }

  var key = regionX + ':' + regionY;

  // Get or create the region.
  var region;
  if (key in this._regions) {
    region = this._regions[key];
  } else {
    region = new RegionRenderer(regionX, regionY);
    this._regions[key] = region;
  }

  // Load the region data if it has not been initialized yet.
  if (region.state == RegionRenderer.STATE_UNINITIALIZED) {
    region.state = RegionRenderer.STATE_LOADING;

    // TODO: Switch to fat arrows when Chrome supports it.
    var self = this;
    this.world.getRegion(regionX, regionY, function (err, regionData) {
      if (err) {
        region.state = RegionRenderer.STATE_ERROR;
        if (err.message != 'Key not found') {
          console.error(err.stack);
        }
        return;
      }

      region.entities = regionData.entities;
      region.tileView = new DataView(regionData.buffer);
      region.state = RegionRenderer.STATE_READY;

      // Ensure that the graphics for all the tiles in this region are loaded.
      var ids = region.getResourceIds();
      self.materials.loadImages(ids.materials);
      self.matmods.loadImages(ids.matmods);

      region.dirty = true;
      self.requestRender();
    });
  }

  // If the region should not get neighbors, return now.
  if (opt_skipNeighbors) return region;

  // Add references to surrounding regions.
  if (!region.neighbors) {
    region.neighbors = [
      this.getRegion(regionX, regionY + 1, true),
      this.getRegion(regionX + 1, regionY, true),
      this.getRegion(regionX, regionY - 1, true),
      this.getRegion(regionX - 1, regionY, true)
    ];

    for (var i = 0; i < 4; i++) {
      var neighbor = region.neighbors[i];
      if (!neighbor) continue;
      neighbor.dirty = true;
    }

    region.dirty = true;
    this.requestRender();
  }

  return region;
};

WorldRenderer.prototype.isRegionVisible = function (region) {
  if (!region) return false;

  var fromX = this._fromRegionX, toX = this._toRegionX,
      fromY = this._fromRegionY, toY = this._toRegionY;

  var visibleY = region.y >= fromY && region.y < toY;
  var visibleX = (region.x >= fromX && region.x < toX) ||
    (region.x >= fromX - this._regionsX && region.x < toX - this._regionsX) ||
    (region.x >= fromX + this._regionsX && region.x < toX + this._regionsX);

  return visibleX && visibleY;
};

// Start loading the resource indexes.
WorldRenderer.prototype.preload = function () {
  this.materials.loadIndex();
  this.matmods.loadIndex();
  this.objects.loadIndex();
};

// TODO: When Chrome and Firefox support CanvasProxy offload rendering to the
//       worker.
WorldRenderer.prototype.render = function () {
  if (!this._loaded) return;

  if (!this._setup) {
    this._calculateViewport();
    return;
  }

  // Precalculate free canvases and a canvas lookup map.
  var freePool = [], poolLookup = {};
  for (var i = 0; i < this._canvasPool.length; i++) {
    var poolItem = this._canvasPool[i],
        region = poolItem.region;

    if (region && this.isRegionVisible(region)) {
      poolLookup[region.x + ':' + region.y] = poolItem;
    } else {
      poolItem.canvas.style.visibility = 'hidden';
      freePool.push(poolItem);
    }
  }

  // TODO: Create a more intelligent render loop.
  for (var regionY = this._fromRegionY; regionY < this._toRegionY; regionY++) {
    for (var regionX = this._fromRegionX; regionX < this._toRegionX; regionX++) {
      var region = this.getRegion(regionX, regionY);
      if (!region) continue;

      // Attempt to find a canvas that is already assigned to the current region.
      var item = poolLookup[region.x + ':' + region.y], forceRender = false;
      if (!item) {
        item = freePool.pop();
        item.region = region;
        forceRender = true;
      }
      var canvas = item.canvas;

      // Position the canvas correctly.
      var screenX = regionX * this._screenRegionWidth,
          screenY = (this._regionsY - regionY) * this._screenRegionHeight;
      canvas.style.left = (screenX - this._originX) + 'px';
      canvas.style.top = (screenY - this._originY) + 'px';
      canvas.style.visibility = (region.state == RegionRenderer.STATE_READY ? 'visible' : 'hidden');

      // Render to the canvas if necessary.
      if (region.dirty || forceRender) {
        var context = canvas.getContext('2d');
        region.render(this, canvas);
      }
    }
  }
};

WorldRenderer.prototype.requestRender = function () {
  if (!this._loaded || this._requestingRender) return;
  this._requestingRender = true;

  var self = this;
  process.nextTick(function () {
    self.render();
    self._requestingRender = false;
  });
};

WorldRenderer.prototype.scroll = function (deltaX, deltaY, opt_screenPixels) {
  if (opt_screenPixels) {
    deltaX /= this._screenTileWidth;
    deltaY /= this._screenTileHeight;
  }

  this.centerX += deltaX;
  this.centerY += deltaY;

  if (this.centerX < 0) {
    this.centerX += this._regionsX * TILES_X;
  } else if (this.centerX >= this._regionsX * TILES_X) {
    this.centerX -= this._regionsX * TILES_X;
  }

  this._calculateRegions();
};

WorldRenderer.prototype.setZoom = function (zoom) {
  if (zoom < MIN_ZOOM) zoom = MIN_ZOOM;
  if (zoom > MAX_ZOOM) zoom = MAX_ZOOM;
  if (zoom == this.zoom) return;

  this.zoom = zoom;
  this._calculateViewport();
};

WorldRenderer.prototype.zoomIn = function () {
  this.setZoom(this.zoom + this.zoom * .1);
};

WorldRenderer.prototype.zoomOut = function () {
  this.setZoom(this.zoom - this.zoom * .1);
};

WorldRenderer.prototype._calculateRegions = function () {
  if (!this._loaded) return;

  this._fromRegionX = Math.floor(this.centerX / TILES_X - this._bounds.width / 2 / this._screenRegionWidth);
  this._fromRegionY = Math.floor(this.centerY / TILES_Y - this._bounds.height / 2 / this._screenRegionHeight);
  this._toRegionX = this._fromRegionX + this._visibleRegionsX;
  this._toRegionY = this._fromRegionY + this._visibleRegionsY;

  this._originX = this.centerX * this._screenTileWidth - this._bounds.width / 2,
  this._originY = ((this._regionsY + 1) * TILES_Y - this.centerY) * this._screenTileHeight - this._bounds.height / 2;

  this.requestRender();
};

WorldRenderer.prototype._calculateViewport = function () {
  if (!this._loaded) return;

  this._setup = true;

  this._screenRegionWidth = REGION_WIDTH * this.zoom;
  this._screenRegionHeight = REGION_HEIGHT * this.zoom;
  this._screenTileWidth = TILE_WIDTH * this.zoom;
  this._screenTileHeight = TILE_HEIGHT * this.zoom;

  this._bounds = this.viewport.getBoundingClientRect();
  this._visibleRegionsX = Math.ceil(this._bounds.width / this._screenRegionWidth + 1);
  this._visibleRegionsY = Math.ceil(this._bounds.height / this._screenRegionHeight + 1);

  // Ensure that there are enough canvas elements to render the screen.
  var existing = this._canvasPool.length,
      required = this._visibleRegionsX * this._visibleRegionsY,
      count = Math.max(existing, required);
  for (var i = 0; i < count; i++) {
    var canvas;

    if (i < existing) {
      canvas = this._canvasPool[i].canvas;
    } else {
      canvas = document.createElement('canvas');
      canvas.style.position = 'absolute';
      canvas.style.visibility = 'hidden';

      canvas.width = REGION_WIDTH;
      canvas.height = REGION_HEIGHT;

      this._canvasPool.push({canvas: canvas, region: null});
      this.viewport.appendChild(canvas);
    }

    canvas.style.width = this._screenRegionWidth + 'px';
    canvas.style.height = this._screenRegionHeight + 'px';
  }

  this._calculateRegions();
};

WorldRenderer.prototype._loadMetadata = function (metadata) {
  var spawn, size;
  switch (metadata.__version__) {
    case 1:
      spawn = metadata.playerStart;
      size = metadata.planet.size;
      break;
    case 2:
      spawn = metadata.playerStart;
      size = metadata.worldTemplate.size;
      break;
    default:
      throw new Error('Unsupported metadata version ' + metadata.__version__);
  }

  this.centerX = spawn[0];
  this.centerY = spawn[1];

  this._regionsX = size[0] / TILES_X;
  this._regionsY = size[1] / TILES_Y;

  this._loaded = true;
};
<|endoftext|>


<commit_before>/**
 * Spring constructor.
 * Creates a constraint between 2 particles.
 * @constructor
 * @param {Particle} p1 Particle to constrain to p2.
 * @param {Particle} p2 Particle to constrain to p1.
 * @param {Number} length Rest length of the spring.
 * @param {Number} stiffness Stiffness of the spring where 0 is elastic and 1 is rigid.
 */
NDP.Spring = function(p1, p2, length, stiffness) {
};

/**
 * Updates the positions of the two particles attached to the spring.
 * @param {Number} delta Time delta since last integration.
 * @param {Number} index Index of the spring within the system.
 * @return {Spring} Spring instance for chaining.
 */
NDP.Spring.prototype.update = function(delta, index) {
};
<commit_msg>:gb: Added error checking for compatible particle component sizes<commit_after>/**
 * Spring constructor.
 * Creates a constraint between 2 particles.
 * @constructor
 * @param {Particle} p1 Particle to constrain to p2.
 * @param {Particle} p2 Particle to constrain to p1.
 * @param {Number} length Rest length of the spring.
 * @param {Number} stiffness Stiffness of the spring where 0 is elastic and 1 is rigid.
 */
NDP.Spring = function(p1, p2, length, stiffness) {

  // Validate particle parameters.
  if (p1.dimensions !== p2.dimensions) {
    throw 'Spring: Particles must be of the same dimensions. P1['+p1.dimensions+'] P2['+p2.dimensions+']';
  }
};

/**
 * Updates the positions of the two particles attached to the spring.
 * @param {Number} delta Time delta since last integration.
 * @param {Number} index Index of the spring within the system.
 * @return {Spring} Spring instance for chaining.
 */
NDP.Spring.prototype.update = function(delta, index) {
};
<|endoftext|>


<commit_before>import _curry2 from './internal/_curry2';

/**
 * Creates a new object by recursively evolving a shallow copy of `object`,
 * according to the `transformation` functions. All non-primitive properties
 * are copied by reference.
 *
 * A `transformation` function will not be invoked if its corresponding key
 * does not exist in the evolved object.
 *
 * @func
 * @memberOf R
 * @since v0.9.0
 * @category Object
 * @sig {k: (v -> v)} -> {k: v} -> {k: v}
 * @param {Object} transformations The object specifying transformation functions to apply
 *        to the object.
 * @param {Object} object The object to be transformed.
 * @return {Object} The transformed object.
 * @example
 *
 *      const tomato  = {firstName: '  Tomato ', data: {elapsed: 100, remaining: 1400}, id:123};
 *      const transformations = {
 *        firstName: R.trim,
 *        lastName: R.trim, // Will not get invoked.
 *        data: {elapsed: R.add(1), remaining: R.add(-1)}
 *      };
 *      R.evolve(transformations, tomato); //=> {firstName: 'Tomato', data: {elapsed: 101, remaining: 1399}, id:123}
 */
var evolve = _curry2(function evolve(transformations, object) {
  var result = {};
  var transformation, key, type;
  for (key in object) {
    transformation = transformations[key];
    type = typeof transformation;
    result[key] = type === 'function'                 ? transformation(object[key])
                : transformation && type === 'object' ? evolve(transformation, object[key])
                                                      : object[key];
  }
  return result;
});
export default evolve;
<commit_msg>typo: extraneous space<commit_after>import _curry2 from './internal/_curry2';

/**
 * Creates a new object by recursively evolving a shallow copy of `object`,
 * according to the `transformation` functions. All non-primitive properties
 * are copied by reference.
 *
 * A `transformation` function will not be invoked if its corresponding key
 * does not exist in the evolved object.
 *
 * @func
 * @memberOf R
 * @since v0.9.0
 * @category Object
 * @sig {k: (v -> v)} -> {k: v} -> {k: v}
 * @param {Object} transformations The object specifying transformation functions to apply
 *        to the object.
 * @param {Object} object The object to be transformed.
 * @return {Object} The transformed object.
 * @example
 *
 *      const tomato = {firstName: '  Tomato ', data: {elapsed: 100, remaining: 1400}, id:123};
 *      const transformations = {
 *        firstName: R.trim,
 *        lastName: R.trim, // Will not get invoked.
 *        data: {elapsed: R.add(1), remaining: R.add(-1)}
 *      };
 *      R.evolve(transformations, tomato); //=> {firstName: 'Tomato', data: {elapsed: 101, remaining: 1399}, id:123}
 */
var evolve = _curry2(function evolve(transformations, object) {
  var result = {};
  var transformation, key, type;
  for (key in object) {
    transformation = transformations[key];
    type = typeof transformation;
    result[key] = type === 'function'                 ? transformation(object[key])
                : transformation && type === 'object' ? evolve(transformation, object[key])
                                                      : object[key];
  }
  return result;
});
export default evolve;
<|endoftext|>


<commit_before>/*global App, Backbone*/
/* Backbone View */
App.View.BaseView = Backbone.View.extend({

  className: 'page_view',
  render: function(){
    this.navbar = new App.View.NavbarView({title: this.model.get('title'), titleWidth: this.model.get('titleWidth')});
    this.$el.append(this.navbar.render());
    var template = this.getViewTemplate();
    this.$el.append(template(this.model.toJSON()));
    return this.$el;
  },

  dataError: function(msg){
    this.$el.find('.response_content').removeClass('alert-success').addClass('alert').addClass('alert-danger').html('Ops, something went wrong (' + msg+ '). Please try again later.');
  },

  dataReset: function(){
    this.$el.find('.response_content').removeClass('alert-success').removeClass('alert').removeClass('alert-danger').html('');
  },

  getViewTemplate : function(){
    var templateId = this.templateId;
    var source   = $("#" + templateId).html();
    var template = Handlebars.compile(source);
    return template;
  }

});<commit_msg>ops => oops<commit_after>/*global App, Backbone*/
/* Backbone View */
App.View.BaseView = Backbone.View.extend({

  className: 'page_view',
  render: function(){
    this.navbar = new App.View.NavbarView({title: this.model.get('title'), titleWidth: this.model.get('titleWidth')});
    this.$el.append(this.navbar.render());
    var template = this.getViewTemplate();
    this.$el.append(template(this.model.toJSON()));
    return this.$el;
  },

  dataError: function(msg){
    this.$el.find('.response_content').removeClass('alert-success').addClass('alert').addClass('alert-danger').html('Oops, something went wrong (' + msg+ '). Please try again later.');
  },

  dataReset: function(){
    this.$el.find('.response_content').removeClass('alert-success').removeClass('alert').removeClass('alert-danger').html('');
  },

  getViewTemplate : function(){
    var templateId = this.templateId;
    var source   = $("#" + templateId).html();
    var template = Handlebars.compile(source);
    return template;
  }

});
<|endoftext|>


<commit_before>/* NODE MODULES */
var zoneElements = require('../elements'),
    zoneQuadrants = require('../quadrants'),
    zoneNeighbors = require('../neighbors');

/** MODULE INTERFACE
 *@method {function} define - Defines the properties of a zone and attaches event emitters monitor their changes
 */
module.exports = {
    define: define
};

/*----------------------------------------------------------------------------*/

/** Defines the properties of a zone and attaches event emitters monitor their changes
 * @param {object} properties - Describes the properties of the zone to be created
 * @param {object} globalNamespace - Zonegrid's global namespace for inter-module communication
 * @param {object} localNamespace - Zone module's local namespace for inter-submodule communication
 * @returns {object} zoneProperties - Contains the properties of a zone in Object#defineProperties notation
 */
function define(properties, globalNamespace, localNamespace) {
    // Create an event emitter in the local namespace to report events on changes to properties
    var propertiesEvents = localNamespace.emitter();

    // Return the zoneProperties object
    return (function createZoneProperties() {
        var zoneProperties = {
            // ID of the zone
            id: {
                value: properties.id
            },
            // Name of the zone
            name: changeGetterSetter('string', 'name', 'name', properties.name),
            // Size of the zone
            size: {
                value: Object.create({}, {
                    x: changeGetterSetter('number', 'size', 'x', properties.size.x),
                    y: changeGetterSetter('number', 'size', 'y', properties.size.y),
                    z: changeGetterSetter('number', 'size', 'z', properties.size.z)
                })
            },
            // Zone limits
            limits: marginGetterSetter('limits', properties.limits),
            // Zone center coordinates
            coordinates: {
                value: Object.create({}, {
                    x: changeGetterSetter('number', 'coordinates', 'x', properties.coordinates.x),
                    y: changeGetterSetter('number', 'coordinates', 'y', properties.coordinates.y),
                    z: changeGetterSetter('number', 'coordinates', 'z', properties.coordinates.z)
                })
            },
            // Maximum range of visibility
            visibility: {
                value: Object.create({}, {
                    x: changeGetterSetter('number', 'visibility', 'x', properties.visibility.x),
                    y: changeGetterSetter('number', 'visibility', 'y', properties.visibility.y),
                    z: changeGetterSetter('number', 'visibility', 'z', properties.visibility.z)
                })
            },
            // Bookin and checkin margin size
            handover: changeGetterSetter('number', 'handover', 'handover', properties.handover),
            // Zone scope and handover limits
            margins: {
                value: Object.create({}, {
                    // Scopein and scopeout margins
                    scope: {
                        value: Object.create({}, {
                            inner: marginGetterSetter('innerScope', properties.margins.scope.inner),
                            outer: marginGetterSetter('outerScope', properties.margins.scope.outer)
                        })
                    },
                    // Bookin and checkin margins
                    handover: {
                        value: Object.create({}, {
                            bookin: marginGetterSetter('bookinMargin', properties.margins.handover.bookin),
                            checkin: marginGetterSetter('checkinMargin', properties.margins.handover.checkin)
                        })
                    }
                })
            }
        };
        // Quadrant system derived from the zone's margins
        var quadrants = zoneQuadrants.create(globalNamespace, localNamespace.emitter(),
                                             zoneProperties.margins.value);
        zoneProperties.quadrants = {
            value: quadrants
        };
        // Set of elements located in the zone
        zoneProperties.elements = zoneElements.createContainer(localNamespace.emitter(), quadrants);

        // Neighboring zones
        var neighbors = Object.create({}, zoneNeighbors.createRelationships(properties.neighbors, changeGetterSetter));
        zoneProperties._neighbors = {
            value: neighbors
        };
        zoneProperties.neighbors = {
            value: function () {
                var neighborLocation = Array.prototype.slice.call(arguments).sort();
                neighborLocation = neighborLocation.join('-');
                neighborLocation = neighborLocation.replace(new RegExp('lower', 'g'), 'l');
                neighborLocation = neighborLocation.replace(new RegExp('middle', 'g'), 'm');
                neighborLocation = neighborLocation.replace(new RegExp('higher', 'g'), 'h');
                neighborLocation = neighborLocation.replace(/\./g, '');
                neighborLocation = neighborLocation.split('-');

                var axes = {
                    x: 0,
                    y: 0,
                    z: 0
                };
                for (var index in neighborLocation) {
                    var segment = neighborLocation[index];
                    for (var axis in axes) {
                        if (segment[0] === axis) {
                            axes[axis] += 1;
                        }
                    }
                }
                for (var axis in axes) {
                    if (axes[axis] === 0) {
                        neighborLocation.push(axis + 'm');
                    }
                }
                neighborLocation = neighborLocation.sort().join('-');
                return neighbors[neighborLocation];
            }
        };

        // Servers
        zoneProperties.servers = {
            value: Object.create({}, {
                jampAssets: changeGetterSetter('object', 'server', 'jampAssets', properties.servers.jampAssets),
                webServer:  changeGetterSetter('object', 'server', 'webServer',  properties.servers.webServer),
                webSockets: changeGetterSetter('object', 'server', 'webSockets', properties.servers.webSockets)
            })
        };

        return zoneProperties;
    })();

    /*----------------------------------------------------------------------------*/

    /** Creates a getter/setter property that emits events when the property is set
     * @param {string} typeofChange - The name or type of the associated property
     * @param {string} propertyChanged - A string version of the associated property
     * @param {number/string} initialValue - The initial value of the property
     * @returns {object} - An object with #get and #set function properties
     */
    function changeGetterSetter(typeofProperty, typeofChange, propertyChanged, initialValue) {
        var value = initialValue;
        return {
            get: function () {
                return value;
            },
            set: function (newValue) {
                value = (typeof newValue === typeofProperty) ? newValue : value;
                propertiesEvents.emit(typeofChange + 'Change', {
                    property: propertyChanged,
                    value: newValue
                });
            }
        }
    }

    /** Creates a margin object containing x, y and z getter/setter properties the emit events when set
     * @param {string} typeofChange - The name or type of the associated margin property
     * @param {object} margins - An object containing x, y and z properties with 'lower' ahd 'higher' properties
     * @returns {object} - An object with x, y and z properties in Object#create notation
     */
    function marginGetterSetter(typeofChange, margins) {
        // Emit an event on changes to a margin property
            function emitMarginEvent(propertyChanged, side, value) {
                propertiesEvents.emit(typeofChange + 'Change', {
                    property: propertyChanged,
                    side: side,
                    value: value
                });
            }
        // Create a margin object with 'lower' and 'higher' getter/setter properties
        function margin(propertyChanged, margin) {
            return {
                value: Object.create({}, {
                    // Lower margin
                    lower: (function (value) {
                        return {
                            get: function () {
                                return value;
                            },
                            set: function (newValue) {
                                value = newValue;
                                emitMarginEvent(propertyChanged, 'lower', newValue);
                            }
                        };
                    })(margin.lower),
                    // Higher margin
                    higher: (function (value) {
                        return {
                            get: function () {
                                return value;
                            },
                            set: function (newValue) {
                                value = newValue;
                                emitMarginEvent(propertyChanged, 'higher', newValue);
                            }
                        };
                    })(margin.higher)
                })
            };
        }

        return {
            value: Object.create({}, {
                x: margin('x', margins.x),
                y: margin('y', margins.y),
                z: margin('z', margins.z)
            })
        }
    }
}<commit_msg>Added the scopein, bookin and checkin properties to the zone object in order to keep a high level view of all margin crossings<commit_after>/* NODE MODULES */
var zoneElements = require('../elements'),
    zoneQuadrants = require('../quadrants'),
    zoneNeighbors = require('../neighbors');

/** MODULE INTERFACE
 *@method {function} define - Defines the properties of a zone and attaches event emitters monitor their changes
 */
module.exports = {
    define: define
};

/*----------------------------------------------------------------------------*/

/** Defines the properties of a zone and attaches event emitters monitor their changes
 * @param {object} properties - Describes the properties of the zone to be created
 * @param {object} globalNamespace - Zonegrid's global namespace for inter-module communication
 * @param {object} localNamespace - Zone module's local namespace for inter-submodule communication
 * @returns {object} zoneProperties - Contains the properties of a zone in Object#defineProperties notation
 */
function define(properties, globalNamespace, localNamespace) {
    // Create an event emitter in the local namespace to report events on changes to properties
    var propertiesEvents = localNamespace.emitter();

    // Return the zoneProperties object
    return (function createZoneProperties() {
        var zoneProperties = {
            // ID of the zone
            id: {
                value: properties.id
            },
            // Name of the zone
            name: changeGetterSetter('string', 'name', 'name', properties.name),
            // Size of the zone
            size: {
                value: Object.create({}, {
                    x: changeGetterSetter('number', 'size', 'x', properties.size.x),
                    y: changeGetterSetter('number', 'size', 'y', properties.size.y),
                    z: changeGetterSetter('number', 'size', 'z', properties.size.z)
                })
            },
            // Zone limits
            limits: marginGetterSetter('limits', properties.limits),
            // Zone center coordinates
            coordinates: {
                value: Object.create({}, {
                    x: changeGetterSetter('number', 'coordinates', 'x', properties.coordinates.x),
                    y: changeGetterSetter('number', 'coordinates', 'y', properties.coordinates.y),
                    z: changeGetterSetter('number', 'coordinates', 'z', properties.coordinates.z)
                })
            },
            // Maximum range of visibility
            visibility: {
                value: Object.create({}, {
                    x: changeGetterSetter('number', 'visibility', 'x', properties.visibility.x),
                    y: changeGetterSetter('number', 'visibility', 'y', properties.visibility.y),
                    z: changeGetterSetter('number', 'visibility', 'z', properties.visibility.z)
                })
            },
            // Bookin and checkin margin size
            handover: changeGetterSetter('number', 'handover', 'handover', properties.handover),
            // Zone scope and handover limits
            margins: {
                value: Object.create({}, {
                    // Scopein and scopeout margins
                    scope: {
                        value: Object.create({}, {
                            inner: marginGetterSetter('innerScope', properties.margins.scope.inner),
                            outer: marginGetterSetter('outerScope', properties.margins.scope.outer)
                        })
                    },
                    // Bookin and checkin margins
                    handover: {
                        value: Object.create({}, {
                            bookin: marginGetterSetter('bookinMargin', properties.margins.handover.bookin),
                            checkin: marginGetterSetter('checkinMargin', properties.margins.handover.checkin)
                        })
                    }
                })
            }
        };
        // Quadrant system derived from the zone's margins
        var quadrants = zoneQuadrants.create(globalNamespace, localNamespace.emitter(),
                                             zoneProperties.margins.value);
        zoneProperties.quadrants = {
            value: quadrants
        };
        // Set of elements located in the zone
        zoneProperties.elements = zoneElements.createContainer(localNamespace.emitter(), quadrants);

        // Neighboring zones
        var neighbors = Object.create({}, zoneNeighbors.createRelationships(properties.neighbors, changeGetterSetter));
        zoneProperties._neighbors = {
            value: neighbors
        };
        zoneProperties.neighbors = {
            value: function () {
                var neighborLocation = Array.prototype.slice.call(arguments).sort();
                neighborLocation = neighborLocation.join('-');
                neighborLocation = neighborLocation.replace(new RegExp('lower', 'g'), 'l');
                neighborLocation = neighborLocation.replace(new RegExp('middle', 'g'), 'm');
                neighborLocation = neighborLocation.replace(new RegExp('higher', 'g'), 'h');
                neighborLocation = neighborLocation.replace(/\./g, '');
                neighborLocation = neighborLocation.split('-');

                var axes = {
                    x: 0,
                    y: 0,
                    z: 0
                };
                for (var index in neighborLocation) {
                    var segment = neighborLocation[index];
                    for (var axis in axes) {
                        if (segment[0] === axis) {
                            axes[axis] += 1;
                        }
                    }
                }
                for (var axis in axes) {
                    if (axes[axis] === 0) {
                        neighborLocation.push(axis + 'm');
                    }
                }
                neighborLocation = neighborLocation.sort().join('-');
                return neighbors[neighborLocation];
            }
        };

        // Servers
        zoneProperties.servers = {
            value: Object.create({}, {
                jampAssets: changeGetterSetter('object', 'server', 'jampAssets', properties.servers.jampAssets),
                webServer:  changeGetterSetter('object', 'server', 'webServer',  properties.servers.webServer),
                webSockets: changeGetterSetter('object', 'server', 'webSockets', properties.servers.webSockets)
            })
        };

        // Elements scoped and booked in neighboring zones
        zoneProperties.scopein = {
            value: {}
        };
        zoneProperties.bookin = {
            value: {}
        };
        zoneProperties.checkin = {
            value: {}
        };

        return zoneProperties;
    })();

    /*----------------------------------------------------------------------------*/

    /** Creates a getter/setter property that emits events when the property is set
     * @param {string} typeofChange - The name or type of the associated property
     * @param {string} propertyChanged - A string version of the associated property
     * @param {number/string} initialValue - The initial value of the property
     * @returns {object} - An object with #get and #set function properties
     */
    function changeGetterSetter(typeofProperty, typeofChange, propertyChanged, initialValue) {
        var value = initialValue;
        return {
            get: function () {
                return value;
            },
            set: function (newValue) {
                value = (typeof newValue === typeofProperty) ? newValue : value;
                propertiesEvents.emit(typeofChange + 'Change', {
                    property: propertyChanged,
                    value: newValue
                });
            }
        }
    }

    /** Creates a margin object containing x, y and z getter/setter properties the emit events when set
     * @param {string} typeofChange - The name or type of the associated margin property
     * @param {object} margins - An object containing x, y and z properties with 'lower' ahd 'higher' properties
     * @returns {object} - An object with x, y and z properties in Object#create notation
     */
    function marginGetterSetter(typeofChange, margins) {
        // Emit an event on changes to a margin property
            function emitMarginEvent(propertyChanged, side, value) {
                propertiesEvents.emit(typeofChange + 'Change', {
                    property: propertyChanged,
                    side: side,
                    value: value
                });
            }
        // Create a margin object with 'lower' and 'higher' getter/setter properties
        function margin(propertyChanged, margin) {
            return {
                value: Object.create({}, {
                    // Lower margin
                    lower: (function (value) {
                        return {
                            get: function () {
                                return value;
                            },
                            set: function (newValue) {
                                value = newValue;
                                emitMarginEvent(propertyChanged, 'lower', newValue);
                            }
                        };
                    })(margin.lower),
                    // Higher margin
                    higher: (function (value) {
                        return {
                            get: function () {
                                return value;
                            },
                            set: function (newValue) {
                                value = newValue;
                                emitMarginEvent(propertyChanged, 'higher', newValue);
                            }
                        };
                    })(margin.higher)
                })
            };
        }

        return {
            value: Object.create({}, {
                x: margin('x', margins.x),
                y: margin('y', margins.y),
                z: margin('z', margins.z)
            })
        }
    }
}<|endoftext|>


<commit_before>/* global Sphere */
/* global Flickr */

var Page = (function() {

    /**
     * popups
     */

    var popups = function(sphere){

        var popupCallback = function(e){
            e.preventDefault();

            var id = e.target.getAttribute('href').substring(1); //#
            var src = document.getElementById(id);
            src.classList.toggle('active');
            if(id === 'SettingsForm'){
                // hard remove animation to reset rotated axi.
                if(src.classList.contains('active')){
                    sphere.cache.set('animation', sphere.state.animation);
                    sphere.sphereAnimation(null);
                }else{
                    sphere.sphereAnimation(sphere.cache.get('animation'));
                }
            }
        };

        var triggers = document.querySelectorAll('.js-popup-trigger');
        for(var i = 0; i < triggers.length; i++){
            triggers[i].addEventListener('click', popupCallback);
        }
    };

    /**
     * update sidebar form
     */

    var updateForms = function(sphere){
        var form = document.getElementById('SettingsForm');
        var nodes = form.querySelectorAll('[name]');
        var state = sphere.state;
        var output;
        for(var i = 0; i < nodes.length; i++){
            if(sphere.state.hasOwnProperty(nodes[i].name)){
                nodes[i].value = state[nodes[i].name];
                output = document.querySelector('output[for=' + nodes[i].name + ']');
                if(output){
                    output.textContent = state[nodes[i].name];
                }
            }
        }

        document.getElementById('json').textContent = JSON.stringify(state, false, 4);
    };

    /**
     * rotate controls
     */

    var rotateControls = function(sphere){
        var els = document.querySelectorAll('.rotate');
        var eventCallback = function(e){
            e.preventDefault();

            var val = sphere.state[e.target.dataset.name] + parseInt(e.target.dataset.val, 10);
            sphere.sphereTransforms(e.target.dataset.name, val);

            updateForms(sphere);
        };

        for(var i = 0; i < els.length; i++){
            els[i].addEventListener('click', eventCallback, false);
        }

    };

    /**
     * sidebarForm
     */

    var sidebarForm = function(sphere){
        var els = document.querySelectorAll('.change');
        var eventCallback = function(e){
            var vals = {};
            var val;
            var method = e.target.dataset.method || 'updateState';

            switch (method){
                case 'updateState':
                    vals[e.target.name] = e.target.value;
                    sphere.updateState(vals);
                break;
                case 'sphereTransforms':
                    val = parseInt(e.target.value, 10);
                    if(isNaN(val)){
                        return false;
                    }
                    sphere.sphereTransforms(e.target.name,  val);
                break;
                default:
                    //nothing
            }
            updateForms(sphere);
        };

        for(var i = 0; i < els.length; i++){
            els[i].addEventListener('change', eventCallback, false);
        }
    };

    var columnControls = function(sphere){

        var els = document.querySelectorAll('.action');
        var eventCallback = function(e){
            e.preventDefault();

            var action = this.name || this.dataset.name || false;
            var value = this.value || this.dataset.val || false;
            var node;

            switch(action){
                case 'reset':
                    sphere.reset();
                    updateForms(sphere);
                break;
                case 'sphereClass':
                    sphere.sphereClass(value);
                break;
                case 'html':
                    sphere.columnContent(this.innerHTML);
                    sphere.sphereClass('transparent');
                    sphere.centreContent(null);
                break;
                case 'words':
                    var words = value.split(' ');
                    for(i = 0; i < sphere.nodes.columns.length; i++){
                        node = document.createElement('div');
                        node.className = 'text-center text';
                        node.textContent =  (typeof words[i] !== 'undefined' ) ? words[i] : '';
                        sphere.columnContent(node, i);
                    }
                    sphere.centreContent(null);
                    sphere.sphereClass('transparent');
                break;
                case 'flickr':
                    flickrSphere(sphere);
                break;
            }
        };

        for(var i = 0; i < els.length; i++){
            els[i].addEventListener('click', eventCallback, false);
        }
    };

    var flickrSphere = function(sphere){
        if(typeof window.Flickr === 'undefined'){
            return false;
        }

        sphere.centreContent('');
        sphere.sphereClass('transparent');
        sphere.columnContent('');

        var items = [];

        var attachEvents = function(sphere, node){
            var start = function(){
                sphere.sphereAnimation('stop');
            };

            var end = function(){
                sphere.sphereAnimation('play');
            };

            var click = function(){
            };

            node.addEventListener('mouseenter', start, false);
            node.addEventListener('touchstart', start, false);
            node.addEventListener('mouseleave', end, false);
            node.addEventListener('touchend', end, false);
            node.addEventListener('click', click, false);
        };

        var attach = function(item, index){

            var figure = document.createElement('figure');
            figure.className = 'flickr-feed-item';
            var img = new Image();
            figure.appendChild(img);

            img.src = item.getImage();
            img.onload = function(){
                sphere.columnContent(figure, index);
                attachEvents(sphere, sphere.nodes.columns[index]);
            };

        };

        var build = function(){
            for(var i = 0; i < sphere.nodes.columns.length; i++){
                attach(items[i], i);
            }

        };

        var feed = function(){
            Flickr.Feed().Photos().ready(function(data){
                items = items.concat(data.items);
                if(items.length < sphere.nodes.columns.length){
                    feed();
                    return;
                }
                build();
            });
        };

        feed();
    };

    return {
        Init: {
            popups: popups,
            sidebarForm: sidebarForm,
            rotateControls: rotateControls,
            columnControls: columnControls,
        },
        updateForms: updateForms,
        flickrSphere: flickrSphere
    };

}());

document.addEventListener('DOMContentLoaded', function() {

    /**
     * Init Sphere
     */

    var sphere = new Sphere(document.getElementById('Draw3dSphere'), {sphereClass: 'circles'});
    //sphere.coordinates();
    sphere.centreContent('
Css Sphere
');

    // add some content to sphere
    var cols = sphere.state.columns - 1;
    var content = document.querySelectorAll('.sphere-init-content');
    for(var i = 0; i < content.length; i++){
        sphere.columnContent(content[i], cols - i);
    }

    /**
     * init Page
     */

    Page.Init.popups(sphere);
    Page.Init.sidebarForm(sphere);
    Page.Init.rotateControls(sphere);
    Page.Init.columnControls(sphere);

    Page.updateForms(sphere);
});

window.addEventListener('resize', function(){
    //@todo
}, true);
<commit_msg>toggle animation, pause on rotate<commit_after>/* global Sphere */
/* global Flickr */

var Page = (function() {

    var toggleAnimation = function(sphere){
        // hard remove animation to reset rotated axi.
        if(sphere.state.animation){
            sphere.cache.set('animation', sphere.state.animation);
            sphere.sphereAnimation(null);
        }else{
            sphere.sphereAnimation(sphere.cache.get('animation'));
        }
    };

    /**
     * popups
     */

    var popups = function(sphere){

        var popupCallback = function(e){
            e.preventDefault();

            var id = e.target.getAttribute('href').substring(1); //#
            var src = document.getElementById(id);
            src.classList.toggle('active');
            if(id === 'SettingsForm'){
                toggleAnimation(sphere);
            }
        };

        var triggers = document.querySelectorAll('.js-popup-trigger');
        for(var i = 0; i < triggers.length; i++){
            triggers[i].addEventListener('click', popupCallback);
        }
    };

    /**
     * update sidebar form
     */

    var updateForms = function(sphere){
        var form = document.getElementById('SettingsForm');
        var nodes = form.querySelectorAll('[name]');
        var state = sphere.state;
        var output;
        for(var i = 0; i < nodes.length; i++){
            if(sphere.state.hasOwnProperty(nodes[i].name)){
                nodes[i].value = state[nodes[i].name];
                output = document.querySelector('output[for=' + nodes[i].name + ']');
                if(output){
                    output.textContent = state[nodes[i].name];
                }
            }
        }

        document.getElementById('json').textContent = JSON.stringify(state, false, 4);
    };

    /**
     * rotate controls
     */

    var rotateControls = function(sphere){
        var els = document.querySelectorAll('.rotate');
        var eventCallback = function(e){
            e.preventDefault();

            sphere.sphereAnimation('stop');
            var val = sphere.state[e.target.dataset.name] + parseInt(e.target.dataset.val, 10);
            sphere.sphereTransforms(e.target.dataset.name, val);

            updateForms(sphere);
        };

        for(var i = 0; i < els.length; i++){
            els[i].addEventListener('click', eventCallback, false);
        }

    };

    /**
     * sidebarForm
     */

    var sidebarForm = function(sphere){
        var els = document.querySelectorAll('.change');
        var eventCallback = function(e){
            var vals = {};
            var val;
            var method = e.target.dataset.method || 'updateState';

            switch (method){
                case 'updateState':
                    vals[e.target.name] = e.target.value;
                    sphere.updateState(vals);
                break;
                case 'sphereTransforms':
                    val = parseInt(e.target.value, 10);
                    if(isNaN(val)){
                        return false;
                    }
                    sphere.sphereTransforms(e.target.name,  val);
                break;
                default:
                    //nothing
            }
            updateForms(sphere);
        };

        for(var i = 0; i < els.length; i++){
            els[i].addEventListener('change', eventCallback, false);
        }
    };

    var columnControls = function(sphere){

        var els = document.querySelectorAll('.action');
        var eventCallback = function(e){
            e.preventDefault();

            var action = this.name || this.dataset.name || false;
            var value = this.value || this.dataset.val || false;
            var node;

            switch(action){
                case 'reset':
                    sphere.reset();
                    updateForms(sphere);
                break;
                case 'sphereClass':
                    sphere.sphereClass(value);
                break;
                case 'html':
                    sphere.columnContent(this.innerHTML);
                    sphere.sphereClass('transparent');
                    sphere.centreContent(null);
                break;
                case 'words':
                    var words = value.split(' ');
                    for(i = 0; i < sphere.nodes.columns.length; i++){
                        node = document.createElement('div');
                        node.className = 'text-center text';
                        node.textContent =  (typeof words[i] !== 'undefined' ) ? words[i] : '';
                        sphere.columnContent(node, i);
                    }
                    sphere.centreContent(null);
                    sphere.sphereClass('transparent');
                break;
                case 'flickr':
                    flickrSphere(sphere);
                break;
            }
        };

        for(var i = 0; i < els.length; i++){
            els[i].addEventListener('click', eventCallback, false);
        }
    };

    var flickrSphere = function(sphere){
        if(typeof window.Flickr === 'undefined'){
            return false;
        }

        sphere.centreContent('');
        sphere.sphereClass('transparent');
        sphere.columnContent('');

        var items = [];

        var attachEvents = function(sphere, node){
            var start = function(){
                sphere.sphereAnimation('stop');
            };

            var end = function(){
                sphere.sphereAnimation('play');
            };

            var click = function(){
            };

            node.addEventListener('mouseenter', start, false);
            node.addEventListener('touchstart', start, false);
            node.addEventListener('mouseleave', end, false);
            node.addEventListener('touchend', end, false);
            node.addEventListener('click', click, false);
        };

        var attach = function(item, index){

            var figure = document.createElement('figure');
            figure.className = 'flickr-feed-item';
            var img = new Image();
            figure.appendChild(img);

            img.src = item.getImage();
            img.onload = function(){
                sphere.columnContent(figure, index);
                attachEvents(sphere, sphere.nodes.columns[index]);
            };

        };

        var build = function(){
            for(var i = 0; i < sphere.nodes.columns.length; i++){
                attach(items[i], i);
            }

        };

        var feed = function(){
            Flickr.Feed().Photos().ready(function(data){
                items = items.concat(data.items);
                if(items.length < sphere.nodes.columns.length){
                    feed();
                    return;
                }
                build();
            });
        };

        feed();
    };

    return {
        Init: {
            popups: popups,
            sidebarForm: sidebarForm,
            rotateControls: rotateControls,
            columnControls: columnControls,
        },
        updateForms: updateForms,
        flickrSphere: flickrSphere
    };

}());

document.addEventListener('DOMContentLoaded', function() {

    /**
     * Init Sphere
     */

    var sphere = new Sphere(document.getElementById('Draw3dSphere'), {sphereClass: 'circles'});
    //sphere.coordinates();
    sphere.centreContent('
Css Sphere
');

    // add some content to sphere
    var cols = sphere.state.columns - 1;
    var content = document.querySelectorAll('.sphere-init-content');
    for(var i = 0; i < content.length; i++){
        sphere.columnContent(content[i], cols - i);
    }

    /**
     * init Page
     */

    Page.Init.popups(sphere);
    Page.Init.sidebarForm(sphere);
    Page.Init.rotateControls(sphere);
    Page.Init.columnControls(sphere);

    Page.updateForms(sphere);
});

window.addEventListener('resize', function(){
    //@todo
}, true);
<|endoftext|>


<commit_before>import React from 'react';
import clsx from 'clsx';
import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';
import { withStyles } from '@material-ui/core/styles';
import List from '@material-ui/core/List';
import Drawer from '@material-ui/core/Drawer';
import SwipeableDrawer from '@material-ui/core/SwipeableDrawer';
import Divider from '@material-ui/core/Divider';
import Hidden from '@material-ui/core/Hidden';
import Box from '@material-ui/core/Box';
import DiamondSponsors from 'docs/src/modules/components/DiamondSponsors';
import AppDrawerNavItem from 'docs/src/modules/components/AppDrawerNavItem';
import Link from 'docs/src/modules/components/Link';
import { pageToTitleI18n } from 'docs/src/modules/utils/helpers';
import PageContext from 'docs/src/modules/components/PageContext';

let savedScrollTop = null;
function PersistScroll(props) {
  const { children } = props;
  const rootRef = React.useRef();

  React.useEffect(() => {
    const parent = rootRef.current ? rootRef.current.parentElement : null;
    const activeElement = document.querySelector('.drawer-active');

    if (!parent || !activeElement || !activeElement.scrollIntoView) {
      return undefined;
    }

    const activeBox = activeElement.getBoundingClientRect();

    if (savedScrollTop === null || activeBox.top - savedScrollTop < 0) {
      // Center the selected item in the list container.
      activeElement.scrollIntoView();
      // Fix a Chrome issue, reset the tabbable ring back to the top of the document.
      document.body.scrollIntoView();
    } else {
      parent.scrollTop = savedScrollTop;
    }

    return () => {
      savedScrollTop = parent.scrollTop;
    };
  }, []);

  return
{children}
;
}

PersistScroll.propTypes = {
  children: PropTypes.node,
};

const styles = (theme) => ({
  paper: {
    width: 240,
    backgroundColor: theme.palette.background.level1,
  },
  title: {
    color: theme.palette.text.secondary,
    marginBottom: theme.spacing(0.5),
    '&:hover': {
      color: theme.palette.primary.main,
    },
  },
  // https://github.com/philipwalton/flexbugs#3-min-height-on-a-flex-container-wont-apply-to-its-flex-items
  toolbarIe11: {
    display: 'flex',
  },
  toolbar: {
    ...theme.mixins.toolbar,
    paddingLeft: theme.spacing(3),
    display: 'flex',
    flexGrow: 1,
    flexDirection: 'column',
    alignItems: 'flex-start',
    justifyContent: 'center',
  },
});

function renderNavItems(options) {
  const { pages, ...params } = options;

  return (
    <List>
      {pages.reduce(
        // eslint-disable-next-line no-use-before-define
        (items, page) => reduceChildRoutes({ items, page, ...params }),
        [],
      )}
    </List>
  );
}

function reduceChildRoutes({ props, activePage, items, page, depth, t }) {
  if (page.displayNav === false) {
    return items;
  }

  if (page.children && page.children.length > 1) {
    const title = pageToTitleI18n(page, t);
    const topLevel = activePage ? activePage.pathname.indexOf(`${page.pathname}/`) === 0 : false;

    items.push(
      <AppDrawerNavItem
        linkProps={page.linkProps}
        depth={depth}
        key={title}
        topLevel={topLevel && !page.subheader}
        openImmediately={topLevel || Boolean(page.subheader)}
        title={title}
      >
        {renderNavItems({ props, pages: page.children, activePage, depth: depth + 1, t })}
      </AppDrawerNavItem>,
    );
  } else {
    const title = pageToTitleI18n(page, t);
    page = page.children && page.children.length === 1 ? page.children[0] : page;

    items.push(
      <AppDrawerNavItem
        linkProps={page.linkProps}
        depth={depth}
        key={title}
        title={title}
        href={page.pathname}
        onClick={props.onClose}
      />,
    );
  }

  return items;
}

// iOS is hosted on high-end devices. We can enable the backdrop transition without
// dropping frames. The performance will be good enough.
// So: <SwipeableDrawer disableBackdropTransition={false} />
const iOS = process.browser && /iPad|iPhone|iPod/.test(navigator.userAgent);

function AppDrawer(props) {
  const { classes, className, disablePermanent, mobileOpen, onClose, onOpen } = props;
  const { activePage, pages } = React.useContext(PageContext);
  const t = useSelector((state) => state.options.t);

  const drawer = (
    <PersistScroll>

          <Link className={classes.title} href="/" onClick={onClose} variant="h6" color="inherit">
            Material-UI
          </Link>
          {process.env.LIB_VERSION ? (
            <Link
              color="textSecondary"
              variant="caption"
              href="https://material-ui.com/versions/"
              onClick={onClose}
            >
              {`v${process.env.LIB_VERSION}`}
            </Link>
          ) : null}

      <Divider />
      <Box mx={3} my={2}>
        <DiamondSponsors />
      </Box>
      {renderNavItems({ props, pages, activePage, depth: 0, t })}
    </PersistScroll>
  );

  return (

      <Hidden lgUp={!disablePermanent} implementation="js">
        <SwipeableDrawer
          classes={{
            paper: clsx(classes.paper, 'algolia-drawer'),
          }}
          disableBackdropTransition={!iOS}
          variant="temporary"
          open={mobileOpen}
          onOpen={onOpen}
          onClose={onClose}
          ModalProps={{
            keepMounted: true,
          }}
        >
          {drawer}
        </SwipeableDrawer>
      </Hidden>
      {disablePermanent ? null : (
        <Hidden mdDown implementation="css">
          <Drawer
            classes={{
              paper: classes.paper,
            }}
            variant="permanent"
            open
          >
            {drawer}
          </Drawer>
        </Hidden>
      )}

  );
}

AppDrawer.propTypes = {
  classes: PropTypes.object.isRequired,
  className: PropTypes.string,
  disablePermanent: PropTypes.bool.isRequired,
  mobileOpen: PropTypes.bool.isRequired,
  onClose: PropTypes.func.isRequired,
  onOpen: PropTypes.func.isRequired,
};

export default withStyles(styles)(AppDrawer);
<commit_msg>[docs] Add missing spot do DiamondSponsors (#20958)<commit_after>import React from 'react';
import clsx from 'clsx';
import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';
import { withStyles } from '@material-ui/core/styles';
import List from '@material-ui/core/List';
import Drawer from '@material-ui/core/Drawer';
import SwipeableDrawer from '@material-ui/core/SwipeableDrawer';
import Divider from '@material-ui/core/Divider';
import Hidden from '@material-ui/core/Hidden';
import Box from '@material-ui/core/Box';
import DiamondSponsors from 'docs/src/modules/components/DiamondSponsors';
import AppDrawerNavItem from 'docs/src/modules/components/AppDrawerNavItem';
import Link from 'docs/src/modules/components/Link';
import { pageToTitleI18n } from 'docs/src/modules/utils/helpers';
import PageContext from 'docs/src/modules/components/PageContext';

let savedScrollTop = null;
function PersistScroll(props) {
  const { children } = props;
  const rootRef = React.useRef();

  React.useEffect(() => {
    const parent = rootRef.current ? rootRef.current.parentElement : null;
    const activeElement = document.querySelector('.drawer-active');

    if (!parent || !activeElement || !activeElement.scrollIntoView) {
      return undefined;
    }

    const activeBox = activeElement.getBoundingClientRect();

    if (savedScrollTop === null || activeBox.top - savedScrollTop < 0) {
      // Center the selected item in the list container.
      activeElement.scrollIntoView();
      // Fix a Chrome issue, reset the tabbable ring back to the top of the document.
      document.body.scrollIntoView();
    } else {
      parent.scrollTop = savedScrollTop;
    }

    return () => {
      savedScrollTop = parent.scrollTop;
    };
  }, []);

  return
{children}
;
}

PersistScroll.propTypes = {
  children: PropTypes.node,
};

const styles = (theme) => ({
  paper: {
    width: 240,
    backgroundColor: theme.palette.background.level1,
  },
  title: {
    color: theme.palette.text.secondary,
    marginBottom: theme.spacing(0.5),
    '&:hover': {
      color: theme.palette.primary.main,
    },
  },
  // https://github.com/philipwalton/flexbugs#3-min-height-on-a-flex-container-wont-apply-to-its-flex-items
  toolbarIe11: {
    display: 'flex',
  },
  toolbar: {
    ...theme.mixins.toolbar,
    paddingLeft: theme.spacing(3),
    display: 'flex',
    flexGrow: 1,
    flexDirection: 'column',
    alignItems: 'flex-start',
    justifyContent: 'center',
  },
});

function renderNavItems(options) {
  const { pages, ...params } = options;

  return (
    <List>
      {pages.reduce(
        // eslint-disable-next-line no-use-before-define
        (items, page) => reduceChildRoutes({ items, page, ...params }),
        [],
      )}
    </List>
  );
}

function reduceChildRoutes({ props, activePage, items, page, depth, t }) {
  if (page.displayNav === false) {
    return items;
  }

  if (page.children && page.children.length > 1) {
    const title = pageToTitleI18n(page, t);
    const topLevel = activePage ? activePage.pathname.indexOf(`${page.pathname}/`) === 0 : false;

    items.push(
      <AppDrawerNavItem
        linkProps={page.linkProps}
        depth={depth}
        key={title}
        topLevel={topLevel && !page.subheader}
        openImmediately={topLevel || Boolean(page.subheader)}
        title={title}
      >
        {renderNavItems({ props, pages: page.children, activePage, depth: depth + 1, t })}
      </AppDrawerNavItem>,
    );
  } else {
    const title = pageToTitleI18n(page, t);
    page = page.children && page.children.length === 1 ? page.children[0] : page;

    items.push(
      <AppDrawerNavItem
        linkProps={page.linkProps}
        depth={depth}
        key={title}
        title={title}
        href={page.pathname}
        onClick={props.onClose}
      />,
    );
  }

  return items;
}

// iOS is hosted on high-end devices. We can enable the backdrop transition without
// dropping frames. The performance will be good enough.
// So: <SwipeableDrawer disableBackdropTransition={false} />
const iOS = process.browser && /iPad|iPhone|iPod/.test(navigator.userAgent);

function AppDrawer(props) {
  const { classes, className, disablePermanent, mobileOpen, onClose, onOpen } = props;
  const { activePage, pages } = React.useContext(PageContext);
  const t = useSelector((state) => state.options.t);

  const drawer = (
    <PersistScroll>

          <Link className={classes.title} href="/" onClick={onClose} variant="h6" color="inherit">
            Material-UI
          </Link>
          {process.env.LIB_VERSION ? (
            <Link
              color="textSecondary"
              variant="caption"
              href="https://material-ui.com/versions/"
              onClick={onClose}
            >
              {`v${process.env.LIB_VERSION}`}
            </Link>
          ) : null}

      <Divider />
      <Box mx={3} my={2}>
        <DiamondSponsors spot="drawer" />
      </Box>
      {renderNavItems({ props, pages, activePage, depth: 0, t })}
    </PersistScroll>
  );

  return (

      <Hidden lgUp={!disablePermanent} implementation="js">
        <SwipeableDrawer
          classes={{
            paper: clsx(classes.paper, 'algolia-drawer'),
          }}
          disableBackdropTransition={!iOS}
          variant="temporary"
          open={mobileOpen}
          onOpen={onOpen}
          onClose={onClose}
          ModalProps={{
            keepMounted: true,
          }}
        >
          {drawer}
        </SwipeableDrawer>
      </Hidden>
      {disablePermanent ? null : (
        <Hidden mdDown implementation="css">
          <Drawer
            classes={{
              paper: classes.paper,
            }}
            variant="permanent"
            open
          >
            {drawer}
          </Drawer>
        </Hidden>
      )}

  );
}

AppDrawer.propTypes = {
  classes: PropTypes.object.isRequired,
  className: PropTypes.string,
  disablePermanent: PropTypes.bool.isRequired,
  mobileOpen: PropTypes.bool.isRequired,
  onClose: PropTypes.func.isRequired,
  onOpen: PropTypes.func.isRequired,
};

export default withStyles(styles)(AppDrawer);
<|endoftext|>


<commit_before>// This file contains a package.json for the dependencies of the command-line
// tool.

// We put this in a JS file so that it can contain comments. It is processed
// into a package.json file by generate-dev-bundle.sh.

var packageJson = {
  name: "meteor-dev-bundle-tool",
  private: true,
  dependencies: {
    // Explicit dependency because we are replacing it with a bundled version
    // and we want to make sure there are no dependencies on a higher version
    npm: "6.4.1",
    pacote: "https://github.com/meteor/pacote/tarball/a3285854a68e4969d6c8abaa74407f7d113b178f",
    "node-gyp": "3.7.0",
    "node-pre-gyp": "0.10.3",
    "meteor-babel": "7.1.3",
    "meteor-promise": "0.8.6",
    promise: "8.0.1",
    reify: "0.17.3",
    fibers: "3.0.0",
    // So that Babel can emit require("@babel/runtime/helpers/...") calls.
    "@babel/runtime": "7.1.2",
    // For backwards compatibility with isopackets that still depend on
    // babel-runtime rather than @babel/runtime.
    "babel-runtime": "7.0.0-beta.3",
    // Not yet upgrading Underscore from 1.5.2 to 1.7.0 (which should be done
    // in the package too) because we should consider using lodash instead
    // (and there are backwards-incompatible changes either way).
    underscore: "1.5.2",
    "source-map-support": "https://github.com/meteor/node-source-map-support/tarball/1912478769d76e5df4c365e147f25896aee6375e",
    semver: "5.4.1",
    request: "2.88.0",
    uuid: "3.3.2",
    fstream: "https://github.com/meteor/fstream/tarball/cf4ea6c175355cec7bee38311e170d08c4078a5d",
    tar: "2.2.1",
    kexec: "3.0.0",
    "source-map": "0.5.3",
    chalk: "0.5.1",
    sqlite3: "3.1.8",
    netroute: "1.0.2",
    "http-proxy": "1.16.2",
    "wordwrap": "0.0.2",
    "moment": "2.20.1",
    "rimraf": "2.6.2",
    "glob": "7.1.2",
    ignore: "3.3.7",
    // XXX: When we update this, see if it fixes this Github issue:
    // https://github.com/jgm/CommonMark/issues/276 . If it does, remove the
    // workaround from the tool.
    "commonmark": "0.15.0",
    escope: "3.6.0",
    split2: "2.2.0",
    multipipe: "2.0.1",
    pathwatcher: "7.1.1",
    optimism: "0.6.8",
    'lru-cache': '4.1.3'
  }
};

if (process.platform === 'win32') {
  // Remove dependencies that do not work on Windows
  delete packageJson.dependencies.netroute;
  delete packageJson.dependencies.kexec;
}

process.stdout.write(JSON.stringify(packageJson, null, 2) + '\n');
<commit_msg>Update pathwatcher npm package to version 8.0.2.<commit_after>// This file contains a package.json for the dependencies of the command-line
// tool.

// We put this in a JS file so that it can contain comments. It is processed
// into a package.json file by generate-dev-bundle.sh.

var packageJson = {
  name: "meteor-dev-bundle-tool",
  private: true,
  dependencies: {
    // Explicit dependency because we are replacing it with a bundled version
    // and we want to make sure there are no dependencies on a higher version
    npm: "6.4.1",
    pacote: "https://github.com/meteor/pacote/tarball/a3285854a68e4969d6c8abaa74407f7d113b178f",
    "node-gyp": "3.7.0",
    "node-pre-gyp": "0.10.3",
    "meteor-babel": "7.1.3",
    "meteor-promise": "0.8.6",
    promise: "8.0.1",
    reify: "0.17.3",
    fibers: "3.0.0",
    // So that Babel can emit require("@babel/runtime/helpers/...") calls.
    "@babel/runtime": "7.1.2",
    // For backwards compatibility with isopackets that still depend on
    // babel-runtime rather than @babel/runtime.
    "babel-runtime": "7.0.0-beta.3",
    // Not yet upgrading Underscore from 1.5.2 to 1.7.0 (which should be done
    // in the package too) because we should consider using lodash instead
    // (and there are backwards-incompatible changes either way).
    underscore: "1.5.2",
    "source-map-support": "https://github.com/meteor/node-source-map-support/tarball/1912478769d76e5df4c365e147f25896aee6375e",
    semver: "5.4.1",
    request: "2.88.0",
    uuid: "3.3.2",
    fstream: "https://github.com/meteor/fstream/tarball/cf4ea6c175355cec7bee38311e170d08c4078a5d",
    tar: "2.2.1",
    kexec: "3.0.0",
    "source-map": "0.5.3",
    chalk: "0.5.1",
    sqlite3: "3.1.8",
    netroute: "1.0.2",
    "http-proxy": "1.16.2",
    "wordwrap": "0.0.2",
    "moment": "2.20.1",
    "rimraf": "2.6.2",
    "glob": "7.1.2",
    ignore: "3.3.7",
    // XXX: When we update this, see if it fixes this Github issue:
    // https://github.com/jgm/CommonMark/issues/276 . If it does, remove the
    // workaround from the tool.
    "commonmark": "0.15.0",
    escope: "3.6.0",
    split2: "2.2.0",
    multipipe: "2.0.1",
    pathwatcher: "8.0.2",
    optimism: "0.6.8",
    'lru-cache': '4.1.3'
  }
};

if (process.platform === 'win32') {
  // Remove dependencies that do not work on Windows
  delete packageJson.dependencies.netroute;
  delete packageJson.dependencies.kexec;
}

process.stdout.write(JSON.stringify(packageJson, null, 2) + '\n');
<|endoftext|>


<commit_before>'use strict';

var os = require('os'),
    fs = require('fs'),
    path = require('path');

function fsExistsSync(path) {
    try {
        fs.accessSync(path, fs.constants.F_OK);
    } catch (e) {
        return false;
    }
    return true;
}

fs.readdir('./src', function (err, files) {

    if (err) {
        console.log('read src error');
    } else {

        try {

            let indexArray = [];

            files.forEach(function (item) {

                var name = item;
                if (name.slice(0, 1) === '_') {
                    name = name.slice(1);
                }

                if (fsExistsSync('./src/' + item + '/' + name + '.scss')) {
                    indexArray.push('@import \'./' + item + '/' + name + '.scss\';');
                }

            });

            fs.writeFile(path.join(__dirname, '../src/components.scss'), indexArray.join(os.EOL), function (error) {
                if (error) {
                    throw error;
                }
                console.log('Generate Components Style Index Successfully!\n');
            });

        } catch (e) {
            console.error(e);
        }

    }

});<commit_msg>update components compile<commit_after>'use strict';

var os = require('os'),
    fs = require('fs'),
    path = require('path');

function fsExistsSync(path) {
    try {
        fs.accessSync(path, (fs.constants && fs.constants.F_OK) || fs.F_OK);
    } catch (e) {
        return false;
    }
    return true;
}

fs.readdir('./src', function (err, files) {

    if (err) {
        console.log('read src error');
    } else {

        try {

            let indexArray = [];

            files.forEach(function (item) {

                var name = item;
                if (name.slice(0, 1) === '_') {
                    name = name.slice(1);
                }

                if (fsExistsSync('./src/' + item + '/' + name + '.scss')) {
                    indexArray.push('@import \'./' + item + '/' + name + '.scss\';');
                }

            });

            fs.writeFile(path.join(__dirname, '../src/components.scss'), indexArray.join(os.EOL), function (error) {
                if (error) {
                    throw error;
                }
                console.log('Generate Components Style Index Successfully!\n');
            });

        } catch (e) {
            console.error(e);
        }

    }

});<|endoftext|>


<commit_before>var jsonEventUrl = 'http://pi2nos.ampr.org:1535/json';

var colors = {
  closed: "gray",
  open: "yellow",
  active: "red"
}

var myOptions = {
  center: new google.maps.LatLng(52.2368, 5.1729),
  zoom: 8,
  mapTypeId: google.maps.MapTypeId.ROADMAP,
  mapTypeControl: false
}

var receivers = {
	  "type": "FeatureCollection",
	  "features": [
		{
		  "type": "Feature",
		  "geometry": {
			"type": "Point",
			"coordinates": [5.1729, 52.2368]
		  },
		  "id":"Rx_Hilversum",
		  "properties": {
			"signal": "10",
			"squelch" : "closed"
		  }
		},
		{
		  "type": "Feature",
		  "geometry": {
			"type": "Point",
			"coordinates": [5.022297, 52.100284]
		  },
		  "id":"Rx_Utrecht",
		  "properties": {
			"signal": "10",
			"squelch" : "closed"
		  }
		},
        {
		  "type": "Feature",
		  "geometry": {
			"type": "Point",
			"coordinates": [3.924334, 51.653101]
		  },
		  "id":"Rx_Zierikzee",
		  "properties": {
			"signal": "10",
			"squelch" : "closed"
		  }
		},
        {
		  "type": "Feature",
		  "geometry": {
			"type": "Point",
			"coordinates": [4.929472, 52.408901]
		  },
		  "id":"Rx_Amsterdam",
		  "properties": {
			"signal": "10",
			"squelch" : "closed"
		  }
		},
        {
		  "type": "Feature",
		  "geometry": {
			"type": "Point",
			"coordinates": [6.022805, 52.239973]
		  },
		  "id":"Rx_Apeldoorn",
		  "properties": {
			"signal": "10",
			"squelch" : "closed"
		  }
		}
	  ]
	}

<commit_msg>Updated exact locations of receivers, thanks to Mischa for the KML file with the info.<commit_after>var jsonEventUrl = 'http://pi2nos.ampr.org:1535/json';

var colors = {
  closed: "gray",
  open: "yellow",
  active: "red"
}

var myOptions = {
  center: new google.maps.LatLng(52.2368, 5.1729),
  zoom: 8,
  mapTypeId: google.maps.MapTypeId.ROADMAP,
  mapTypeControl: false
}

"Rx_Hilversum,Rx_Utrecht,Rx_Amsterdam,Rx_Zierikzee,Rx_Apeldoorn,Dailyminutes"

var receivers = {
	  "type": "FeatureCollection",
	  "features": [
		{
		  "id":"Rx_Hilversum",
		  "type": "Feature",
		  "geometry": {
			"type": "Point",
			"coordinates": [5.164326284803233,52.24249959861779]
		  },
		  "properties": {
			"signal": "10",
			"squelch" : "closed"
		  }
		},
		{
		  "id":"Rx_Utrecht",
		  "type": "Feature",
		  "geometry": {
			"type": "Point",
			"coordinates": [5.053434032571373, 52.00992614369851]
		  },
		  "properties": {
			"signal": "10",
			"squelch" : "closed"
		  }
		},
        {
		  "id":"Rx_Zierikzee",
		  "type": "Feature",
		  "geometry": {
			"type": "Point",
			"coordinates": [3.931893379717417,51.64707776608346]
		  },
		  "properties": {
			"signal": "10",
			"squelch" : "closed"
		  }
		},
        {
		  "id":"Rx_Amsterdam",
		  "type": "Feature",
		  "geometry": {
			"type": "Point",
			"coordinates": [4.78980338760532,52.36033042450219]
		  },
		  "properties": {
			"signal": "10",
			"squelch" : "closed"
		  }
		},
        {
		  "type": "Feature",
		  "id":"Rx_Apeldoorn",
		  "geometry": {
			"type": "Point",
			"coordinates": [5.90613085257128,52.22481977473116]
		  },
		  "properties": {
			"signal": "10",
			"squelch" : "closed"
		  }
		}
		/*  Fake repeater used for John's "Daily Minutes" transmissions
		,{
		  "type": "Feature",
		  "geometry": {
			"type": "Point",
			"coordinates": [5.247611, 52.564620]
		  },
		  "id":"Dailyminutes",
		  "properties": {
			"signal": "10",
			"squelch" : "closed"
		  }
		} */
	  ]
	}

<|endoftext|>