<commit_before>// eslint-disable-next-line no-unused-vars
const viz = {
  scalingFactor: 2,
  circleRadius: 5,
  resizeTimer: null,
  minZoom: 0.5,
  maxZoom: 1.5,
  collisionRadius: 30,
  tickCount: 30,

  init(nodes, links) {
    const { width, height } = this.getDimensions();
    const { canvas, context } = this.createCanvas();

    this.canvas = canvas;
    this.context = context;
    this.tooltip = document.getElementById('tooltip');
    this.circleRadius = this.circleRadius * this.scalingFactor;
    this.collisionRadius = this.collisionRadius * this.scalingFactor;
    this.scale = (window.devicePixelRatio || 1) * this.scalingFactor;
    this.transform = d3.zoomIdentity;

    this.updateCanvas(width, height);
    this.draw(nodes, links);
    this.addListeners();
  },

  draw(nodes, links) {
    this.nodes = nodes;
    this.links = links;

    this.simulateForce();
    this.drawOnCanvas();
  },

  simulateForce() {
    if (!this.simulation) {
      this.simulation = d3.forceSimulation(this.nodes);
      this.registerSimulationForces();
    } else {
      this.simulation.nodes(this.nodes);
    }
    this.registerLinkForce();
    this.manualTick();
  },

  manualTick() {
    this.simulation.alphaTarget(0.1);
    for (let i = 0; i < this.tickCount; i++) {
      this.simulation.tick();
    }
    this.stopSimulation();
  },

  restartSimulation() {
    this.simulation.alphaTarget(0.1);
    this.simulation.restart();
  },

  stopSimulation() {
    this.simulation.alphaTarget(0);
    this.simulation.stop();
  },

  registerLinkForce() {
    const linkForce = d3.forceLink(this.links);
    linkForce.id((d) => d.hostname);
    this.simulation.force('link', linkForce);
  },

  registerSimulationForces() {
    const centerForce = d3.forceCenter(this.width / 2, this.height / 2);
    this.simulation.force('center', centerForce);

    const forceX = d3.forceX(this.width / 2);
    this.simulation.force('x', forceX);

    const forceY = d3.forceY(this.height / 2);
    this.simulation.force('y', forceY);

    const chargeForce = d3.forceManyBody();
    this.simulation.force('charge', chargeForce);

    const collisionForce = d3.forceCollide(this.collisionRadius);
    this.simulation.force('collide', collisionForce);
  },

  createCanvas() {
    const base = document.getElementById('visualization');
    const canvas = document.createElement('canvas');
    const context = canvas.getContext('2d');

    base.appendChild(canvas);

    return {
      canvas,
      context
    };
  },

  updateCanvas(width, height) {
    this.width = width;
    this.height = height;
    this.canvas.setAttribute('width', width * this.scale);
    this.canvas.setAttribute('height', height * this.scale);
    this.canvas.style.width = `${width}px`;
    this.canvas.style.height = `${height}px`;
    this.context.scale(this.scale, this.scale);
  },

  getDimensions() {
    const element = document.body;
    const { width, height } = element.getBoundingClientRect();

    return {
      width,
      height
    };
  },

  drawOnCanvas() {
    this.context.clearRect(0, 0, this.width, this.height);
    this.context.save();
    this.context.translate(this.transform.x, this.transform.y);
    this.context.scale(this.transform.k, this.transform.k);
    this.drawLinks();
    this.drawNodes();
    this.context.restore();
  },

  drawNodes() {
    for (const node of this.nodes) {
      const x = node.fx || node.x;
      const y = node.fy || node.y;
      this.context.beginPath();
      this.context.moveTo(x, y);

      if (node.shadow) {
        this.drawShadow(x, y);
      }

      if (node.firstParty) {
        this.drawFirstParty(node);
      } else {
        this.drawThirdParty(node);
      }

      if (node.favicon) {
        this.drawFavicon(node.favicon, x, y);
      }

      this.context.fillStyle = 'white';
      this.context.closePath();
      this.context.fill();
    }
  },

  getSquare() {
    const side = Math.sqrt(this.circleRadius * this.circleRadius * 2);
    const offset = side * 0.5;

    return {
      side,
      offset
    };
  },

  drawFavicon(favicon, x, y) {
    const { side, offset } = this.getSquare();
    const img = new Image();
    img.src = favicon;
    img.onload = () => {
      this.context.drawImage(img,
        this.transform.applyX(x) - offset,
        this.transform.applyY(y) - offset,
        side,
        side);
    };
  },

  drawShadow(x, y) {
    this.context.beginPath();
    this.context.lineWidth = 6;
    this.context.shadowColor = 'white';
    this.context.strokeStyle = 'rgba(0,0,0,1)';
    this.context.shadowBlur = 15;
    this.context.shadowOffsetX = 0;
    this.context.shadowOffsetY = 0;
    this.context.arc(x, y, this.circleRadius + 5, 0, 2 * Math.PI);
    this.context.stroke();
    this.context.closePath();
  },

  drawFirstParty(node) {
    this.context.arc(node.x, node.y, this.circleRadius, 0, 2 * Math.PI);
  },

  drawThirdParty(node) {
    const deltaY = this.circleRadius / 2;
    const deltaX = deltaY * Math.sqrt(3);

    this.context.moveTo(node.x - deltaX, node.y + deltaY);
    this.context.lineTo(node.x, node.y - this.circleRadius);
    this.context.lineTo(node.x + deltaX, node.y + deltaY);
  },

  getTooltipPosition(x, y) {
    const tooltipArrowHeight = 20;
    const { right: canvasRight } = this.canvas.getBoundingClientRect();
    const {
      height: tooltipHeight,
      width: tooltipWidth
    } = this.tooltip.getBoundingClientRect();
    const top = y - tooltipHeight - this.circleRadius - tooltipArrowHeight;

    let left;
    if (x + tooltipWidth >= canvasRight) {
      left = x - tooltipWidth;
    } else {
      left = x - (tooltipWidth / 2);
    }

    return {
      left,
      top
    };
  },

  showTooltip(title, x, y) {
    this.tooltip.innerText = title;
    this.tooltip.style.display = 'block';

    const { left, top } = this.getTooltipPosition(x, y);
    this.tooltip.style['left'] = `${left}px`;
    this.tooltip.style['top'] = `${top}px`;
  },

  hideTooltip() {
    this.tooltip.style.display = 'none';
  },

  drawLinks() {
    this.context.beginPath();
    for (const d of this.links) {
      const sx = d.source.fx || d.source.x;
      const sy = d.source.fy || d.source.y;
      const tx = d.target.fx || d.target.x;
      const ty = d.target.fy || d.target.y;
      this.context.moveTo(sx, sy);
      this.context.lineTo(tx, ty);
    }
    this.context.closePath();
    this.context.strokeStyle = '#ccc';
    this.context.stroke();
  },

  isPointInsideCircle(x, y, cx, cy) {
    const dx = Math.abs(x - cx);
    const dy = Math.abs(y - cy);
    const d = dx * dx + dy * dy;
    const r = this.circleRadius;

    return d <= r * r;
  },

  getNodeAtCoordinates(x, y) {
    for (const node of this.nodes) {
      if (this.isPointInsideCircle(x, y, node.x, node.y)) {
        return node;
      }
    }
    return null;
  },

  getMousePosition(event) {
    const { left, top } = this.canvas.getBoundingClientRect();

    return {
      mouseX: event.clientX - left,
      mouseY: event.clientY - top
    };
  },

  addListeners() {
    this.addMouseMove();
    this.addWindowResize();
    this.addDrag();
    this.addZoom();
  },

  addMouseMove() {
    this.canvas.addEventListener('mousemove', (event) => {
      const { mouseX, mouseY } = this.getMousePosition(event);
      const [ invertX, invertY ] = this.transform.invert([mouseX, mouseY]);
      const node = this.getNodeAtCoordinates(invertX, invertY);

      if (node) {
        this.showTooltip(node.hostname, mouseX, mouseY);
      } else {
        this.hideTooltip();
      }
    });
  },

  addWindowResize() {
    window.addEventListener('resize', () => {
      clearTimeout(this.resizeTimer);
      this.resizeTimer = setTimeout(() => {
        this.resize();
      }, 250);
    });
  },

  resize() {
    this.canvas.style.width = 0;
    this.canvas.style.height = 0;

    const { width, height } = this.getDimensions('visualization');
    this.updateCanvas(width, height);
    this.draw(this.nodes, this.links);
  },

  addDrag() {
    const drag = d3.drag();
    drag.subject(() => this.dragSubject());
    drag.on('start', () => this.dragStart());
    drag.on('drag', () => this.drag());
    drag.on('end', () => this.dragEnd());

    d3.select(this.canvas)
      .call(drag);
  },

  dragSubject() {
    const x = this.transform.invertX(d3.event.x);
    const y = this.transform.invertY(d3.event.y);
    const node = this.getNodeAtCoordinates(x, y);

    return node;
  },

  dragStart() {
    if (!d3.event.active) {
      this.restartSimulation();
    }
    d3.event.subject.shadow = true;
    d3.event.subject.fx = d3.event.subject.x;
    d3.event.subject.fy = d3.event.subject.y;
  },

  drag() {
    d3.event.subject.fx = d3.event.x;
    d3.event.subject.fy = d3.event.y;

    this.hideTooltip();
    this.drawOnCanvas();
  },

  dragEnd() {
    if (!d3.event.active) {
      this.stopSimulation();
    }
    d3.event.subject.x = d3.event.subject.fx;
    d3.event.subject.y = d3.event.subject.fy;
    d3.event.subject.fx = null;
    d3.event.subject.fy = null;
    d3.event.subject.shadow = false;
  },

  addZoom() {
    const zoom = d3.zoom().scaleExtent([this.minZoom, this.maxZoom]);
    zoom.on('zoom', () => this.zoom());

    d3.select(this.canvas)
      .call(zoom);
  },

  zoom() {
    this.transform = d3.event.transform;
    this.drawOnCanvas();
  }
};
<commit_msg>Cache favicons and other fixes (#201)<commit_after>// eslint-disable-next-line no-unused-vars
const viz = {
  scalingFactor: 2,
  circleRadius: 5,
  resizeTimer: null,
  minZoom: 0.5,
  maxZoom: 1.5,
  collisionRadius: 30,
  tickCount: 30,
  canvasColor: 'white',

  init(nodes, links) {
    const { width, height } = this.getDimensions();
    const { canvas, context } = this.createCanvas();

    this.canvas = canvas;
    this.context = context;
    this.tooltip = document.getElementById('tooltip');
    this.circleRadius = this.circleRadius * this.scalingFactor;
    this.collisionRadius = this.collisionRadius * this.scalingFactor;
    this.scale = (window.devicePixelRatio || 1) * this.scalingFactor;
    this.transform = d3.zoomIdentity;

    this.updateCanvas(width, height);
    this.draw(nodes, links);
    this.addListeners();
  },

  draw(nodes, links) {
    this.nodes = nodes;
    this.links = links;

    this.simulateForce();
    this.drawOnCanvas();
  },

  simulateForce() {
    if (!this.simulation) {
      this.simulation = d3.forceSimulation(this.nodes);
      this.registerSimulationForces();
    } else {
      this.simulation.nodes(this.nodes);
    }
    this.registerLinkForce();
    this.manualTick();
  },

  manualTick() {
    this.simulation.alphaTarget(0.1);
    for (let i = 0; i < this.tickCount; i++) {
      this.simulation.tick();
    }
    this.stopSimulation();
  },

  restartSimulation() {
    this.simulation.alphaTarget(0.1);
    this.simulation.restart();
  },

  stopSimulation() {
    this.simulation.alphaTarget(0);
    this.simulation.stop();
  },

  registerLinkForce() {
    const linkForce = d3.forceLink(this.links);
    linkForce.id((d) => d.hostname);
    this.simulation.force('link', linkForce);
  },

  registerSimulationForces() {
    const centerForce = d3.forceCenter(this.width / 2, this.height / 2);
    this.simulation.force('center', centerForce);

    const forceX = d3.forceX(this.width / 2);
    this.simulation.force('x', forceX);

    const forceY = d3.forceY(this.height / 2);
    this.simulation.force('y', forceY);

    const chargeForce = d3.forceManyBody();
    this.simulation.force('charge', chargeForce);

    const collisionForce = d3.forceCollide(this.collisionRadius);
    this.simulation.force('collide', collisionForce);
  },

  createCanvas() {
    const base = document.getElementById('visualization');
    const canvas = document.createElement('canvas');
    const context = canvas.getContext('2d');

    base.appendChild(canvas);

    return {
      canvas,
      context
    };
  },

  updateCanvas(width, height) {
    this.width = width;
    this.height = height;
    this.canvas.setAttribute('width', width * this.scale);
    this.canvas.setAttribute('height', height * this.scale);
    this.canvas.style.width = `${width}px`;
    this.canvas.style.height = `${height}px`;
    this.context.scale(this.scale, this.scale);
  },

  getDimensions() {
    const element = document.body;
    const { width, height } = element.getBoundingClientRect();

    return {
      width,
      height
    };
  },

  drawOnCanvas() {
    this.context.clearRect(0, 0, this.width, this.height);
    this.context.save();
    this.context.translate(this.transform.x, this.transform.y);
    this.context.scale(this.transform.k, this.transform.k);
    this.drawLinks();
    this.drawNodes();
    this.context.restore();
  },

  drawNodes() {
    for (const node of this.nodes) {
      const x = node.fx || node.x;
      const y = node.fy || node.y;
      this.context.beginPath();
      this.context.moveTo(x, y);

      if (node.shadow) {
        this.drawShadow(x, y);
      }

      if (node.firstParty) {
        this.drawFirstParty(x, y);
      } else {
        this.drawThirdParty(x, y);
      }

      this.context.fillStyle = this.canvasColor;
      this.context.closePath();
      this.context.fill();

      if (node.favicon) {
        this.drawFavicon(node, x, y);
      }
    }
  },

  getSquare() {
    const side = Math.sqrt(this.circleRadius * this.circleRadius * 2);
    const offset = side * 0.5;

    return {
      side,
      offset
    };
  },

  convertURIToImageData(URI) {
    return new Promise((resolve, reject) => {
      if (!URI) {
        return reject();
      }

      const canvas = document.createElement('canvas'),
        context = canvas.getContext('2d'),
        side = this.getSquare().side,
        image = new Image();

      canvas.width = side * this.scale;
      canvas.height = side * this.scale;
      context.fillStyle = this.canvasColor;
      context.fillRect(0, 0, canvas.width, canvas.height);

      image.onload = () => {
        context.drawImage(image, 0, 0, canvas.width, canvas.height);
        return resolve(context.getImageData(0, 0, canvas.width, canvas.height));
      };
      image.src = URI;
    });
  },

  async drawFavicon(node, x, y) {
    const offset = this.getSquare().offset,
      tx = this.transform.applyX(x) - offset,
      ty = this.transform.applyY(y) - offset;

    if (!node.image) {
      node.image = await this.convertURIToImageData(node.favicon);
    }

    this.context.putImageData(node.image,
      tx * this.scale,
      ty * this.scale
    );
  },

  drawShadow(x, y) {
    this.context.beginPath();
    this.context.lineWidth = 2;
    this.context.shadowColor = this.canvasColor;
    this.context.strokeStyle = 'rgba(0, 0, 0, 1)';
    this.context.shadowBlur = 15;
    this.context.shadowOffsetX = 0;
    this.context.shadowOffsetY = 0;
    this.context.arc(x, y, this.circleRadius + 5, 0, 2 * Math.PI);
    this.context.stroke();
    this.context.closePath();
  },

  drawFirstParty(x, y) {
    this.context.arc(x, y, this.circleRadius, 0, 2 * Math.PI);
  },

  drawThirdParty(x, y) {
    const deltaY = this.circleRadius / 2;
    const deltaX = deltaY * Math.sqrt(3);

    this.context.moveTo(x - deltaX, y + deltaY);
    this.context.lineTo(x, y - this.circleRadius);
    this.context.lineTo(x + deltaX, y + deltaY);
  },

  getTooltipPosition(x, y) {
    const tooltipArrowHeight = 20;
    const { right: canvasRight } = this.canvas.getBoundingClientRect();
    const {
      height: tooltipHeight,
      width: tooltipWidth
    } = this.tooltip.getBoundingClientRect();
    const top = y - tooltipHeight - this.circleRadius - tooltipArrowHeight;

    let left;
    if (x + tooltipWidth >= canvasRight) {
      left = x - tooltipWidth;
    } else {
      left = x - (tooltipWidth / 2);
    }

    return {
      left,
      top
    };
  },

  showTooltip(title, x, y) {
    this.tooltip.innerText = title;
    this.tooltip.style.display = 'block';

    const { left, top } = this.getTooltipPosition(x, y);
    this.tooltip.style['left'] = `${left}px`;
    this.tooltip.style['top'] = `${top}px`;
  },

  hideTooltip() {
    this.tooltip.style.display = 'none';
  },

  drawLinks() {
    this.context.beginPath();
    for (const d of this.links) {
      const sx = d.source.fx || d.source.x;
      const sy = d.source.fy || d.source.y;
      const tx = d.target.fx || d.target.x;
      const ty = d.target.fy || d.target.y;
      this.context.moveTo(sx, sy);
      this.context.lineTo(tx, ty);
    }
    this.context.closePath();
    this.context.strokeStyle = '#ccc';
    this.context.stroke();
  },

  isPointInsideCircle(x, y, cx, cy) {
    const dx = Math.abs(x - cx);
    const dy = Math.abs(y - cy);
    const d = dx * dx + dy * dy;
    const r = this.circleRadius;

    return d <= r * r;
  },

  getNodeAtCoordinates(x, y) {
    for (const node of this.nodes) {
      if (this.isPointInsideCircle(x, y, node.x, node.y)) {
        return node;
      }
    }
    return null;
  },

  getMousePosition(event) {
    const { left, top } = this.canvas.getBoundingClientRect();

    return {
      mouseX: event.clientX - left,
      mouseY: event.clientY - top
    };
  },

  addListeners() {
    this.addMouseMove();
    this.addWindowResize();
    this.addDrag();
    this.addZoom();
  },

  addMouseMove() {
    this.canvas.addEventListener('mousemove', (event) => {
      const { mouseX, mouseY } = this.getMousePosition(event);
      const [ invertX, invertY ] = this.transform.invert([mouseX, mouseY]);
      const node = this.getNodeAtCoordinates(invertX, invertY);

      if (node) {
        this.showTooltip(node.hostname, mouseX, mouseY);
      } else {
        this.hideTooltip();
      }
    });
  },

  addWindowResize() {
    window.addEventListener('resize', () => {
      clearTimeout(this.resizeTimer);
      this.resizeTimer = setTimeout(() => {
        this.resize();
      }, 250);
    });
  },

  resize() {
    this.canvas.style.width = 0;
    this.canvas.style.height = 0;

    const { width, height } = this.getDimensions('visualization');
    this.updateCanvas(width, height);
    this.draw(this.nodes, this.links);
  },

  addDrag() {
    const drag = d3.drag();
    drag.subject(() => this.dragSubject());
    drag.on('start', () => this.dragStart());
    drag.on('drag', () => this.drag());
    drag.on('end', () => this.dragEnd());

    d3.select(this.canvas)
      .call(drag);
  },

  dragSubject() {
    const x = this.transform.invertX(d3.event.x);
    const y = this.transform.invertY(d3.event.y);
    return this.getNodeAtCoordinates(x, y);
  },

  dragStart() {
    if (!d3.event.active) {
      this.restartSimulation();
    }
    d3.event.subject.shadow = true;
    d3.event.subject.fx = d3.event.subject.x;
    d3.event.subject.fy = d3.event.subject.y;
  },

  drag() {
    d3.event.subject.fx = d3.event.x;
    d3.event.subject.fy = d3.event.y;

    this.hideTooltip();
    this.drawOnCanvas();
  },

  dragEnd() {
    if (!d3.event.active) {
      this.stopSimulation();
    }
    d3.event.subject.x = d3.event.subject.fx;
    d3.event.subject.y = d3.event.subject.fy;
    d3.event.subject.fx = null;
    d3.event.subject.fy = null;
    d3.event.subject.shadow = false;
  },

  addZoom() {
    const zoom = d3.zoom().scaleExtent([this.minZoom, this.maxZoom]);
    zoom.on('zoom', () => this.zoom());

    d3.select(this.canvas)
      .call(zoom);
  },

  zoom() {
    this.transform = d3.event.transform;
    this.drawOnCanvas();
  }
};
<|endoftext|>


<commit_before>import React from "react";
import _ from "lodash";

var DIRECTIONS = ["north", "east", "south", "west"];

class Players extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      playerDirections: props.playerStates.map(el => DIRECTIONS.indexOf(el.direction))
    };
  }

  componentWillReceiveProps(nextProps) {
    var playerDirections = this.state.playerDirections;
    var newPlayerDirections = nextProps.playerStates.map(el => DIRECTIONS.indexOf(el.direction));

    this.setState({
      playerDirections: newPlayerDirections.map((el, index) => {
        var diff = ((el + 4) % 4) - ((playerDirections[index] + 4) % 4);
        if (diff === 3) diff = -1;
        if (diff === -3) diff = 1;

        return playerDirections[index] + diff;
      })
    });
  }

  render() {
    var { playerDirections } = this.state;
    var { gridSize, playerStates, playerInstances } = this.props;

    var tileSize = 100 / gridSize;

    var playerRender = _.map(playerStates, (playerData, playerIndex) => {
      if (!playerData.isAlive) return null;

      var playerInfo = playerInstances[playerIndex].getInfo();

      return (

{playerInfo.name}

      );
    });

    return
{playerRender}
;
  }
}

export default Players;
<commit_msg>Rewrite Player.js to use hooks<commit_after>import React from "react";
import _ from "lodash";

var DIRECTIONS = ["north", "east", "south", "west"];

function Players(props) {
  const [playerDirections, setPlayerDirections] = React.useState(
    props.playerStates.map((el) => DIRECTIONS.indexOf(el.direction))
  );

  // every time that the player state changes we need to update the direction
  React.useEffect(() => {
    const newPlayerDirections = props.playerStates.map((el) => DIRECTIONS.indexOf(el.direction));

    setPlayerDirections(
      newPlayerDirections.map((el, index) => {
        let directionDifference = ((el + 4) % 4) - ((playerDirections[index] + 4) % 4);
        if (directionDifference === 3) directionDifference = -1;
        if (directionDifference === -3) directionDifference = 1;

        return playerDirections[index] + directionDifference;
      })
    );
  }, [props]);

  const { gridSize, playerStates, playerInstances } = props;

  const tileSize = 100 / gridSize;

  const playerRender = _.map(playerStates, (playerData, playerIndex) => {
    if (!playerData.isAlive) return null;

    const playerInfo = playerInstances[playerIndex].getInfo();

    return (

{playerInfo.name}

    );
  });

  return
{playerRender}
;
}

export default Players;
<|endoftext|>


<commit_before>/*
 * Copyright 2011 eBay Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var raptorPubsub = require('raptor-pubsub');
var ready = require('raptor-dom').ready;
var EMPTY_OBJ = {};
var Widget = require('./Widget');
var initWidgets = require('./init-widgets');

// Exports:
exports.getWidgetsContext = require('./WidgetsContext').getWidgetsContext;
exports.Widget = Widget;
exports.uniqueId = require('./uniqueId');
exports.ready = ready;
exports.onInitWidget = function(listener) {
    raptorPubsub.on('marko-widgets/initWidget', listener);
};
exports.attrs = function() {
    return EMPTY_OBJ;
};
exports.get = exports.forEl = function (id) {
    if (!id) {
        return null;
    }

    var node = typeof id === 'string' ? document.getElementById(id) : id;
    return (node && node.__widget) || null;
};
exports.initAllWidgets = function() {
    initWidgets.initServerRendered(true /* scan DOM */);
};

// Subscribe to DOM manipulate events to handle creating and destroying widgets
raptorPubsub
    .on('dom/beforeRemove', function(eventArgs) {
        var el = eventArgs.el;
        var widget = el.id ? require('./').get(el.id) : null;
        if (widget) {
            widget.destroy({
                removeNode: false,
                recursive: true
            });
        }
    })
    .on('raptor-renderer/renderedToDOM', function(eventArgs) {
        var context = eventArgs.context;
        var widgetsContext = context.attributes.widgets;
        if (widgetsContext) {
            widgetsContext.initWidgets();
        }
    });

window.$rwidgets = function(ids) {
    initWidgets.initServerRendered(ids);
};<commit_msg>Renamed forEl to widgetForEl<commit_after>/*
 * Copyright 2011 eBay Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var raptorPubsub = require('raptor-pubsub');
var ready = require('raptor-dom').ready;
var EMPTY_OBJ = {};
var Widget = require('./Widget');
var initWidgets = require('./init-widgets');

// Exports:
exports.getWidgetsContext = require('./WidgetsContext').getWidgetsContext;
exports.Widget = Widget;
exports.uniqueId = require('./uniqueId');
exports.ready = ready;
exports.onInitWidget = function(listener) {
    raptorPubsub.on('marko-widgets/initWidget', listener);
};
exports.attrs = function() {
    return EMPTY_OBJ;
};
exports.get = exports.widgetForEl = function (id) {
    if (!id) {
        return null;
    }

    var node = typeof id === 'string' ? document.getElementById(id) : id;
    return (node && node.__widget) || null;
};
exports.initAllWidgets = function() {
    initWidgets.initServerRendered(true /* scan DOM */);
};

// Subscribe to DOM manipulate events to handle creating and destroying widgets
raptorPubsub
    .on('dom/beforeRemove', function(eventArgs) {
        var el = eventArgs.el;
        var widget = el.id ? require('./').get(el.id) : null;
        if (widget) {
            widget.destroy({
                removeNode: false,
                recursive: true
            });
        }
    })
    .on('raptor-renderer/renderedToDOM', function(eventArgs) {
        var context = eventArgs.context;
        var widgetsContext = context.attributes.widgets;
        if (widgetsContext) {
            widgetsContext.initWidgets();
        }
    });

window.$rwidgets = function(ids) {
    initWidgets.initServerRendered(ids);
};<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
import $ from 'jquery';
import 'select2';
import shallowEqualFuzzy from 'shallow-equal-fuzzy';

export default class Select2 extends Component {
  static propTypes = {
    defaultValue: PropTypes.oneOfType([
      PropTypes.number,
      PropTypes.array,
      PropTypes.string,
    ]),
    value: PropTypes.oneOfType([
      PropTypes.number,
      PropTypes.array,
      PropTypes.string,
    ]),
    data: PropTypes.array,
    events: PropTypes.array,
    options: PropTypes.object,
    multiple: PropTypes.bool,
    onOpen: PropTypes.func,
    onClose: PropTypes.func,
    onSelect: PropTypes.func,
    onChange: PropTypes.func,
    onUnselect: PropTypes.func,
  };

  static defaultProps = {
    data: [],
    events: [
      ['change', 'onChange'],
      ['select2:open', 'onOpen'],
      ['select2:close', 'onClose'],
      ['select2:select', 'onSelect'],
      ['select2:unselect', 'onUnselect'],
    ],
    options: {},
    multiple: false,
  };

  constructor(props) {
    super(props);
    this.el = null;
  }

  componentDidMount() {
    this.initSelect2();
    this.props.events.forEach(event => {
      this.el.on(event[0], this.props[event[1]]);
    });
  }

  componentWillReceiveProps(nextProps) {
    if (this.el && nextProps.value !== this.props.value) {
      this.setValue(nextProps.value);
    }
  }

  componentDidUpdate(prevProps) {
    if (!shallowEqualFuzzy(prevProps.data, this.props.data)) {
      this.destroySelect2();
      this.initSelect2();
    }
  }

  componentWillUnmount() {
    this.props.events.forEach(event => {
      this.el.off(event[0], this.props[event[1]]);
    });
    this.destroySelect2();
  }

  setValue(value) {
    const elVal = this.el.val();
    if (!shallowEqualFuzzy(elVal, value)) {
      this.el.val(value).trigger('change');
    }
  }

  initSelect2() {
    if (this.el) { return; }
    this.el = $(ReactDOM.findDOMNode(this));
    this.el.select2(this.props.options);
    const { defaultValue, value } = this.props;
    if (defaultValue === (void 0) && value !== (void 0)) {
      this.setValue(value);
    }
  }

  destroySelect2() {
    if (!this.el) { return; }
    this.el.select2('destroy');
    this.el = null;
  }

  isObject(value) {
    const type = typeof value;
    return type === 'function' || (value && type === 'object') || false;
  }

  render() {
    const { data, value, ...params } = this.props;
    return (
      <select {...params}>
        {data.map((item, k) => {
          if (this.isObject(item)) {
            const { id, text, ...itemParams } = item;
            return (<option key={`option-${k}`} value={id} {...itemParams}>{text}</option>);
          }

          return (<option key={`option-${k}`} value={item}>{item}</option>);
        })}
      </select>
    );
  }
}
<commit_msg>Refactor Select2.js<commit_after>import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
import shallowEqualFuzzy from 'shallow-equal-fuzzy';
import $ from 'jquery';
import 'select2';

export default class Select2 extends Component {
  static propTypes = {
    defaultValue: PropTypes.oneOfType([
      PropTypes.number,
      PropTypes.array,
      PropTypes.string,
    ]),
    value: PropTypes.oneOfType([
      PropTypes.number,
      PropTypes.array,
      PropTypes.string,
    ]),
    data: PropTypes.array,
    events: PropTypes.array,
    options: PropTypes.object,
    multiple: PropTypes.bool,
    onOpen: PropTypes.func,
    onClose: PropTypes.func,
    onSelect: PropTypes.func,
    onChange: PropTypes.func,
    onUnselect: PropTypes.func,
  };

  static defaultProps = {
    data: [],
    events: [
      ['change', 'onChange'],
      ['select2:open', 'onOpen'],
      ['select2:close', 'onClose'],
      ['select2:select', 'onSelect'],
      ['select2:unselect', 'onUnselect'],
    ],
    options: {},
    multiple: false,
  };

  constructor(props) {
    super(props);
    this.el = null;
  }

  componentDidMount() {
    this.initSelect2();
  }

  componentWillReceiveProps(nextProps) {
    if (this.el && nextProps.value !== this.props.value) {
      this.setValue(nextProps.value);
    }
  }

  componentDidUpdate(prevProps) {
    if (!shallowEqualFuzzy(prevProps.data, this.props.data)) {
      this.destroySelect2(false);
      this.initSelect2(false);
    }
  }

  componentWillUnmount() {
    this.destroySelect2();
  }

  setValue(value) {
    const elVal = this.el.val();
    if (!shallowEqualFuzzy(elVal, value)) {
      this.el.val(value).trigger('change');
    }
  }

  initSelect2(withCallbacks = true) {
    if (this.el) { return; }
    const { defaultValue, value, options, events } = this.props;

    this.el = $(ReactDOM.findDOMNode(this));
    this.el.select2(options);

    if (withCallbacks) {
      events.forEach(event => {
        if (typeof this.props[event[1]] !== 'undefined') {
          this.el.on(event[0], this.props[event[1]]);
        }
      });
    }

    if (typeof defaultValue === 'undefined' && typeof value !== 'undefined') {
      this.setValue(value);
    }
  }

  destroySelect2(withCallbacks = true) {
    if (!this.el) { return; }

    if (withCallbacks) {
      this.props.events.forEach(event => {
        if (typeof this.props[event[1]] !== 'undefined') {
          this.el.off(event[0], this.props[event[1]]);
        }
      });
    }

    this.el.select2('destroy');
    this.el = null;
  }

  isObject(value) {
    const type = typeof value;
    return type === 'function' || (value && type === 'object') || false;
  }

  render() {
    const { data, value, ...params } = this.props;
    return (
      <select {...params}>
        {data.map((item, k) => {
          if (this.isObject(item)) {
            const { id, text, ...itemParams } = item;
            return (<option key={`option-${k}`} value={id} {...itemParams}>{text}</option>);
          }

          return (<option key={`option-${k}`} value={item}>{item}</option>);
        })}
      </select>
    );
  }
}
<|endoftext|>


<commit_before>// @flow

import React, { Component } from 'react';
import type { ComponentType } from 'react';
import { connect as reduxConnect } from 'react-redux';
import { bindActionCreators } from 'redux';
import isFunction from 'lodash/isFunction';
import isObject from 'lodash/isObject';
import merge from 'lodash/merge';
import each from 'lodash/each';
import reduce from 'lodash/reduce';
// import reactReduxFetchActions from '../actions';
import { getModel } from '../reducers/selectors';
// import container from '../container';
import capitalizeFirstLetter from '../utils/capitalizeFirstLetter';
import buildActionsFromMappings, {
  ensureResourceIsObject,
  validateResourceObject,
} from '../utils/buildActionsFromMappings';
import helpers from '../utils/helpers';
import type { reduxAction } from '../types';

// const defaultRequestType = 'get';

type Props = {
  dispatch(action: reduxAction): void,
  fetchData: Object,
};

type State = {
  dispatchFunctions?: Object,
}

type FuncOrArr = Function | Array<*>;
type OptionalFuncOrObj = Function | Object | null;

function getDisplayName(WrappedComponent: ComponentType<*>): string {
  return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}

function connect(
  mapPropsToRequestsToProps: FuncOrArr,
  componentMapStateToProps?: OptionalFuncOrObj = null,
  componentMapDispatchToProps?: OptionalFuncOrObj = null,
) {
  return function wrapWithReactReduxFetch(WrappedComponent: ComponentType<*>) {
    class ReactReduxFetch extends Component<Props, State> {
      constructor(props) {
        super(props);

        // if mapPropsToRequestsToProps is a function,
        // we can't cache our dispatch functions because they might depend on the props.
        // We could support this in the future by building the functions again when te props change.
        if (typeof mapPropsToRequestsToProps === 'function') {
          return;
        }

        this.state = {
          dispatchFunctions: this.actionsFromProps(props.dispatch, mapPropsToRequestsToProps),
        };
      }

      state = {};

      /**
       * @param {Object} fetchData The complete react-redux-fetch state leaf
       * @param {Array} mappings Array of objects with shape:
       *                {resource: ..., method: ..., request: ...}
       * @return {Object} all the resources the WrappedComponent requested
       */
      getFilteredFetchData = (fetchData, mappings) => {
        const data = {};

        each(mappings, (mapping) => {
          const resource = ensureResourceIsObject(mapping);
          validateResourceObject(resource);
          const resourceName = resource.name;

          data[`${resourceName}Fetch`] = fetchData[resourceName] || {};
        });

        return data;
      };

      /**
       * @param {Function} dispatch Redux dispatch function
       * @param {Array} mappings Array of objects with shape:
       *                {resource: ..., method: ..., request: ...}
       * @return {Object} functions for the WrappedComponent e.g.: 'dispatchUserFetch()'
       **/
      actionsFromProps = (dispatch, mappings: Array<*>): Object =>
        reduce(
          buildActionsFromMappings(mappings),
          (actions, actionCreator, key) =>
            Object.assign({}, actions, {
              [`dispatch${capitalizeFirstLetter(key)}`]: (...args) => {
                const action = actionCreator(...args);
                if (action) {
                  dispatch(action);
                }
              },
            }),
          {},
        );

      /**
       * If the value passed to connect() is a function,
       *    execute the function and pass the props + context
       * @param {Object} props React props
       * @param {Object} context React context
       * @return {Array} an array with request configurations
       **/
      buildMappings = (props: Props, context: Object): Array<*> => {
        const finalProps = props || this.props;
        const finalContext = context || this.context || {};

        return isFunction(mapPropsToRequestsToProps)
          ? // $FlowFixMe
            mapPropsToRequestsToProps(finalProps, finalContext)
          : // $FlowFixMe
            mapPropsToRequestsToProps;
      };

      render() {
        const { fetchData, ...other } = this.props;
        const { dispatchFunctions } = this.state;

        const mappings = this.buildMappings(this.props, this.context);
        const actions = dispatchFunctions || this.actionsFromProps(this.props.dispatch, mappings);
        const data = this.getFilteredFetchData(fetchData, mappings);

        return <WrappedComponent {...other} {...actions} {...data} />;
      }
    }

    ReactReduxFetch.displayName = `ReactReduxFetch.connect(${getDisplayName(WrappedComponent)})`;

    // ReactReduxFetch.propTypes = {
    //   dispatch: PropTypes.func.isRequired,
    //   fetchData: PropTypes.object.isRequired,
    // };

    const mapStateToProps = (state, props) =>
      merge(
        { fetchData: getModel(state) },
        helpers.ensureObject(componentMapStateToProps, [state, props]),
      );

    let mapDispatchToProps;

    if (isFunction(componentMapDispatchToProps)) {
      // $FlowFixMe
      mapDispatchToProps = dispatch => merge({ dispatch }, componentMapDispatchToProps(dispatch));
    } else if (isObject(componentMapDispatchToProps)) {
      mapDispatchToProps = dispatch =>
        merge({ dispatch }, bindActionCreators(componentMapDispatchToProps, dispatch));
    }

    return reduxConnect(mapStateToProps, mapDispatchToProps)(ReactReduxFetch);
  };
}

// function factory(defaults = {}, options = {}) {
function factory() {
  function connectImpl(
    map: FuncOrArr,
    mapStateToProps?: OptionalFuncOrObj,
    mapDispatchToProps?: OptionalFuncOrObj,
  ) {
    return connect(map, mapStateToProps, mapDispatchToProps);
  }

  return connectImpl;
}

export default factory();
<commit_msg>fixed broken lint<commit_after>// @flow

import React, { Component } from 'react';
import type { ComponentType } from 'react';
import { connect as reduxConnect } from 'react-redux';
import { bindActionCreators } from 'redux';
import isFunction from 'lodash/isFunction';
import isObject from 'lodash/isObject';
import merge from 'lodash/merge';
import each from 'lodash/each';
import reduce from 'lodash/reduce';
// import reactReduxFetchActions from '../actions';
import { getModel } from '../reducers/selectors';
// import container from '../container';
import capitalizeFirstLetter from '../utils/capitalizeFirstLetter';
import buildActionsFromMappings, {
  ensureResourceIsObject,
  validateResourceObject,
} from '../utils/buildActionsFromMappings';
import helpers from '../utils/helpers';
import type { reduxAction } from '../types';

// const defaultRequestType = 'get';

type Props = {
  dispatch(action: reduxAction): void,
  fetchData: Object,
};

type State = {
  dispatchFunctions?: Object,
}

type FuncOrArr = Function | Array<*>;
type OptionalFuncOrObj = Function | Object | null;

function getDisplayName(WrappedComponent: ComponentType<*>): string {
  return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}

function connect(
  mapPropsToRequestsToProps: FuncOrArr,
  componentMapStateToProps?: OptionalFuncOrObj = null,
  componentMapDispatchToProps?: OptionalFuncOrObj = null,
) {
  return function wrapWithReactReduxFetch(WrappedComponent: ComponentType<*>) {
    class ReactReduxFetch extends Component<Props, State> {
      constructor(props) {
        super(props);

        // if mapPropsToRequestsToProps is a function,
        // we can't cache our dispatch functions because they might depend on the props.
        // We could support this in the future by building the functions again when te props change.
        if (typeof mapPropsToRequestsToProps === 'function') {
          return;
        }

        this.state = {
          dispatchFunctions: this.actionsFromProps(props.dispatch, mapPropsToRequestsToProps),
        };
      }

      state = {};

      /**
       * @param {Object} fetchData The complete react-redux-fetch state leaf
       * @param {Array} mappings Array of objects with shape:
       *                {resource: ..., method: ..., request: ...}
       * @return {Object} all the resources the WrappedComponent requested
       */
      getFilteredFetchData = (fetchData, mappings) => {
        const data = {};

        each(mappings, (mapping) => {
          const resource = ensureResourceIsObject(mapping);
          validateResourceObject(resource);
          const resourceName = resource.name;

          data[`${resourceName}Fetch`] = fetchData[resourceName] || {};
        });

        return data;
      };

       /**
       * @param {Function} dispatch Redux dispatch function
       * @param {Array} mappings Array of objects with shape:
       *                {resource: ..., method: ..., request: ...}
       * @return {Object} functions for the WrappedComponent e.g.: 'dispatchUserFetch()'
        * */
      actionsFromProps = (dispatch, mappings: Array<*>): Object =>
        reduce(
          buildActionsFromMappings(mappings),
          (actions, actionCreator, key) =>
            Object.assign({}, actions, {
              [`dispatch${capitalizeFirstLetter(key)}`]: (...args) => {
                const action = actionCreator(...args);
                if (action) {
                  dispatch(action);
                }
              },
            }),
          {},
        );

      /**
       * If the value passed to connect() is a function,
       *    execute the function and pass the props + context
       * @param {Object} props React props
       * @param {Object} context React context
       * @return {Array} an array with request configurations
       * */
      buildMappings = (props: Props, context: Object): Array<*> => {
        const finalProps = props || this.props;
        const finalContext = context || this.context || {};

        return isFunction(mapPropsToRequestsToProps)
          ? // $FlowFixMe
            mapPropsToRequestsToProps(finalProps, finalContext)
          : // $FlowFixMe
            mapPropsToRequestsToProps;
      };

      render() {
        const { fetchData, ...other } = this.props;
        const { dispatchFunctions } = this.state;

        const mappings = this.buildMappings(this.props, this.context);
        const actions = dispatchFunctions || this.actionsFromProps(this.props.dispatch, mappings);
        const data = this.getFilteredFetchData(fetchData, mappings);

        return <WrappedComponent {...other} {...actions} {...data} />;
      }
    }

    ReactReduxFetch.displayName = `ReactReduxFetch.connect(${getDisplayName(WrappedComponent)})`;

    // ReactReduxFetch.propTypes = {
    //   dispatch: PropTypes.func.isRequired,
    //   fetchData: PropTypes.object.isRequired,
    // };

    const mapStateToProps = (state, props) =>
      merge(
        { fetchData: getModel(state) },
        helpers.ensureObject(componentMapStateToProps, [state, props]),
      );

    let mapDispatchToProps;

    if (isFunction(componentMapDispatchToProps)) {
      // $FlowFixMe
      mapDispatchToProps = dispatch => merge({ dispatch }, componentMapDispatchToProps(dispatch));
    } else if (isObject(componentMapDispatchToProps)) {
      mapDispatchToProps = dispatch =>
        merge({ dispatch }, bindActionCreators(componentMapDispatchToProps, dispatch));
    }

    return reduxConnect(mapStateToProps, mapDispatchToProps)(ReactReduxFetch);
  };
}

// function factory(defaults = {}, options = {}) {
function factory() {
  function connectImpl(
    map: FuncOrArr,
    mapStateToProps?: OptionalFuncOrObj,
    mapDispatchToProps?: OptionalFuncOrObj,
  ) {
    return connect(map, mapStateToProps, mapDispatchToProps);
  }

  return connectImpl;
}

export default factory();
<|endoftext|>


<commit_before>var webdriverio = require('../webdriverio'),
    child_process = require('child_process'),
    EventHandler = require('../utils/EventHandler'),
    PromiseHandler = require('../utils/PromiseHandler'),
    nonSeleniumCommands = require('./static').nonSeleniumCommands,
    chainIt = require('chainit'),
    path = require('path');

/**
 * Instance instance
 */
function Instance(instanceName, capabilities) {
    /**
     * assign bitmask
     */
    this.name = instanceName;
    this.origin = 'instance';

    this.commandId = 0;
    this.eventHandler = new EventHandler(this);

    /**
     * register listener for error to avoid breaking tests if no listener is registered
     */
    this.eventHandler.on('error', function(){});

    /**
     * process disconnect listener
     * gets called once an instance called the `end` method
     */
    this.onDisconnect = function(e) {
        /**
         * ToDo handle disconnects
         */
        // this.cp.kill();
    };

    this.onMessage = function(message) {
        /**
         * only handle messages executed by multibrowser
         */
        if(message.origin !== this.origin) {
            return;
        }

        /**
         * handling events
         */
        if(message.action === 'event') {
            message.args.unshift(message.type);
            message.args.push(message.instanceName);
            return this.eventHandler.emit.apply(this.eventHandler, message.args);
        }

        /**
         * acknowledge end command
         */
        if(message.action === 'command' && message.fnName === 'end') {
            this.cp.send({ action: 'kill' });
        }

        this.eventHandler.emit(message.origin + '_' + message.commandId, message);
    };

    this.onError = function(err) {
        /**
         * ToDo handle errors
         */
    };

    /**
     * addCommand added here because it's synchronous and thus does not need
     * to be added to asynchronous chain.
     */
    this.addCommand = function(name, fn) {
        chainIt.add(this, name, fn);

        /**
         * promisify new commands
         */
        this[name] = PromiseHandler(name, this[name]);

        /**
         * we still returns the instance so that we can continue chaining
         */
        return this;
    };

    this.cp = child_process.fork(__dirname + path.sep + 'runner.js');
    this.cp.on('disconnect', this.onDisconnect.bind(this));
    this.cp.on('message', this.onMessage.bind(this));
    this.cp.on('error', this.onError.bind(this));

    /**
     * initialise process instance
     */
    this.cp.send({
        action: 'initiate',
        instanceName: this.name,
        capabilities: capabilities
    });
};

/**
 * assign custom instance methods to each WebdriverIO command to make sure they'll get chained
 */
Object.keys(webdriverio.prototype).forEach(function(fnName) {
    /**
     * skip non selenium commands so they still get handled like
     * normal chained commands
     */
    if(nonSeleniumCommands.indexOf(fnName) === 0) {
        return Instance.prototype[fnName] = webdriverio.prototype[fnName];
    }

    /**
     * handle Selenium methods as real chained methods but instead of doing
     * HTTP requests we listen on the result from all instances.
     * Therefor is the actual Instance command just the event listener
     * and gets triggered once one intances finishes the command
     */
    Instance.prototype[fnName] = function(){
        var self = this,
            args = Array.prototype.slice.call(arguments),
            callback = args.pop();

        var processMessage = {
            origin: this.origin,
            action: 'command',
            fnName: fnName,
            args: args,
            commandId: this.commandId
        };

        this.cp.send(processMessage);
        this.eventHandler.on(this.origin + '_' + this.commandId, function(message) {
            return callback.apply(self, message.args);
        });

        this.commandId++;

        return this;
    };
});

var InstanceConstructor = chainIt(Instance);
Object.keys(InstanceConstructor.prototype).forEach(function(fnName) {
    if(fnName.indexOf('__') === 0) {
        return;
    }

    InstanceConstructor.prototype[fnName] = PromiseHandler(fnName, InstanceConstructor.prototype[fnName]);
});

module.exports = InstanceConstructor;<commit_msg>cast function arguments to string to enable execute commands (for multibrowser instance)<commit_after>var webdriverio = require('../webdriverio'),
    child_process = require('child_process'),
    EventHandler = require('../utils/EventHandler'),
    PromiseHandler = require('../utils/PromiseHandler'),
    nonSeleniumCommands = require('./static').nonSeleniumCommands,
    chainIt = require('chainit'),
    path = require('path');

/**
 * Instance instance
 */
function Instance(instanceName, capabilities) {
    /**
     * assign bitmask
     */
    this.name = instanceName;
    this.origin = 'instance';

    this.commandId = 0;
    this.eventHandler = new EventHandler(this);

    /**
     * register listener for error to avoid breaking tests if no listener is registered
     */
    this.eventHandler.on('error', function(){});

    /**
     * process disconnect listener
     * gets called once an instance called the `end` method
     */
    this.onDisconnect = function(e) {
        /**
         * ToDo handle disconnects
         */
        // this.cp.kill();
    };

    this.onMessage = function(message) {
        /**
         * only handle messages executed by multibrowser
         */
        if(message.origin !== this.origin) {
            return;
        }

        /**
         * handling events
         */
        if(message.action === 'event') {
            message.args.unshift(message.type);
            message.args.push(message.instanceName);
            return this.eventHandler.emit.apply(this.eventHandler, message.args);
        }

        /**
         * acknowledge end command
         */
        if(message.action === 'command' && message.fnName === 'end') {
            this.cp.send({ action: 'kill' });
        }

        this.eventHandler.emit(message.origin + '_' + message.commandId, message);
    };

    this.onError = function(err) {
        /**
         * ToDo handle errors
         */
    };

    /**
     * addCommand added here because it's synchronous and thus does not need
     * to be added to asynchronous chain.
     */
    this.addCommand = function(name, fn) {
        chainIt.add(this, name, fn);

        /**
         * promisify new commands
         */
        this[name] = PromiseHandler(name, this[name]);

        /**
         * we still returns the instance so that we can continue chaining
         */
        return this;
    };

    this.cp = child_process.fork(__dirname + path.sep + 'runner.js');
    this.cp.on('disconnect', this.onDisconnect.bind(this));
    this.cp.on('message', this.onMessage.bind(this));
    this.cp.on('error', this.onError.bind(this));

    /**
     * initialise process instance
     */
    this.cp.send({
        action: 'initiate',
        instanceName: this.name,
        capabilities: capabilities
    });
};

/**
 * assign custom instance methods to each WebdriverIO command to make sure they'll get chained
 */
Object.keys(webdriverio.prototype).forEach(function(fnName) {
    /**
     * skip non selenium commands so they still get handled like
     * normal chained commands
     */
    if(nonSeleniumCommands.indexOf(fnName) === 0) {
        return Instance.prototype[fnName] = webdriverio.prototype[fnName];
    }

    /**
     * handle Selenium methods as real chained methods but instead of doing
     * HTTP requests we listen on the result from all instances.
     * Therefor is the actual Instance command just the event listener
     * and gets triggered once one intances finishes the command
     */
    Instance.prototype[fnName] = function(){
        var self = this,
            args = Array.prototype.slice.call(arguments),
            callback = args.pop();

        /**
         * cast all function parameters into strings to send them to the instance child_process
         */
        for(var i in args) {
            args[i] = typeof args[i] === 'function' ? args[i].toString() : args[i];
        }

        var processMessage = {
            origin: this.origin,
            action: 'command',
            fnName: fnName,
            args: args,
            commandId: this.commandId
        };

        this.cp.send(processMessage);
        this.eventHandler.on(this.origin + '_' + this.commandId, function(message) {
            return callback.apply(self, message.args);
        });

        this.commandId++;

        return this;
    };
});

var InstanceConstructor = chainIt(Instance);
Object.keys(InstanceConstructor.prototype).forEach(function(fnName) {
    if(fnName.indexOf('__') === 0) {
        return;
    }

    InstanceConstructor.prototype[fnName] = PromiseHandler(fnName, InstanceConstructor.prototype[fnName]);
});

module.exports = InstanceConstructor;<|endoftext|>


<commit_before>import React from 'react';
import { Link } from 'react-router';
import FlatButton from 'material-ui/FlatButton';
import Talker from 'material-ui/svg-icons/action/record-voice-over';
import Calendar from 'material-ui/svg-icons/editor/insert-invitation';
import Silverware from 'material-ui/svg-icons/maps/restaurant';
import { green50, deepOrange800 } from 'material-ui/styles/colors';
import {
	Footer,
	Hero,
	HorizontalSplit,
	ImageList,
	Page,
	Section,
} from 'neal-react';

const styles = {
	navButtons: {
		color: green50,
		height: 50,
		width: 75,
		fontSize: 20,
		backgroundColor: deepOrange800,
		margin: 10,
	},
	talker: {
		width: 75,
		height: 75,
	},
	lead: {
		marginLeft: 35,
	},
	bannerBox: {
		margin: 'auto',
	},
};

const brandName = 'ColdForge';

const Landing = () => (
	<Page>

 Icebox

"The complete refrigerator companion"

				<Link to="signin" className="nav-link">
					<FlatButton
						style={styles.navButtons}
					>
						Sign In
					</FlatButton>
				</Link>
				<Link to="signup" className="nav-link">
					<FlatButton
						style={styles.navButtons}
					>
						Sign Up
					</FlatButton>
				</Link>

		<Hero
			backgroundImage="../../assets/veggieDrop.jpg"
			className="banner-display"
			style={styles.landingImage}
		/>

			<HorizontalSplit padding="md">

					<Talker style={styles.talker} />

Input Items by Voice

						Add items to your icebox as you unload your groceries with
						the sound of your voice. Icebox goes hands-free in the kitchen
						so that you can spend more time gettings things done and less
						time playing with an app.

					<Calendar style={styles.talker} />

Track Food Expiration Dates

						Keep track of how long your food will last so that you can better
						plan your grocery shopping and what meals you cook. With Icebox
						mobile, take what is in your refriegerator with you and never buy
						something you already have.

					<Silverware style={styles.talker} />

Sends you Smart Recipies

						Icebox will suggest recipes to you based on the food that is
						expiring in your fridge. Choose your recipe and forget about
						having to decide what is for dinner or finding creative ways
						to use up the food you have.

			</HorizontalSplit>

"...nearly 40% of the food produced in the United States
				winds up in a landfill..."

–fastcoexist.com

The Engineering Team

Colin Zarnegar

Product Owner

Austin Sefton

Front End

Nathaniel Schwab

Scrum Master

Andrew Yao

Full Stack

			<ImageList centered>

			</ImageList>

				First food photograph designed by Onlyyouqj - Freepik.com

				Second food photograph designed by Kstudio - Freepik.com

	</Page>
);

export default Landing;
<commit_msg>[style] lengthens banner background image to fill whole screen<commit_after>import React from 'react';
import { Link } from 'react-router';
import FlatButton from 'material-ui/FlatButton';
import Talker from 'material-ui/svg-icons/action/record-voice-over';
import Calendar from 'material-ui/svg-icons/editor/insert-invitation';
import Silverware from 'material-ui/svg-icons/maps/restaurant';
import { green50, deepOrange800 } from 'material-ui/styles/colors';
import {
	Footer,
	Hero,
	HorizontalSplit,
	ImageList,
	Page,
	Section,
} from 'neal-react';

const styles = {
	landingImage: {
		height: 1000,
		backgroundImage: "url('../../assets/veggieDrop.jpg')"
	},
	navButtons: {
		color: green50,
		height: 50,
		width: 75,
		fontSize: 20,
		backgroundColor: deepOrange800,
		margin: 10,
	},
	talker: {
		width: 75,
		height: 75,
	},
	lead: {
		marginLeft: 35,
	},
	bannerBox: {
		margin: 'auto',
	},
};

const brandName = 'ColdForge';

const Landing = () => (
	<Page>

 Icebox

"The complete refrigerator companion"

				<Link to="signin" className="nav-link">
					<FlatButton
						style={styles.navButtons}
					>
						Sign In
					</FlatButton>
				</Link>
				<Link to="signup" className="nav-link">
					<FlatButton
						style={styles.navButtons}
					>
						Sign Up
					</FlatButton>
				</Link>

			<HorizontalSplit padding="md">

					<Talker style={styles.talker} />

Input Items by Voice

						Add items to your icebox as you unload your groceries with
						the sound of your voice. Icebox goes hands-free in the kitchen
						so that you can spend more time gettings things done and less
						time playing with an app.

					<Calendar style={styles.talker} />

Track Food Expiration Dates

						Keep track of how long your food will last so that you can better
						plan your grocery shopping and what meals you cook. With Icebox
						mobile, take what is in your refriegerator with you and never buy
						something you already have.

					<Silverware style={styles.talker} />

Sends you Smart Recipies

						Icebox will suggest recipes to you based on the food that is
						expiring in your fridge. Choose your recipe and forget about
						having to decide what is for dinner or finding creative ways
						to use up the food you have.

			</HorizontalSplit>

"...nearly 40% of the food produced in the United States
				winds up in a landfill..."

–fastcoexist.com

The Engineering Team

Colin Zarnegar

Product Owner

Austin Sefton

Front End

Nathaniel Schwab

Scrum Master

Andrew Yao

Full Stack

			<ImageList centered>

			</ImageList>

				First food photograph designed by Onlyyouqj - Freepik.com

				Second food photograph designed by Kstudio - Freepik.com

	</Page>
);

export default Landing;
<|endoftext|>


<commit_before>var base64_val = [
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63,
   52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255,  0,255,255,
  255,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
   15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
  255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
   41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255
]

function base64_8(str, index) {
  var v =
    (base64_val[str.charCodeAt(index)]) +
    (base64_val[str.charCodeAt(index+1)] << 6);
  return v;
}

function base64_16(str, index) {
  var v =
    (base64_val[str.charCodeAt(index)]) +
    (base64_val[str.charCodeAt(index+1)] << 6) +
    (base64_val[str.charCodeAt(index+2)] << 12);
  return v;
}

function base64_16s(str, index) {
  var v = base64_16(str, index);
  if (v > 32767)
    return v - 65536;
  else
    return v;
}

function base64_24(str, index) {
  var v =
    (base64_val[str.charCodeAt(index)]) +
    (base64_val[str.charCodeAt(index+1)] << 6) +
    (base64_val[str.charCodeAt(index+2)] << 12) +
    (base64_val[str.charCodeAt(index+3)] << 18);
  return v;
}

function base64_32(str, index) {
  var v =
    (base64_val[str.charCodeAt(index)]) +
    (base64_val[str.charCodeAt(index+1)] << 6) +
    (base64_val[str.charCodeAt(index+2)] << 12) +
    (base64_val[str.charCodeAt(index+3)] << 18) +
    (base64_val[str.charCodeAt(index+4)] << 24) +
    (base64_val[str.charCodeAt(index+5)] << 30);
  return v;
}

function createXHR()
{
  try { return new XMLHttpRequest(); } catch(e) {}
  try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e) {}
  try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e) {}
  try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) {}
  try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {}

  return null;
}

var surfaces = {};
var outstanding_commands = new Array();
var input_socket = null;

function initContext(canvas, x, y, id)
{
  canvas.surface_id = id;
  canvas.style["position"] = "absolute"
  canvas.style["left"] = x + "px"
  canvas.style["top"] = y + "px"
  canvas.style["display"] = "none"
  context = canvas.getContext("2d")
  context.globalCompositeOperation = "src-over"
  context.fillRect(0, 0, canvas.width, canvas.height);
  document.body.appendChild(canvas)

  return context
}

function handleCommands(cmd_obj)
{
  var cmd = cmd_obj.data;
  var i = cmd_obj.pos;

  while (i < cmd.length) {
    var command = cmd[i++];
    switch (command) {
      /* create new surface */
      case 's':
        var id = base64_16(cmd, i);
        i = i + 3;
        var x = base64_16(cmd, i);
        i = i + 3;
        var y = base64_16(cmd, i);
        i = i + 3;
        var w = base64_16(cmd, i);
        i = i + 3;
        var h = base64_16(cmd, i);
        i = i + 3;
        var surface = document.createElement("canvas");
	surface.width = w;
	surface.height = h;
	surfaces[id] = initContext(surface, x, y, id);
        break;

      /* show a surface */
      case 'S':
        var id = base64_16(cmd, i);
        i = i + 3;
	surfaces[id].canvas.style["display"] = "inline";
        break;

      /* hide a surface */
      case 'H':
        var id = base64_16(cmd, i);
        i = i + 3;
	surfaces[id].canvas.style["display"] = "inline";
        break;

      /* delete surface */
      case 'd':
        var id = base64_16(cmd, i);
        i = i + 3;
	var canvas = surfaces[id].canvas
	delete surfaces[id]
	canvas.parentNode.removeChild(canvas);

        break;

      /* move a surface */
      case 'm':
        var id = base64_16(cmd, i);
        i = i + 3;
        var x = base64_16(cmd, i);
        i = i + 3;
        var y = base64_16(cmd, i);
        i = i + 3;
	surfaces[id].canvas.style["left"] = x + "px";
	surfaces[id].canvas.style["top"] = y + "px";
        break;

      /* resize a surface */
      case 'r':
        var id = base64_16(cmd, i);
        i = i + 3;
        var w = base64_16(cmd, i);
        i = i + 3;
        var h = base64_16(cmd, i);
        i = i + 3;
	surfaces[id].canvas.width = w;
	surfaces[id].canvas.height = h;
        break;

      /* put image data surface */
      case 'i':
        var id = base64_16(cmd, i);
        i = i + 3;
        var x = base64_16(cmd, i);
        i = i + 3;
        var y = base64_16(cmd, i);
        i = i + 3;
        var size = base64_32(cmd, i);
        i = i + 6;
	var url = cmd.slice(i, i + size);
	i = i + size;
        var img = new Image();
	img.src = url
	if (img.complete) {
          surfaces[id].drawImage(img, x, y);
	} else {
	  cmd_obj.pos = i;
	  img.onload = function() { surfaces[id].drawImage(img, x, y); handleOutstanding(); }
	  return false
	}

        break;

      /* copy rects */
      case 'b':
        var id = base64_16(cmd, i);
        i = i + 3;

	var nrects = base64_16(cmd, i);
        i = i + 3;

	var context = surfaces[id];
	context.save();

	var minx;
	var miny;
	var maxx;
	var maxy;
	for (var r = 0; r < nrects; r++) {
	  var x = base64_16(cmd, i);
          i = i + 3;
          var y = base64_16(cmd, i);
          i = i + 3;
          var w = base64_16(cmd, i);
          i = i + 3;
          var h = base64_16(cmd, i);
          i = i + 3;
	  context.rect(x, y, w, h);

	  if (r == 0) {
	      minx = x;
	      miny = y;
	      maxx = x + w;
	      maxy = y + h;
	  } else {
	      if (x < minx)
		  minx = x;
	      if (y < miny)
		  miny = y;
	      if (x + w > maxx)
		  maxx = x + w;
	      if (y + h > maxy)
		  maxy = y + h;
	  }
	}

	context.clip()

        var dx = base64_16s(cmd, i);
        i = i + 3;
        var dy = base64_16s(cmd, i);
        i = i + 3;

        context.drawImage(context.canvas,
			  minx - dx, miny - dy, maxx - minx, maxy - miny,
			  minx, miny, maxx - minx, maxy - miny);

	context.restore();
        break;

      default:
        alert("Unknown op " + command);
    }
  }
  return true;
}

function handleOutstanding()
{
  while (outstanding_commands.length > 0) {
    var cmd = outstanding_commands.shift();
    if (!handleCommands(cmd)) {
      outstanding_commands.unshift(cmd);
      return;
    }
  }
}

function handleLoad(event)
{
  var cmd_obj = {};
  cmd_obj.data = event.target.responseText;
  cmd_obj.pos = 0;

  outstanding_commands.push(cmd_obj);
  if (outstanding_commands.length == 1) {
    handleOutstanding()
  }

  if ("WebSocket" in window) {
    var loc = window.location.toString().replace("http:", "ws:");
    loc = loc.substr(0, loc.lastIndexOf('/')) + "/input";
    var ws = new WebSocket(loc, "broadway");
    ws.onopen = function() {
      input_socket = ws;
    };
    ws.onclose = function() {
      input_socket = null;
    };
  } else {
     alert("WebSocket not supported, input will not work!");
  }
}

function get_surface_id(ev) {
  var id = ev.target.surface_id;
  if (id != undefined)
    return id;
  return 0;
}

function send_input(cmd, args)
{
  if (input_socket != null) {
      input_socket.send(cmd + args.join(","));
  }
}

function on_mouse_move (ev) {
  send_input ("m", [get_surface_id(ev), ev.pageX, ev.pageY, ev.timeStamp])
}

function on_mouse_down (ev) {
  send_input ("b", [get_surface_id(ev), ev.pageX, ev.pageY, ev.button, ev.timeStamp])
}

function on_mouse_up (ev) {
  send_input ("B", [get_surface_id(ev), ev.pageX, ev.pageY, ev.button, ev.timeStamp])
}

function connect()
{
  var xhr = createXHR();
  if (xhr) {
    if (typeof xhr.multipart == 'undefined') {
      alert("Sorry, this example only works in browsers that support multipart.");
      return;
    }

    xhr.multipart = true;
    xhr.open("GET", "/output", true);
    xhr.onload = handleLoad;
    xhr.send(null);
  }

  document.onmousemove = on_mouse_move;
  document.onmousedown = on_mouse_down;
  document.onmouseup = on_mouse_up;
}
<commit_msg>[broadway] Only open one websocket for input!<commit_after>var base64_val = [
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63,
   52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255,  0,255,255,
  255,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
   15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
  255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
   41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255
]

function base64_8(str, index) {
  var v =
    (base64_val[str.charCodeAt(index)]) +
    (base64_val[str.charCodeAt(index+1)] << 6);
  return v;
}

function base64_16(str, index) {
  var v =
    (base64_val[str.charCodeAt(index)]) +
    (base64_val[str.charCodeAt(index+1)] << 6) +
    (base64_val[str.charCodeAt(index+2)] << 12);
  return v;
}

function base64_16s(str, index) {
  var v = base64_16(str, index);
  if (v > 32767)
    return v - 65536;
  else
    return v;
}

function base64_24(str, index) {
  var v =
    (base64_val[str.charCodeAt(index)]) +
    (base64_val[str.charCodeAt(index+1)] << 6) +
    (base64_val[str.charCodeAt(index+2)] << 12) +
    (base64_val[str.charCodeAt(index+3)] << 18);
  return v;
}

function base64_32(str, index) {
  var v =
    (base64_val[str.charCodeAt(index)]) +
    (base64_val[str.charCodeAt(index+1)] << 6) +
    (base64_val[str.charCodeAt(index+2)] << 12) +
    (base64_val[str.charCodeAt(index+3)] << 18) +
    (base64_val[str.charCodeAt(index+4)] << 24) +
    (base64_val[str.charCodeAt(index+5)] << 30);
  return v;
}

function createXHR()
{
  try { return new XMLHttpRequest(); } catch(e) {}
  try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e) {}
  try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e) {}
  try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) {}
  try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {}

  return null;
}

var surfaces = {};
var outstanding_commands = new Array();
var input_socket = null;

function initContext(canvas, x, y, id)
{
  canvas.surface_id = id;
  canvas.style["position"] = "absolute"
  canvas.style["left"] = x + "px"
  canvas.style["top"] = y + "px"
  canvas.style["display"] = "none"
  context = canvas.getContext("2d")
  context.globalCompositeOperation = "src-over"
  context.fillRect(0, 0, canvas.width, canvas.height);
  document.body.appendChild(canvas)

  return context
}

function handleCommands(cmd_obj)
{
  var cmd = cmd_obj.data;
  var i = cmd_obj.pos;

  while (i < cmd.length) {
    var command = cmd[i++];
    switch (command) {
      /* create new surface */
      case 's':
        var id = base64_16(cmd, i);
        i = i + 3;
        var x = base64_16(cmd, i);
        i = i + 3;
        var y = base64_16(cmd, i);
        i = i + 3;
        var w = base64_16(cmd, i);
        i = i + 3;
        var h = base64_16(cmd, i);
        i = i + 3;
        var surface = document.createElement("canvas");
	surface.width = w;
	surface.height = h;
	surfaces[id] = initContext(surface, x, y, id);
        break;

      /* show a surface */
      case 'S':
        var id = base64_16(cmd, i);
        i = i + 3;
	surfaces[id].canvas.style["display"] = "inline";
        break;

      /* hide a surface */
      case 'H':
        var id = base64_16(cmd, i);
        i = i + 3;
	surfaces[id].canvas.style["display"] = "inline";
        break;

      /* delete surface */
      case 'd':
        var id = base64_16(cmd, i);
        i = i + 3;
	var canvas = surfaces[id].canvas
	delete surfaces[id]
	canvas.parentNode.removeChild(canvas);

        break;

      /* move a surface */
      case 'm':
        var id = base64_16(cmd, i);
        i = i + 3;
        var x = base64_16(cmd, i);
        i = i + 3;
        var y = base64_16(cmd, i);
        i = i + 3;
	surfaces[id].canvas.style["left"] = x + "px";
	surfaces[id].canvas.style["top"] = y + "px";
        break;

      /* resize a surface */
      case 'r':
        var id = base64_16(cmd, i);
        i = i + 3;
        var w = base64_16(cmd, i);
        i = i + 3;
        var h = base64_16(cmd, i);
        i = i + 3;
	surfaces[id].canvas.width = w;
	surfaces[id].canvas.height = h;
        break;

      /* put image data surface */
      case 'i':
        var id = base64_16(cmd, i);
        i = i + 3;
        var x = base64_16(cmd, i);
        i = i + 3;
        var y = base64_16(cmd, i);
        i = i + 3;
        var size = base64_32(cmd, i);
        i = i + 6;
	var url = cmd.slice(i, i + size);
	i = i + size;
        var img = new Image();
	img.src = url
	if (img.complete) {
          surfaces[id].drawImage(img, x, y);
	} else {
	  cmd_obj.pos = i;
	  img.onload = function() { surfaces[id].drawImage(img, x, y); handleOutstanding(); }
	  return false
	}

        break;

      /* copy rects */
      case 'b':
        var id = base64_16(cmd, i);
        i = i + 3;

	var nrects = base64_16(cmd, i);
        i = i + 3;

	var context = surfaces[id];
	context.save();

	var minx;
	var miny;
	var maxx;
	var maxy;
	for (var r = 0; r < nrects; r++) {
	  var x = base64_16(cmd, i);
          i = i + 3;
          var y = base64_16(cmd, i);
          i = i + 3;
          var w = base64_16(cmd, i);
          i = i + 3;
          var h = base64_16(cmd, i);
          i = i + 3;
	  context.rect(x, y, w, h);

	  if (r == 0) {
	      minx = x;
	      miny = y;
	      maxx = x + w;
	      maxy = y + h;
	  } else {
	      if (x < minx)
		  minx = x;
	      if (y < miny)
		  miny = y;
	      if (x + w > maxx)
		  maxx = x + w;
	      if (y + h > maxy)
		  maxy = y + h;
	  }
	}

	context.clip()

        var dx = base64_16s(cmd, i);
        i = i + 3;
        var dy = base64_16s(cmd, i);
        i = i + 3;

        context.drawImage(context.canvas,
			  minx - dx, miny - dy, maxx - minx, maxy - miny,
			  minx, miny, maxx - minx, maxy - miny);

	context.restore();
        break;

      default:
        alert("Unknown op " + command);
    }
  }
  return true;
}

function handleOutstanding()
{
  while (outstanding_commands.length > 0) {
    var cmd = outstanding_commands.shift();
    if (!handleCommands(cmd)) {
      outstanding_commands.unshift(cmd);
      return;
    }
  }
}

function handleLoad(event)
{
  var cmd_obj = {};
  cmd_obj.data = event.target.responseText;
  cmd_obj.pos = 0;

  outstanding_commands.push(cmd_obj);
  if (outstanding_commands.length == 1) {
    handleOutstanding()
  }
}

function get_surface_id(ev) {
  var id = ev.target.surface_id;
  if (id != undefined)
    return id;
  return 0;
}

function send_input(cmd, args)
{
  if (input_socket != null) {
      input_socket.send(cmd + args.join(","));
  }
}

function on_mouse_move (ev) {
  send_input ("m", [get_surface_id(ev), ev.pageX, ev.pageY, ev.timeStamp])
}

function on_mouse_down (ev) {
  send_input ("b", [get_surface_id(ev), ev.pageX, ev.pageY, ev.button, ev.timeStamp])
}

function on_mouse_up (ev) {
  send_input ("B", [get_surface_id(ev), ev.pageX, ev.pageY, ev.button, ev.timeStamp])
}

function connect()
{
  var xhr = createXHR();
  if (xhr) {
    if (typeof xhr.multipart == 'undefined') {
      alert("Sorry, this example only works in browsers that support multipart.");
      return;
    }

    xhr.multipart = true;
    xhr.open("GET", "/output", true);
    xhr.onload = handleLoad;
    xhr.send(null);
  }

  if ("WebSocket" in window) {
    var loc = window.location.toString().replace("http:", "ws:");
    loc = loc.substr(0, loc.lastIndexOf('/')) + "/input";
    var ws = new WebSocket(loc, "broadway");
    ws.onopen = function() {
      input_socket = ws;
    };
    ws.onclose = function() {
      input_socket = null;
    };
  } else {
     alert("WebSocket not supported, input will not work!");
  }
  document.onmousemove = on_mouse_move;
  document.onmousedown = on_mouse_down;
  document.onmouseup = on_mouse_up;
}
<|endoftext|>


<commit_before>(function() {
	var recursive=function(str,o,c) {
		var p=[],s=str,o=str.match(o)||[],c=str.match(c)||[];
		var _build=function(str,o,i) {
			var s=str.substr(0,str.indexOf(o[i]));
			var e=str.substr(str.indexOf(o[i])+o[i].length);
			return s+_noop(o[i].length)+e;
		};
		var _noop=function(l) {
			var s=[];
			for(var i=0;i<l;i++) s.push('-');
			return s.join('');
		};
		var _judge=function(arr) {
			for(var i=0,c=0,p=0,t=[];i<arr.length;i++) {
				if(!c) p=i;
				if(arr[i]=='o') c++;
				if(arr[i]=='c') c--;
				if(!c && arr[i]) t.push(s.substr(p,i+1-p));
			}
			return t;
		};
		for(var i=0;i<o.length;i++) {
			p[str.indexOf(o[i])]='o';
			str=_build(str,o,i);
		}
		for(var i=0;i<c.length;i++) {
			p[str.indexOf(c[i])+c[i].length-1]='c';
			str=_build(str,c,i);
		}
		return _judge(p);
	};

	var replace=function(str,a,b) {
		var s=str.substr(0,str.indexOf(a));
		var e=str.substr(str.indexOf(a)+a.length);
		return s+b+e;
	};

	var reference=function(str,re) {
		var ret;
		str.replace(re,function() {
			ret=arguments;
			return ret[0];
		});
		return ret;
	};

	var evalString=new Function('exp',
		"return exp;"
	);

	this.juicer=function(tpl,data) {
		var fn=arguments.callee;
		var re={
			'_for':/{@for\s+([^}]*)}([\s\S]*){@\/for}/igm,
			'_if':/{@if\s+([^}]*)}([\s\S]*){@\/if}/igm,
			'_unit':/\[#(.*?)(\s+condition=["|'](.*?)["|'])?\]/igm,
		};
		var _for=function(str) {
			var ref=reference(str,re._for),chain=ref[1],inner=ref[2];
			if(!data[chain]) return '';
			for(var i=0,t=[];i<data[chain].length;i++) t.push(fn(inner,data[chain][i]));
			return t.join('');
		};
		var _if=function(str) {
			var ref=reference(str,re._if),condition=ref[1],inner=ref[2];
			if(evalString(fn(condition,data))) return fn(inner,data);
			return '';
		};
		var _unit=function($a,$1,$2,$3) {
			if(!$3 || evalString(fn($3,data))) return data[$1]?typeof(data[$1])=='object'?true:data[$1]:'';
			return '';
		};

		for(var i=0,__f=recursive(tpl,/{@for[^}]*?}/igm,/{@\/for}/igm);i<__f.length;i++) {
			tpl=replace(tpl,__f[i],_for(__f[i]));
		}

		for(var i=0,__i=recursive(tpl,/{@if[^}]*?}/igm,/{@\/if}/igm);i<__i.length;i++) {
			tpl=replace(tpl,__i[i],_if(__i[i]));
		}

		tpl=tpl.replace(re._unit,_unit);

		return tpl;
	};
})();
<commit_msg>added the copyright information.<commit_after>/*
	@author: guokai
	@email/gtalk: badkaikai@gmail.com
	@blog/website: http://benben.cc
	@license: apache license,version 2.0

	@usage: http://paulguo.github.com/Juicer
	@version: 0.1.0
	@build: 110626120407
*/

(function() {
	var recursive=function(str,o,c) {
		var p=[],s=str,o=str.match(o)||[],c=str.match(c)||[];
		var _build=function(str,o,i) {
			var s=str.substr(0,str.indexOf(o[i]));
			var e=str.substr(str.indexOf(o[i])+o[i].length);
			return s+_noop(o[i].length)+e;
		};
		var _noop=function(l) {
			var s=[];
			for(var i=0;i<l;i++) s.push('-');
			return s.join('');
		};
		var _judge=function(arr) {
			for(var i=0,c=0,p=0,t=[];i<arr.length;i++) {
				if(!c) p=i;
				if(arr[i]=='o') c++;
				if(arr[i]=='c') c--;
				if(!c && arr[i]) t.push(s.substr(p,i+1-p));
			}
			return t;
		};
		for(var i=0;i<o.length;i++) {
			p[str.indexOf(o[i])]='o';
			str=_build(str,o,i);
		}
		for(var i=0;i<c.length;i++) {
			p[str.indexOf(c[i])+c[i].length-1]='c';
			str=_build(str,c,i);
		}
		return _judge(p);
	};

	var replace=function(str,a,b) {
		var s=str.substr(0,str.indexOf(a));
		var e=str.substr(str.indexOf(a)+a.length);
		return s+b+e;
	};

	var reference=function(str,re) {
		var ret;
		str.replace(re,function() {
			ret=arguments;
			return ret[0];
		});
		return ret;
	};

	var evalString=new Function('exp',
		"return exp;"
	);

	this.juicer=function(tpl,data) {
		var fn=arguments.callee;
		var re={
			'_for':/{@for\s+([^}]*)}([\s\S]*){@\/for}/igm,
			'_if':/{@if\s+([^}]*)}([\s\S]*){@\/if}/igm,
			'_unit':/\[#(.*?)(\s+condition=["|'](.*?)["|'])?\]/igm,
		};
		var _for=function(str) {
			var ref=reference(str,re._for),chain=ref[1],inner=ref[2];
			if(!data[chain]) return '';
			for(var i=0,t=[];i<data[chain].length;i++) t.push(fn(inner,data[chain][i]));
			return t.join('');
		};
		var _if=function(str) {
			var ref=reference(str,re._if),condition=ref[1],inner=ref[2];
			if(evalString(fn(condition,data))) return fn(inner,data);
			return '';
		};
		var _unit=function($a,$1,$2,$3) {
			if(!$3 || evalString(fn($3,data))) return data[$1]?typeof(data[$1])=='object'?true:data[$1]:'';
			return '';
		};

		for(var i=0,__f=recursive(tpl,/{@for[^}]*?}/igm,/{@\/for}/igm);i<__f.length;i++) {
			tpl=replace(tpl,__f[i],_for(__f[i]));
		}

		for(var i=0,__i=recursive(tpl,/{@if[^}]*?}/igm,/{@\/if}/igm);i<__i.length;i++) {
			tpl=replace(tpl,__i[i],_if(__i[i]));
		}

		tpl=tpl.replace(re._unit,_unit);

		return tpl;
	};
})();
<|endoftext|>


<commit_before>(function(global) {
	"use strict";

	/***************************************************************************
	 *	swapper.js:
	 *	A JS class to help you toggle the visibility of parts of your web project.
	 *
	 *	By Dani Gámez Franco, http://gmzcodes.com
	 *	Licensed under MIT.
	 *
	 *	Version: 1.1.1
	 *	Last Update: 2014-08-30
	 *
	 *	NOTE:
	 *	The current page class CAN NOT be changed programmatically. Search and
	 *	replace "currentPage" with the desired class name inside this file
	 *	instead or adapt your project to work with the default value.
	 *
	 *	Same thing for "deadPage" and "pageMe".
	 *
	 *	TO-DO:
	 *	 - Add a callback to call on transition end (with option to use delegation).
	 *	 - Add a parameter to use or not requestAnimationFrame.
	 *	 - Use parameters instead of strings for the classes used by swapper.js
	 *	   and add functions to change them programmatically (?).
	 *	 - Add a method to remove elements from the set.
	 *
	 **************************************************************************/

	// CONSTRUCTOR & (PUBLIC) VARIABLES ////////////////////////////////////////

	var Swapper = function(IDs, currentIndex, defaultIndex, anchorMode) {
		this.pagesIDs=new Array();
		this.pagesDOM=new Array();
		this.pagesCount=0;

		if(typeof IDs === "string"){
			if(IDs==="autoMODE"){ // Automatically seach for .pageMe elements.
				var elements=document.getElementsByClassName("pageMe");

				IDs = new Array();

				for(var i=0, L=elements.length; i<L; ++i)
					elements[i].id.length>0 && IDs.push(elements[i].id);
			}
			else IDs=new Array(IDs); // Just one element added.
		}

		if(Object.prototype.toString.call( IDs ) === "[object Array]")
			this.addPages(IDs);
		else
			throw "Invalid argument 'IDs'.";

		// Current element:
		if(typeof currentIndex === "number" && this.pagesCount > 0)
			this.currentIndex = Math.max( Math.min(currentIndex, this.pagesCount-1), 0);
		else
			this.currentIndex = null;

		// Default element:
		this.setDefaultByIndex(defaultIndex);

		// Anchor mode:
		this.anchorMode = anchorMode?true:false;
	};

	// PROTOTYPE VARIABLES /////////////////////////////////////////////////////

	// Set transitionEvent property in the prototype. Code from Modernizr:
	Swapper.prototype.transitionEvent = (function(){
		"use strict";
		var t;
		var el = document.createElement('fakeelement');
		var transitions = {
		  'transition':'transitionend',
		  'OTransition':'oTransitionEnd',
		  'MozTransition':'transitionend',
		  'WebkitTransition':'webkitTransitionEnd'
		}

		for(t in transitions){
			if( el.style[t] !== undefined ){
				return transitions[t];
			}
		}
	})();

	// METHODS /////////////////////////////////////////////////////////////////

	Swapper.prototype.addPage=function(ID) {

		if(this.pagesIDs.indexOf(ID)==-1){

			var element=document.getElementById(ID);

			if(element){
				this.pagesIDs.push(ID);
				this.pagesDOM.push(element);

				++this.pagesCount;

				/*

				TO-DO: Maybe in future versions...

				element.addEventListener(this.transitionEvent, function(e) {

					if(e.propertyName=="opacity"){
						console.log(e.target.className);
						if(e.target.className=="hiddenPage"){
							e.target.className="hiddenPage";
						}
						else {
							console.log("VISIBLE");
							console.log(e.target);
						}
					}
				});

				*/

				return true;
			}
			else{
				console.error("Swapper.js (ERR) - No element with ID '"+ID+"' found.");
			}
		}
		else{
			console.error("Swapper.js (ERR) - Element with ID '"+ID+"' already exists.");
		}

		return false;
	};

	Swapper.prototype.addPages=function(IDs) {
		for (var i=0, L=IDs.length; i<L; ++i)
			this.addPage(IDs[i]);
	};

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

	Swapper.prototype.setDefaultByID=function(ID) {
		var index = this.pagesIDs.indexOf(ID);

		if(index>-1) this.setDefaultByIndex(index);
		else throw "Swapper.js (ERR) - Invalid ID.";
	};

	Swapper.prototype.setDefaultByIndex=function(index) {
		if(typeof index == "number" && this.pagesCount > 0)
			this.defaultIndex = Math.max( Math.min(index, this.pagesCount-1), 0);
		else
			this.defaultIndex = null;
	};

	Swapper.prototype.clearDefault=function(){
		this.defaultIndex = null;
	};

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

	Swapper.prototype.selectByID=function(ID) {
		this.selectByIndex(this.pagesIDs.indexOf(ID));
	};

	Swapper.prototype.selectByIndex=function(index) {

		if( typeof index == "number" && index >=0 & index < this.pagesCount){

			// If there's a default element and we want to select the current one (already selected):
			if(this.currentIndex == index && this.defaultIndex != null) index = this.defaultIndex;

			if(this.anchorMode){
				window.location.hash="#"+this.pagesIDs[index];
			}
			else{
				if(this.currentIndex >=0)
					this.pagesDOM[this.currentIndex].classList.remove("currentPage");

				this.pagesDOM[index].classList.add("currentPage");
				this.currentIndex=index;
			}
		}
		else console.error("Swapper.js (ERR) - Invalid index.");
	};

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

	Swapper.prototype.selectNone=function() {
		if(this.anchorMode){
			window.location.hash = "";
		}
		else{
			if(this.currentIndex >=0)
				this.pagesDOM[this.currentIndex].classList.remove("currentPage");

			this.currentIndex=null;
		}
	};

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

	Swapper.prototype.kill=function(id){ // Page DOM id, not private one.
		var deadElement = document.getElementById(id);

		if(deadElement){
			deadElement.addEventListener(this.transitionEvent, function(e) {
				if(e.propertyName=="opacity"){
					e.target.remove();
				}
			});

			deadElement.classList.add("deadPage");
		}
	};

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

	global.Swapper = Swapper;

}(window));
<commit_msg>Some tiny performance improvements on:<commit_after>(function(global) {
	"use strict";

	/***************************************************************************
	 *	swapper.js:
	 *	A JS class to help you toggle the visibility of parts of your web project.
	 *
	 *	By Dani Gámez Franco, http://gmzcodes.com
	 *	Licensed under MIT.
	 *
	 *	Version: 1.1.1
	 *	Last Update: 2014-08-30
	 *
	 *	NOTE:
	 *	The current page class CAN NOT be changed programmatically. Search and
	 *	replace "currentPage" with the desired class name inside this file
	 *	instead or adapt your project to work with the default value.
	 *
	 *	Same thing for "deadPage" and "pageMe".
	 *
	 *	TO-DO:
	 *	 - Add a callback to call on transition end (with option to use delegation).
	 *	 - Add a parameter to use or not requestAnimationFrame.
	 *	 - Use parameters instead of strings for the classes used by swapper.js
	 *	   and add functions to change them programmatically (?).
	 *	 - Add a method to remove elements from the set.
	 *
	 **************************************************************************/

	// CONSTRUCTOR & (PUBLIC) VARIABLES ////////////////////////////////////////

	var Swapper = function(IDs, currentIndex, defaultIndex, anchorMode) {
		this.pagesIDs = [];
		this.pagesDOM = [];
		this.pagesCount=0;

		if(typeof IDs === "string"){
			if(IDs==="autoMODE"){ // Automatically seach for .pageMe elements.
				var elements=document.getElementsByClassName("pageMe");

				IDs = [];

				for(var i=0, L=elements.length; i<L; ++i)
					elements[i].id.length>0 && IDs[IDs.length] = elements[i].id;
			}
			else IDs = [IDs]; // Just one element added.
		}

		if(Object.prototype.toString.call( IDs ) === "[object Array]")
			this.addPages(IDs);
		else
			throw "Invalid argument 'IDs'.";

		// Current element:
		if(typeof currentIndex === "number" && this.pagesCount > 0)
			this.currentIndex = Math.max( Math.min(currentIndex, this.pagesCount-1), 0);
		else
			this.currentIndex = null;

		// Default element:
		this.setDefaultByIndex(defaultIndex);

		// Anchor mode:
		this.anchorMode = anchorMode?true:false;
	};

	// PROTOTYPE VARIABLES /////////////////////////////////////////////////////

	// Set transitionEvent property in the prototype. Code from Modernizr:
	Swapper.prototype.transitionEvent = (function(){
		"use strict";
		var t;
		var el = document.createElement('fakeelement');
		var transitions = {
		  'transition':'transitionend',
		  'OTransition':'oTransitionEnd',
		  'MozTransition':'transitionend',
		  'WebkitTransition':'webkitTransitionEnd'
		}

		for(t in transitions){
			if( el.style[t] !== undefined ){
				return transitions[t];
			}
		}
	})();

	// METHODS /////////////////////////////////////////////////////////////////

	Swapper.prototype.addPage=function(ID) {

		if(this.pagesIDs.indexOf(ID)==-1){

			var element=document.getElementById(ID);

			if(element){
				this.pagesIDs[pagesIDs.length] = ID;
				this.pagesDOM[pagesDOM.length] = element;

				++this.pagesCount;

				/*

				TO-DO: Maybe in future versions...

				element.addEventListener(this.transitionEvent, function(e) {

					if(e.propertyName=="opacity"){
						console.log(e.target.className);
						if(e.target.className=="hiddenPage"){
							e.target.className="hiddenPage";
						}
						else {
							console.log("VISIBLE");
							console.log(e.target);
						}
					}
				});

				*/

				return true;
			}
			else{
				console.error("Swapper.js (ERR) - No element with ID '"+ID+"' found.");
			}
		}
		else{
			console.error("Swapper.js (ERR) - Element with ID '"+ID+"' already exists.");
		}

		return false;
	};

	Swapper.prototype.addPages=function(IDs) {
		for (var i=0, L=IDs.length; i<L; ++i)
			this.addPage(IDs[i]);
	};

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

	Swapper.prototype.setDefaultByID=function(ID) {
		var index = this.pagesIDs.indexOf(ID);

		if(index>-1) this.setDefaultByIndex(index);
		else throw "Swapper.js (ERR) - Invalid ID.";
	};

	Swapper.prototype.setDefaultByIndex=function(index) {
		if(typeof index == "number" && this.pagesCount > 0)
			this.defaultIndex = Math.max( Math.min(index, this.pagesCount-1), 0);
		else
			this.defaultIndex = null;
	};

	Swapper.prototype.clearDefault=function(){
		this.defaultIndex = null;
	};

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

	Swapper.prototype.selectByID=function(ID) {
		this.selectByIndex(this.pagesIDs.indexOf(ID));
	};

	Swapper.prototype.selectByIndex=function(index) {

		if( typeof index == "number" && index >=0 & index < this.pagesCount){

			// If there's a default element and we want to select the current one (already selected):
			if(this.currentIndex == index && this.defaultIndex != null) index = this.defaultIndex;

			if(this.anchorMode){
				window.location.hash="#"+this.pagesIDs[index];
			}
			else{
				if(this.currentIndex >=0)
					this.pagesDOM[this.currentIndex].classList.remove("currentPage");

				this.pagesDOM[index].className += " currentPage";
				this.currentIndex=index;
			}
		}
		else console.error("Swapper.js (ERR) - Invalid index.");
	};

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

	Swapper.prototype.selectNone=function() {
		if(this.anchorMode){
			window.location.hash = "";
		}
		else{
			if(this.currentIndex >=0)
				this.pagesDOM[this.currentIndex].classList.remove("currentPage");

			this.currentIndex=null;
		}
	};

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

	Swapper.prototype.kill=function(id){ // Page DOM id, not private one.
		var deadElement = document.getElementById(id);

		if(deadElement){
			deadElement.addEventListener(this.transitionEvent, function(e) {
				if(e.propertyName=="opacity"){
					e.target.remove();
				}
			});

			deadElement.className += " deadPage";
		}
	};

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

	global.Swapper = Swapper;

}(window));
<|endoftext|>