<commit_before>import EventClass from "event-class-es6";

import uuid from "../graph/utils/uuid";
import htmlw from "./utils/htmlw";
import config from "./utils/config";
import RenderNodeFinder from "./utils/finder";
import RenderConnection from "./nodes/connection";

const _graph = Symbol("graph");
const _config = Symbol("config");
const _zoom = Symbol("zoomPan");
const _renderGroups = Symbol("renderGroups");
const _renderBlocks = Symbol("renderBlocks");
const _renderConnections = Symbol("renderConnections");
const _renderGroupIds = Symbol("renderGroupIds");
const _renderBlockIds = Symbol("renderBlockIds");
const _renderNodeFinder = Symbol("renderNodeFinder");
const _svg = Symbol("svg");
const _svgRoot = Symbol("svgRoot");
const _svgGroups = Symbol("svgGroups");
const _svgConnections = Symbol("svgConnections");
const _svgBlocks = Symbol("svgBlocks");

export default class Renderer extends EventClass {

    /**
     * Creates a renderer for the specified graph and svg element
     * @param {Graph} graph - specifies the graph
     * @param {Element} svg - specifies the svg element
     */
    constructor(graph, svg) {
        super();

        this[_graph] = graph;
        this[_config] = config;
        this[_zoom] = {"zoom": 1, "pan": [0, 0]};
        this[_renderGroups] = [];
        this[_renderBlocks] = [];
        this[_renderConnections] = [];
        this[_renderGroupIds] = {};
        this[_renderBlockIds] = {};
        this[_renderNodeFinder] = new RenderNodeFinder(this);
        this[_svg] = new htmlw(svg);
        this[_svgRoot] = this[_svg].append("svg:g");
        this[_svgGroups] = this[_svgRoot].append("svg:g").classed("dude-graph-groups");
        this[_svgConnections] = this[_svgRoot].append("svg:g").classed("dude-graph-connections");
        this[_svgBlocks] = this[_svgRoot].append("svg:g").classed("dude-graph-blocks");
    }

    /**
     * Returns this renderer fancy name
     * @returns {string}
     */
    get fancyName() { return "renderer (" + this[_renderBlocks].length + " render blocks)"; }

    /**
     * Returns this renderer config
     * @returns {Object}
     */
    get config() { return this[_config]; }
    /**
     * Sets this renderer config to the specified config
     * @param {Object} config - specifies the config
     */
    set config(config) { this[_config] = config; }
    /**
     * Returns this renderer render groups
     * @returns {Array<RenderGroup>}
     */
    get renderGroups() { return this[_renderGroups]; }
    /**
     * Returns this renderer render points
     * @returns {Array<RenderPoint>}
     */
    get renderPoints() {
        const renderPoints = [];
        this[_renderBlocks].forEach(rb => rb.renderPoints.forEach(rp => renderPoints.push(rp)));
        return renderPoints;
    }
    /**
     * Returns this renderer render blocks
     * @returns {Array<RenderBlock>}
     */
    get renderBlocks() { return this[_renderBlocks]; }
    /**
     * Returns this renderer render groups
     * @returns {Array<RenderConnection>}
     */
    get renderConnections() { return this[_renderConnections]; }
    /**
     * Returns this renderer render node finder
     * @returns {RenderNodeFinder}
     */
    get renderNodeFinder() { return this[_renderNodeFinder]; }
    /**
     * Returns this renderer svg element
     * @returns {SVGSVGElement}
     */
    get svg() { return this[_svg].element; }
    /**
     * Returns this renderer svg root element
     * @returns {SVGGElement}
     */
    get svgRoot() {return this[_svgRoot].element; }
    /**
     * Returns this renderer svg groups element
     * @returns {SVGGElement}
     */
    get svgGroups() {return this[_svgGroups].element; }
    /**
     * Returns this renderer svg blocks element
     * @returns {SVGGElement}
     */
    get svgBlocks() {return this[_svgBlocks].element; }
    /**
     * Returns this renderer svg connections element
     * @returns {SVGGElement}
     */
    get svgConnections() {return this[_svgConnections].element; }

    /**
     * Adds the specified render block to this renderer
     * @param {RenderBlock} renderBlock - specifies the render block
     */
    addRenderBlock(renderBlock) {
        if (renderBlock.block.graph !== this[_graph]) {
            throw new Error(this.fancyName + " cannot add a renderBlock bound to another graph");
        }
        if (renderBlock.id !== null && typeof this[_renderBlockIds][renderBlock.id] !== "undefined") {
            throw new Error(this.fancyName + " cannot redefine id " + renderBlock.id);
        }
        if (renderBlock.id === null) {
            renderBlock.id = renderBlock.block.id + "#" + uuid();
        }
        this[_renderBlocks].push(renderBlock);
        this[_renderBlockIds][renderBlock.id] = renderBlock;
        renderBlock.renderer = this;
        renderBlock.element = this[_svgBlocks].append("svg:g");
        renderBlock.element.attr("id", "bid-" + renderBlock.id);
        renderBlock.element.attr("class", "dude-graph-block");
        renderBlock.added();
        this.emit("render-block-add", renderBlock);
    }
    /**
     * Removes the specified render block from this renderer
     * @param {RenderBlock} renderBlock - specifies the render block
     */
    removeRenderBlock(renderBlock) {
        if (renderBlock.renderer !== this || !this[_renderBlocks].includes(renderBlock)) {
            throw new Error(this.fancyName + " has no render block " + renderBlock.fancyName);
        }
        if (renderBlock.parent !== null) {
            throw new Error(this.fancyName + " cannot remove render block with a parent");
        }
        renderBlock.removed();
        renderBlock.element.remove();
        this[_renderBlockIds][renderBlock.id] = undefined;
        this[_renderBlocks].splice(this[_renderBlocks].indexOf(renderBlock), 1);
        this.emit("render-block-remove", renderBlock);
    }
    /**
     * Returns the corresponding render block for the specified render block id
     * @param {string} renderBlockId - specifies the render block id
     * @returns {RenderBlock|null}
     */
    renderBlockById(renderBlockId) {
        return this[_renderBlocks].find(renderBlock => renderBlock.id === renderBlockId) || null;
    }
    /**
     * Returns the corresponding render blocks for the specified block
     * @param {Block} block - specifies the block
     * @returns {Array<RenderBlock>}
     */
    renderBlocksByBlock(block) {
        return this[_renderBlocks].filter(renderBlock => renderBlock.block === block);
    }

    /**
     * Adds the specified render group to this renderer
     * @param {RenderGroup} renderGroup - specifies the render group
     */
    addRenderGroup(renderGroup) {
        if (renderGroup.id !== null && typeof this[_renderGroupIds][renderGroup.id] !== "undefined") {
            throw new Error(this.fancyName + " cannot redefine id " + renderGroup.id);
        }
        if (renderGroup.id === null) {
            renderGroup.id = uuid();
        }
        renderGroup.renderer = this;
        this[_renderGroups].push(renderGroup);
        this[_renderGroupIds][renderGroup.id] = renderGroup;
        renderGroup.element = this[_svgGroups].append("svg:g");
        renderGroup.element.attr("id", "gid-" + renderGroup.id);
        renderGroup.element.attr("class", "dude-graph-group");
        renderGroup.added();
        this.emit("render-group-add", renderGroup);
    }
    /**
     * Removes the specified render group from this renderer
     * @param {RenderGroup} renderGroup - specifies the render group
     */
    removeRenderGroup(renderGroup) {
        if (renderGroup.renderer !== this || !this[_renderGroups].includes(renderGroup)) {
            throw new Error(this.fancyName + " has no render block " + renderGroup.fancyName);
        }
        if (renderGroup.renderBlocks.length > 0) {
            throw new Error(this.fancyName + " cannot remove render group with render blocks");
        }
        renderGroup.removed();
        renderGroup.element.remove();
        this[_renderGroupIds][renderGroup.id] = undefined;
        this[_renderGroups].splice(this[_renderGroups].indexOf(renderGroup), 1);
        this.emit("render-group-remove", renderGroup);
    }
    /**
     * Returns the corresponding render group for the specified render group id
     * @param {string} renderGroupId - specifies the render group id
     * @returns {RenderGroup|null}
     */
    renderGroupById(renderGroupId) {
        return this[_renderGroups].find(renderGroup => renderGroup.id === renderGroupId) || null;
    }

    /**
     * Connects the specified output render point to the specified input render point
     * @param {RenderPoint} inputRenderPoint - specifies the input render point
     * @param {RenderPoint} outputRenderPoint - specifies the output render point
     * @returns {RenderConnection}
     */
    connect(inputRenderPoint, outputRenderPoint) {
        if (outputRenderPoint.renderBlock === null) {
            throw new Error(outputRenderPoint.fancyName +
                " cannot connect to another render point when not bound to a render block");
        }
        if (inputRenderPoint.renderBlock === null) {
            throw new Error(inputRenderPoint.fancyName +
                " cannot connect to another render point when not bound to a render block");
        }
        if (outputRenderPoint.renderBlock.renderer !== this) {
            throw new Error(outputRenderPoint.fancyName + " is not in this renderer");
        }
        if (inputRenderPoint.renderBlock.renderer !== this) {
            throw new Error(inputRenderPoint.fancyName + " is not in this renderer");
        }
        if (!outputRenderPoint.point.output) {
            throw new Error(outputRenderPoint.fancyName + " is not an output");
        }
        if (inputRenderPoint.point.output) {
            throw new Error(inputRenderPoint.fancyName + " is not an input");
        }
        const connection = this[_graph].connectionForPoints(inputRenderPoint.point, outputRenderPoint.point);
        if (connection === null) {
            throw new Error(outputRenderPoint.point.fancyName +
                " is not connected to " + inputRenderPoint.point.fancyName);
        }
        const renderConnectionFound = this.renderConnectionsForRenderPoints(inputRenderPoint, outputRenderPoint);
        if (renderConnectionFound !== null) {
            throw new Error(this.fancyName + " cannot redefine " + renderConnectionFound.fancyName);
        }
        const renderConnection = new RenderConnection(connection, inputRenderPoint, outputRenderPoint);
        this[_renderConnections].push(renderConnection);
        outputRenderPoint.addRenderConnection(renderConnection);
        inputRenderPoint.addRenderConnection(renderConnection);
        renderConnection.renderer = this;
        renderConnection.element = this[_svgConnections].append("svg:path").attr("class", "dude-graph-connection");
        renderConnection.added();
        this.emit("connect", renderConnection);
        return renderConnection;
    }
    /**
     * Disconnects the specified output render point from the specified input render point
     * @param {RenderPoint} inputRenderPoint - specifies the input render point
     * @param {RenderPoint} outputRenderPoint - specifies the output render point
     */
    disconnect(inputRenderPoint, outputRenderPoint) {
        if (inputRenderPoint.renderBlock === null) {
            throw new Error(inputRenderPoint.fancyName +
                " cannot connect to another render point when not bound to a render block");
        }
        if (outputRenderPoint.renderBlock === null) {
            throw new Error(outputRenderPoint.fancyName +
                " cannot connect to another render point when not bound to a render block");
        }
        if (inputRenderPoint.renderBlock.renderer !== this) {
            throw new Error(inputRenderPoint.fancyName + " is not in this renderer");
        }
        if (outputRenderPoint.renderBlock.renderer !== this) {
            throw new Error(outputRenderPoint.fancyName + " is not in this renderer");
        }
        if (!inputRenderPoint.point.input) {
            throw new Error(inputRenderPoint.fancyName + " is not an input");
        }
        if (!outputRenderPoint.point.output) {
            throw new Error(outputRenderPoint.fancyName + " is not an output");
        }
        const renderConnection = this.renderConnectionsForRenderPoints(inputRenderPoint, outputRenderPoint);
        if (renderConnection === null) {
            throw new Error(this.fancyName + " cannot find a render connection between " +
                outputRenderPoint.fancyName + " and " + inputRenderPoint.fancyName);
        }
        inputRenderPoint.removeRenderConnection(renderConnection);
        outputRenderPoint.removeRenderConnection(renderConnection);
        this[_renderConnections].splice(this[_renderConnections].indexOf(renderConnection), 1);
        renderConnection.removed();
        renderConnection.element.remove();
        renderConnection.renderer = null;
        this.emit("disconnect", renderConnection);
    }
    /**
     * Returns the render connection between the specified output render point from the specified input render point
     * @param {RenderPoint} inputRenderPoint - specifies the input render point
     * @param {RenderPoint} outputRenderPoint - specifies the output render point
     * @returns {RenderConnection|null}
     */
    renderConnectionsForRenderPoints(inputRenderPoint, outputRenderPoint) {
        return this[_renderConnections].find((rc) => {
                return rc.inputRenderPoint === inputRenderPoint && rc.outputRenderPoint === outputRenderPoint;
            }) || null;
    }

}
<commit_msg>Return the HTMLWrapped svg elements to be consistent<commit_after>import EventClass from "event-class-es6";

import uuid from "../graph/utils/uuid";
import htmlw from "./utils/htmlw";
import config from "./utils/config";
import RenderNodeFinder from "./utils/finder";
import RenderConnection from "./nodes/connection";

const _graph = Symbol("graph");
const _config = Symbol("config");
const _zoom = Symbol("zoomPan");
const _renderGroups = Symbol("renderGroups");
const _renderBlocks = Symbol("renderBlocks");
const _renderConnections = Symbol("renderConnections");
const _renderGroupIds = Symbol("renderGroupIds");
const _renderBlockIds = Symbol("renderBlockIds");
const _renderNodeFinder = Symbol("renderNodeFinder");
const _svg = Symbol("svg");
const _svgRoot = Symbol("svgRoot");
const _svgGroups = Symbol("svgGroups");
const _svgConnections = Symbol("svgConnections");
const _svgBlocks = Symbol("svgBlocks");

export default class Renderer extends EventClass {

    /**
     * Creates a renderer for the specified graph and svg element
     * @param {Graph} graph - specifies the graph
     * @param {Element} svg - specifies the svg element
     */
    constructor(graph, svg) {
        super();

        this[_graph] = graph;
        this[_config] = config;
        this[_zoom] = {"zoom": 1, "pan": [0, 0]};
        this[_renderGroups] = [];
        this[_renderBlocks] = [];
        this[_renderConnections] = [];
        this[_renderGroupIds] = {};
        this[_renderBlockIds] = {};
        this[_renderNodeFinder] = new RenderNodeFinder(this);
        this[_svg] = new htmlw(svg);
        this[_svgRoot] = this[_svg].append("svg:g");
        this[_svgGroups] = this[_svgRoot].append("svg:g").classed("dude-graph-groups");
        this[_svgConnections] = this[_svgRoot].append("svg:g").classed("dude-graph-connections");
        this[_svgBlocks] = this[_svgRoot].append("svg:g").classed("dude-graph-blocks");
    }

    /**
     * Returns this renderer fancy name
     * @returns {string}
     */
    get fancyName() { return "renderer (" + this[_renderBlocks].length + " render blocks)"; }

    /**
     * Returns this renderer config
     * @returns {Object}
     */
    get config() { return this[_config]; }
    /**
     * Sets this renderer config to the specified config
     * @param {Object} config - specifies the config
     */
    set config(config) { this[_config] = config; }
    /**
     * Returns this renderer render groups
     * @returns {Array<RenderGroup>}
     */
    get renderGroups() { return this[_renderGroups]; }
    /**
     * Returns this renderer render points
     * @returns {Array<RenderPoint>}
     */
    get renderPoints() {
        const renderPoints = [];
        this[_renderBlocks].forEach(rb => rb.renderPoints.forEach(rp => renderPoints.push(rp)));
        return renderPoints;
    }
    /**
     * Returns this renderer render blocks
     * @returns {Array<RenderBlock>}
     */
    get renderBlocks() { return this[_renderBlocks]; }
    /**
     * Returns this renderer render groups
     * @returns {Array<RenderConnection>}
     */
    get renderConnections() { return this[_renderConnections]; }
    /**
     * Returns this renderer render node finder
     * @returns {RenderNodeFinder}
     */
    get renderNodeFinder() { return this[_renderNodeFinder]; }
    /**
     * Returns this renderer svg element
     * @returns {HTMLWrapper}
     */
    get svg() { return this[_svg]; }
    /**
     * Returns this renderer svg root element
     * @returns {HTMLWrapper}
     */
    get svgRoot() {return this[_svgRoot]; }
    /**
     * Returns this renderer svg groups element
     * @returns {HTMLWrapper}
     */
    get svgGroups() {return this[_svgGroups]; }
    /**
     * Returns this renderer svg blocks element
     * @returns {HTMLWrapper}
     */
    get svgBlocks() {return this[_svgBlocks]; }
    /**
     * Returns this renderer svg connections element
     * @returns {HTMLWrapper}
     */
    get svgConnections() {return this[_svgConnections]; }

    /**
     * Adds the specified render block to this renderer
     * @param {RenderBlock} renderBlock - specifies the render block
     */
    addRenderBlock(renderBlock) {
        if (renderBlock.block.graph !== this[_graph]) {
            throw new Error(this.fancyName + " cannot add a renderBlock bound to another graph");
        }
        if (renderBlock.id !== null && typeof this[_renderBlockIds][renderBlock.id] !== "undefined") {
            throw new Error(this.fancyName + " cannot redefine id " + renderBlock.id);
        }
        if (renderBlock.id === null) {
            renderBlock.id = renderBlock.block.id + "#" + uuid();
        }
        this[_renderBlocks].push(renderBlock);
        this[_renderBlockIds][renderBlock.id] = renderBlock;
        renderBlock.renderer = this;
        renderBlock.element = this[_svgBlocks].append("svg:g");
        renderBlock.element.attr("id", "bid-" + renderBlock.id);
        renderBlock.element.attr("class", "dude-graph-block");
        renderBlock.added();
        this.emit("render-block-add", renderBlock);
    }
    /**
     * Removes the specified render block from this renderer
     * @param {RenderBlock} renderBlock - specifies the render block
     */
    removeRenderBlock(renderBlock) {
        if (renderBlock.renderer !== this || !this[_renderBlocks].includes(renderBlock)) {
            throw new Error(this.fancyName + " has no render block " + renderBlock.fancyName);
        }
        if (renderBlock.parent !== null) {
            throw new Error(this.fancyName + " cannot remove render block with a parent");
        }
        renderBlock.removed();
        renderBlock.element.remove();
        this[_renderBlockIds][renderBlock.id] = undefined;
        this[_renderBlocks].splice(this[_renderBlocks].indexOf(renderBlock), 1);
        this.emit("render-block-remove", renderBlock);
    }
    /**
     * Returns the corresponding render block for the specified render block id
     * @param {string} renderBlockId - specifies the render block id
     * @returns {RenderBlock|null}
     */
    renderBlockById(renderBlockId) {
        return this[_renderBlocks].find(renderBlock => renderBlock.id === renderBlockId) || null;
    }
    /**
     * Returns the corresponding render blocks for the specified block
     * @param {Block} block - specifies the block
     * @returns {Array<RenderBlock>}
     */
    renderBlocksByBlock(block) {
        return this[_renderBlocks].filter(renderBlock => renderBlock.block === block);
    }

    /**
     * Adds the specified render group to this renderer
     * @param {RenderGroup} renderGroup - specifies the render group
     */
    addRenderGroup(renderGroup) {
        if (renderGroup.id !== null && typeof this[_renderGroupIds][renderGroup.id] !== "undefined") {
            throw new Error(this.fancyName + " cannot redefine id " + renderGroup.id);
        }
        if (renderGroup.id === null) {
            renderGroup.id = uuid();
        }
        renderGroup.renderer = this;
        this[_renderGroups].push(renderGroup);
        this[_renderGroupIds][renderGroup.id] = renderGroup;
        renderGroup.element = this[_svgGroups].append("svg:g");
        renderGroup.element.attr("id", "gid-" + renderGroup.id);
        renderGroup.element.attr("class", "dude-graph-group");
        renderGroup.added();
        this.emit("render-group-add", renderGroup);
    }
    /**
     * Removes the specified render group from this renderer
     * @param {RenderGroup} renderGroup - specifies the render group
     */
    removeRenderGroup(renderGroup) {
        if (renderGroup.renderer !== this || !this[_renderGroups].includes(renderGroup)) {
            throw new Error(this.fancyName + " has no render block " + renderGroup.fancyName);
        }
        if (renderGroup.renderBlocks.length > 0) {
            throw new Error(this.fancyName + " cannot remove render group with render blocks");
        }
        renderGroup.removed();
        renderGroup.element.remove();
        this[_renderGroupIds][renderGroup.id] = undefined;
        this[_renderGroups].splice(this[_renderGroups].indexOf(renderGroup), 1);
        this.emit("render-group-remove", renderGroup);
    }
    /**
     * Returns the corresponding render group for the specified render group id
     * @param {string} renderGroupId - specifies the render group id
     * @returns {RenderGroup|null}
     */
    renderGroupById(renderGroupId) {
        return this[_renderGroups].find(renderGroup => renderGroup.id === renderGroupId) || null;
    }

    /**
     * Connects the specified output render point to the specified input render point
     * @param {RenderPoint} inputRenderPoint - specifies the input render point
     * @param {RenderPoint} outputRenderPoint - specifies the output render point
     * @returns {RenderConnection}
     */
    connect(inputRenderPoint, outputRenderPoint) {
        if (outputRenderPoint.renderBlock === null) {
            throw new Error(outputRenderPoint.fancyName +
                " cannot connect to another render point when not bound to a render block");
        }
        if (inputRenderPoint.renderBlock === null) {
            throw new Error(inputRenderPoint.fancyName +
                " cannot connect to another render point when not bound to a render block");
        }
        if (outputRenderPoint.renderBlock.renderer !== this) {
            throw new Error(outputRenderPoint.fancyName + " is not in this renderer");
        }
        if (inputRenderPoint.renderBlock.renderer !== this) {
            throw new Error(inputRenderPoint.fancyName + " is not in this renderer");
        }
        if (!outputRenderPoint.point.output) {
            throw new Error(outputRenderPoint.fancyName + " is not an output");
        }
        if (inputRenderPoint.point.output) {
            throw new Error(inputRenderPoint.fancyName + " is not an input");
        }
        const connection = this[_graph].connectionForPoints(inputRenderPoint.point, outputRenderPoint.point);
        if (connection === null) {
            throw new Error(outputRenderPoint.point.fancyName +
                " is not connected to " + inputRenderPoint.point.fancyName);
        }
        const renderConnectionFound = this.renderConnectionsForRenderPoints(inputRenderPoint, outputRenderPoint);
        if (renderConnectionFound !== null) {
            throw new Error(this.fancyName + " cannot redefine " + renderConnectionFound.fancyName);
        }
        const renderConnection = new RenderConnection(connection, inputRenderPoint, outputRenderPoint);
        this[_renderConnections].push(renderConnection);
        outputRenderPoint.addRenderConnection(renderConnection);
        inputRenderPoint.addRenderConnection(renderConnection);
        renderConnection.renderer = this;
        renderConnection.element = this[_svgConnections].append("svg:path").attr("class", "dude-graph-connection");
        renderConnection.added();
        this.emit("connect", renderConnection);
        return renderConnection;
    }
    /**
     * Disconnects the specified output render point from the specified input render point
     * @param {RenderPoint} inputRenderPoint - specifies the input render point
     * @param {RenderPoint} outputRenderPoint - specifies the output render point
     */
    disconnect(inputRenderPoint, outputRenderPoint) {
        if (inputRenderPoint.renderBlock === null) {
            throw new Error(inputRenderPoint.fancyName +
                " cannot connect to another render point when not bound to a render block");
        }
        if (outputRenderPoint.renderBlock === null) {
            throw new Error(outputRenderPoint.fancyName +
                " cannot connect to another render point when not bound to a render block");
        }
        if (inputRenderPoint.renderBlock.renderer !== this) {
            throw new Error(inputRenderPoint.fancyName + " is not in this renderer");
        }
        if (outputRenderPoint.renderBlock.renderer !== this) {
            throw new Error(outputRenderPoint.fancyName + " is not in this renderer");
        }
        if (!inputRenderPoint.point.input) {
            throw new Error(inputRenderPoint.fancyName + " is not an input");
        }
        if (!outputRenderPoint.point.output) {
            throw new Error(outputRenderPoint.fancyName + " is not an output");
        }
        const renderConnection = this.renderConnectionsForRenderPoints(inputRenderPoint, outputRenderPoint);
        if (renderConnection === null) {
            throw new Error(this.fancyName + " cannot find a render connection between " +
                outputRenderPoint.fancyName + " and " + inputRenderPoint.fancyName);
        }
        inputRenderPoint.removeRenderConnection(renderConnection);
        outputRenderPoint.removeRenderConnection(renderConnection);
        this[_renderConnections].splice(this[_renderConnections].indexOf(renderConnection), 1);
        renderConnection.removed();
        renderConnection.element.remove();
        renderConnection.renderer = null;
        this.emit("disconnect", renderConnection);
    }
    /**
     * Returns the render connection between the specified output render point from the specified input render point
     * @param {RenderPoint} inputRenderPoint - specifies the input render point
     * @param {RenderPoint} outputRenderPoint - specifies the output render point
     * @returns {RenderConnection|null}
     */
    renderConnectionsForRenderPoints(inputRenderPoint, outputRenderPoint) {
        return this[_renderConnections].find((rc) => {
                return rc.inputRenderPoint === inputRenderPoint && rc.outputRenderPoint === outputRenderPoint;
            }) || null;
    }

}
<|endoftext|>


<commit_before>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 * @format
 */

const {dirname, join, resolve} = require('path');

const FLOW_ROOT = resolve(__dirname, '../../../');
const defaultTestsDirName = 'newtests';

// This is where we look for tests to run and where we put newly converted
// tests
function getTestsDir(relative_to?: string): string {
  if (relative_to !== undefined) {
    return resolve(relative_to, defaultTestsDirName);
  } else {
    return dirname(require.resolve(join(defaultTestsDirName, 'package.json')));
  }
}

const binOptions: Array<string> = [
  resolve(FLOW_ROOT, 'bin/flow'), // Open source build
  resolve(FLOW_ROOT, 'bin/flow.exe'), // Open source windows build
  resolve(FLOW_ROOT, '../buck-out/gen/flow/flow/flow'), // Buck
];

const defaultFlowConfigName = '_flowconfig';

module.exports = {
  defaultTestsDirName,
  getTestsDir,
  binOptions,
  defaultFlowConfigName,
};
<commit_msg>prefer buck build over OSS build when using tool test<commit_after>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 * @format
 */

const {dirname, join, resolve} = require('path');

const FLOW_ROOT = resolve(__dirname, '../../../');
const defaultTestsDirName = 'newtests';

// This is where we look for tests to run and where we put newly converted
// tests
function getTestsDir(relative_to?: string): string {
  if (relative_to !== undefined) {
    return resolve(relative_to, defaultTestsDirName);
  } else {
    return dirname(require.resolve(join(defaultTestsDirName, 'package.json')));
  }
}

const binOptions: Array<string> = [
  resolve(FLOW_ROOT, '../buck-out/gen/flow/flow/flow'), // Buck
  resolve(FLOW_ROOT, 'bin/flow'), // Open source build
  resolve(FLOW_ROOT, 'bin/flow.exe'), // Open source windows build
];

const defaultFlowConfigName = '_flowconfig';

module.exports = {
  defaultTestsDirName,
  getTestsDir,
  binOptions,
  defaultFlowConfigName,
};
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import PropTypes from 'prop-types'
import htmlescape from 'htmlescape'
import flush from 'styled-jsx/server'

export default class Document extends Component {
  static getInitialProps ({ renderPage }) {
    const { html, head, errorHtml, chunks } = renderPage()
    const styles = flush()
    return { html, head, errorHtml, chunks, styles }
  }

  static childContextTypes = {
    _documentProps: PropTypes.any
  }

  getChildContext () {
    return { _documentProps: this.props }
  }

  render () {
    return

        <NextScript />

  }
}

export class Head extends Component {
  static contextTypes = {
    _documentProps: PropTypes.any
  }

  getChunkPreloadLink (filename) {
    const { __NEXT_DATA__ } = this.context._documentProps
    let { buildStats, assetPrefix, buildId } = __NEXT_DATA__
    const hash = buildStats ? buildStats[filename].hash : buildId

    return (
      <link
        key={filename}
        rel='preload'
        href={`${assetPrefix}/_next/${hash}/${filename}`}
        as='script'
      />
    )
  }

  getPreloadMainLinks () {
    const { dev } = this.context._documentProps
    if (dev) {
      return [
        this.getChunkPreloadLink('manifest.js'),
        this.getChunkPreloadLink('commons.js'),
        this.getChunkPreloadLink('main.js')
      ]
    }

    // In the production mode, we have a single asset with all the JS content.
    return [
      this.getChunkPreloadLink('app.js')
    ]
  }

  getPreloadDynamicChunks () {
    const { chunks, __NEXT_DATA__ } = this.context._documentProps
    let { assetPrefix, buildId } = __NEXT_DATA__
    return chunks.map((chunk) => (
      <link
        key={chunk}
        rel='preload'
        href={`${assetPrefix}/_next/${buildId}/webpack/chunks/${chunk}`}
        as='script'
      />
    ))
  }

  render () {
    const { head, styles, __NEXT_DATA__ } = this.context._documentProps
    const { pathname, buildId, assetPrefix, nextExport } = __NEXT_DATA__
    const pagePathname = getPagePathname(pathname, nextExport)

    return
      <link rel='preload' href={`${assetPrefix}/_next/${buildId}/page${pagePathname}`} as='script' />
      <link rel='preload' href={`${assetPrefix}/_next/${buildId}/page/_error/index.js`} as='script' />
      {this.getPreloadDynamicChunks()}
      {this.getPreloadMainLinks()}
      {(head || []).map((h, i) => React.cloneElement(h, { key: h.key || i }))}
      {styles || null}
      {this.props.children}

  }
}

export class Main extends Component {
  static propTypes = {
    className: PropTypes.string
  }

  static contextTypes = {
    _documentProps: PropTypes.any
  }

  render () {
    const { html, errorHtml } = this.context._documentProps
    const { className } = this.props
    return (

    )
  }
}

export class NextScript extends Component {
  static propTypes = {
    nonce: PropTypes.string
  }

  static contextTypes = {
    _documentProps: PropTypes.any
  }

  getChunkScript (filename, additionalProps = {}) {
    const { __NEXT_DATA__ } = this.context._documentProps
    let { buildStats, assetPrefix, buildId } = __NEXT_DATA__
    const hash = buildStats ? buildStats[filename].hash : buildId

    return (


<commit_before>/* See license.txt for terms of usage */

define([], function() {

// ********************************************************************************************* //
// Firebug Trace - FBTrace

var scope = {};

try
{
    Components.utils["import"]("resource://fbtrace/firebug-trace-service.js", scope);
}
catch (err)
{
    Components.utils.reportError("FBTrace is not installed, use empty implementation");

    scope.traceConsoleService =
    {
        getTracer: function(prefDomain)
        {
            var TraceAPI = ["dump", "sysout", "setScope", "matchesNode", "time", "timeEnd"];
            var TraceObj = {};
            for (var i=0; i<TraceAPI.length; i++)
                TraceObj[TraceAPI[i]] = function() {};
            return TraceObj;
        }
    };
}

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

return scope.traceConsoleService.getTracer("extensions.firebug");

// ********************************************************************************************* //
});
<commit_msg>[1.9] Put Components.utils to a constant<commit_after>/* See license.txt for terms of usage */

define([], function() {

//********************************************************************************************* //
//Constants

const Cu = Components.utils;

// ********************************************************************************************* //
// Firebug Trace - FBTrace

var scope = {};

try
{
    Cu["import"]("resource://fbtrace/firebug-trace-service.js", scope);
}
catch (err)
{
    Cu.reportError("FBTrace is not installed, use empty implementation");

    scope.traceConsoleService =
    {
        getTracer: function(prefDomain)
        {
            var TraceAPI = ["dump", "sysout", "setScope", "matchesNode", "time", "timeEnd"];
            var TraceObj = {};
            for (var i=0; i<TraceAPI.length; i++)
                TraceObj[TraceAPI[i]] = function() {};
            return TraceObj;
        }
    };
}

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

return scope.traceConsoleService.getTracer("extensions.firebug");

// ********************************************************************************************* //
});<|endoftext|>


<commit_before>(function ($) {
    'use strict';

    $(document).ready(function() {

        $('.sylius-sortable-list').sortable({
            forceFallback: true,
            onEnd: function (event) {
                $(this).api({
                    throttle: 500,
                    method: 'PUT',
                    action: 'move taxon',
                    on: 'now',
                    urlData: {
                        id: $(event.item).data('id')
                    },
                    beforeSend: function (settings) {
                        settings.data = {
                            position: event.newIndex
                        };

                        return settings;
                    },
                    onSuccess: function (response) {
                        $(event.item).find('.sylius-taxon-move-up').data('position', event.newIndex);
                        $(event.item).find('.sylius-taxon-move-down').data('position', event.newIndex);
                    },
                    onFailure: function (response) {
                        throw 'Something went wrong with api call.';
                    }
                });
            }
        });

        $('.sylius-taxon-move-up').api({
            method: 'PUT',
            on: 'click',
            beforeSend: function (settings) {
                settings.data = {
                    position: $(this).data('position') - 1
                };

                return settings;
            },
            onSuccess: function (response) {
                location.reload();
            }
        });

        $('.sylius-taxon-move-down').api({
            method: 'PUT',
            on: 'click',
            beforeSend: function (settings) {
                settings.data = {
                    position: $(this).data('position') + 1
                };

                return settings;
            },
            onSuccess: function (response) {
                location.reload();
            }
        });
    });
})( jQuery );
<commit_msg>[Behat] Fix wait for methods<commit_after>(function ($) {
    'use strict';

    $(document).ready(function() {

        $('.sylius-sortable-list').sortable({
            forceFallback: true,
            onStart: function (event) {
                $(event.item).addClass('dragging-started');
            },
            onEnd: function (event) {
                $(event.item).removeClass('dragging-started');
                $(this).api({
                    throttle: 500,
                    method: 'PUT',
                    action: 'move taxon',
                    on: 'now',
                    urlData: {
                        id: $(event.item).data('id')
                    },
                    beforeSend: function (settings) {
                        settings.data = {
                            position: event.newIndex
                        };

                        return settings;
                    },
                    onSuccess: function (response) {
                        $(event.item).find('.sylius-taxon-move-up').data('position', event.newIndex);
                        $(event.item).find('.sylius-taxon-move-down').data('position', event.newIndex);
                    },
                    onFailure: function (response) {
                        throw 'Something went wrong with api call.';
                    }
                });
            }
        });

        $('.sylius-taxon-move-up').api({
            method: 'PUT',
            on: 'click',
            beforeSend: function (settings) {
                settings.data = {
                    position: $(this).data('position') - 1
                };

                return settings;
            },
            onSuccess: function (response) {
                location.reload();
            }
        });

        $('.sylius-taxon-move-down').api({
            method: 'PUT',
            on: 'click',
            beforeSend: function (settings) {
                settings.data = {
                    position: $(this).data('position') + 1
                };

                return settings;
            },
            onSuccess: function (response) {
                location.reload();
            }
        });
    });
})( jQuery );
<|endoftext|>


<commit_before>(function () {
  'use strict';

  angular
    .module('core')
    .run(menuConfig);

  menuConfig.$inject = ['menuService'];

  function menuConfig(menuService) {
    menuService.addMenu('account', {
      roles: ['user']
    });

    menuService.addMenuItem('account', {
      title: '',
      state: 'settings',
      type: 'dropdown',
      roles: ['user']
    });

    menuService.addSubMenuItem('account', 'settings', {
      title: 'Edit Profile',
      state: 'settings.profile'
    });

    if (window.features.swu) menuService.addSubMenuItem('account', 'settings', {
      title: 'Messages',
      state: 'settings.messages'
    });

  }
}());
<commit_msg>User dropdown menu: Profile<commit_after>(function () {
  'use strict';

  angular
    .module('core')
    .run(menuConfig);

  menuConfig.$inject = ['menuService'];

  function menuConfig(menuService) {
    menuService.addMenu('account', {
      roles: ['user']
    });

    menuService.addMenuItem('account', {
      title: '',
      state: 'settings',
      type: 'dropdown',
      roles: ['user']
    });

    menuService.addSubMenuItem('account', 'settings', {
      title: 'Profile',
      state: 'settings.profile'
    });

    if (window.features.swu) menuService.addSubMenuItem('account', 'settings', {
      title: 'Messages',
      state: 'settings.messages'
    });

  }
}());
<|endoftext|>


<commit_before><commit_msg>Add tape test hooks<commit_after><|endoftext|>


<commit_before>'use strict';

var expect = require('chai').expect;

var colCache = require('../../../lib/utils/col-cache');

describe('colCache', function() {
  it('caches values', function() {
    expect(colCache.l2n('A')).to.equal(1);
    expect(colCache._l2n.A).to.equal(1);
    expect(colCache._n2l[1]).to.equal('A');

    // also, because of the fill heuristic A-Z will be there too
    var dic = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
    dic.forEach(function(letter, index) {
      expect(colCache._l2n[letter]).to.equal(index + 1);
      expect(colCache._n2l[index + 1]).to.equal(letter);
    });

    // next level
    expect(colCache.n2l(27)).to.equal('AA');
    expect(colCache._l2n.AB).to.equal(28);
    expect(colCache._n2l[28]).to.equal('AB');
  });

  it('converts numbers to letters', function() {
    expect(colCache.n2l(1)).to.equal('A');
    expect(colCache.n2l(26)).to.equal('Z');
    expect(colCache.n2l(27)).to.equal('AA');
    expect(colCache.n2l(702)).to.equal('ZZ');
    expect(colCache.n2l(703)).to.equal('AAA');
  });
  it('converts letters to numbers', function() {
    expect(colCache.l2n('A')).to.equal(1);
    expect(colCache.l2n('Z')).to.equal(26);
    expect(colCache.l2n('AA')).to.equal(27);
    expect(colCache.l2n('ZZ')).to.equal(702);
    expect(colCache.l2n('AAA')).to.equal(703);
  });

  it('throws when out of bounds', function() {
    expect(function() { colCache.n2l(0); }).to.throw(Error);
    expect(function() { colCache.n2l(-1); }).to.throw(Error);
    expect(function() { colCache.n2l(16385); }).to.throw(Error);

    expect(function() { colCache.l2n(''); }).to.throw(Error);
    expect(function() { colCache.l2n('AAAA'); }).to.throw(Error);
    expect(function() { colCache.l2n(16385); }).to.throw(Error);
  });

  it('validates addresses properly', function() {
    expect(colCache.validateAddress('A1')).to.be.ok();
    expect(colCache.validateAddress('AA10')).to.be.ok();
    expect(colCache.validateAddress('ABC100000')).to.be.ok();

    expect(function() { colCache.validateAddress('A'); }).to.throw(Error);
    expect(function() { colCache.validateAddress('1'); }).to.throw(Error);
    expect(function() { colCache.validateAddress('1A'); }).to.throw(Error);
    expect(function() { colCache.validateAddress('A 1'); }).to.throw(Error);
    expect(function() { colCache.validateAddress('A1A'); }).to.throw(Error);
    expect(function() { colCache.validateAddress('1A1'); }).to.throw(Error);
    expect(function() { colCache.validateAddress('a1'); }).to.throw(Error);
    expect(function() { colCache.validateAddress('a'); }).to.throw(Error);
  });

  it('decodes addresses', function() {
    expect(colCache.decodeAddress('A1')).to.deep.equal({address: 'A1', col: 1, row: 1, $col$row: '$A$1'});
    expect(colCache.decodeAddress('AA11')).to.deep.equal({address: 'AA11', col: 27, row: 11, $col$row: '$AA$11'});

    it('convert [sheetName!][$]col[$]row[[$]col[$]row] into address or range structures', function() {
      expect(colCache.decodeEx('Sheet1!$H$1')).to.deep.equal({$col$row: '$H$1', address: 'H1', col: 8, row: 1, sheetName: 'Sheet1'});
      expect(colCache.decodeEx("'Sheet 1'!$H$1")).to.deep.equal({$col$row: '$H$1', address: 'H1', col: 8, row: 1, sheetName: 'Sheet 1'});
      expect(colCache.decodeEx("'Sheet !$:1'!$H$1")).to.deep.equal({$col$row: '$H$1', address: 'H1', col: 8, row: 1, sheetName: 'Sheet !$:1'});
      expect(colCache.decodeEx("'Sheet !$:1'!#REF!")).to.deep.equal({sheetName: 'Sheet !$:1', error: '#REF!'});
    });
  });

  it('gets address structures (and caches them)', function() {
    var addr = colCache.getAddress('D5');
    expect(addr.address).to.equal('D5');
    expect(addr.row).to.equal(5);
    expect(addr.col).to.equal(4);
    expect(colCache.getAddress('D5')).to.equal(addr);
    expect(colCache.getAddress(5, 4)).to.equal(addr);

    addr = colCache.getAddress('E4');
    expect(addr.address).to.equal('E4');
    expect(addr.row).to.equal(4);
    expect(addr.col).to.equal(5);
    expect(colCache.getAddress('E4')).to.equal(addr);
    expect(colCache.getAddress(4, 5)).to.equal(addr);
  });

  it('decodes addresses and ranges', function() {
    // address
    expect(colCache.decode('A1')).to.deep.equal({address: 'A1', col: 1, row: 1, $col$row: '$A$1'});
    expect(colCache.decode('AA11')).to.deep.equal({address: 'AA11', col: 27, row: 11, $col$row: '$AA$11'});

    // range
    expect(colCache.decode('A1:B2')).to.deep.equal({
      dimensions: 'A1:B2',
      tl: 'A1',
      br: 'B2',
      top: 1,
      left: 1,
      bottom: 2,
      right: 2
    });

    // wonky ranges
    expect(colCache.decode('A2:B1')).to.deep.equal({
      dimensions: 'A1:B2',
      tl: 'A1',
      br: 'B2',
      top: 1,
      left: 1,
      bottom: 2,
      right: 2
    });
    expect(colCache.decode('B2:A1')).to.deep.equal({
      dimensions: 'A1:B2',
      tl: 'A1',
      br: 'B2',
      top: 1,
      left: 1,
      bottom: 2,
      right: 2
    });
  });
});
<commit_msg>Fix misplaced it(...) in test<commit_after>'use strict';

var expect = require('chai').expect;

var colCache = require('../../../lib/utils/col-cache');

describe('colCache', function() {
  it('caches values', function() {
    expect(colCache.l2n('A')).to.equal(1);
    expect(colCache._l2n.A).to.equal(1);
    expect(colCache._n2l[1]).to.equal('A');

    // also, because of the fill heuristic A-Z will be there too
    var dic = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
    dic.forEach(function(letter, index) {
      expect(colCache._l2n[letter]).to.equal(index + 1);
      expect(colCache._n2l[index + 1]).to.equal(letter);
    });

    // next level
    expect(colCache.n2l(27)).to.equal('AA');
    expect(colCache._l2n.AB).to.equal(28);
    expect(colCache._n2l[28]).to.equal('AB');
  });

  it('converts numbers to letters', function() {
    expect(colCache.n2l(1)).to.equal('A');
    expect(colCache.n2l(26)).to.equal('Z');
    expect(colCache.n2l(27)).to.equal('AA');
    expect(colCache.n2l(702)).to.equal('ZZ');
    expect(colCache.n2l(703)).to.equal('AAA');
  });
  it('converts letters to numbers', function() {
    expect(colCache.l2n('A')).to.equal(1);
    expect(colCache.l2n('Z')).to.equal(26);
    expect(colCache.l2n('AA')).to.equal(27);
    expect(colCache.l2n('ZZ')).to.equal(702);
    expect(colCache.l2n('AAA')).to.equal(703);
  });

  it('throws when out of bounds', function() {
    expect(function() { colCache.n2l(0); }).to.throw(Error);
    expect(function() { colCache.n2l(-1); }).to.throw(Error);
    expect(function() { colCache.n2l(16385); }).to.throw(Error);

    expect(function() { colCache.l2n(''); }).to.throw(Error);
    expect(function() { colCache.l2n('AAAA'); }).to.throw(Error);
    expect(function() { colCache.l2n(16385); }).to.throw(Error);
  });

  it('validates addresses properly', function() {
    expect(colCache.validateAddress('A1')).to.be.ok();
    expect(colCache.validateAddress('AA10')).to.be.ok();
    expect(colCache.validateAddress('ABC100000')).to.be.ok();

    expect(function() { colCache.validateAddress('A'); }).to.throw(Error);
    expect(function() { colCache.validateAddress('1'); }).to.throw(Error);
    expect(function() { colCache.validateAddress('1A'); }).to.throw(Error);
    expect(function() { colCache.validateAddress('A 1'); }).to.throw(Error);
    expect(function() { colCache.validateAddress('A1A'); }).to.throw(Error);
    expect(function() { colCache.validateAddress('1A1'); }).to.throw(Error);
    expect(function() { colCache.validateAddress('a1'); }).to.throw(Error);
    expect(function() { colCache.validateAddress('a'); }).to.throw(Error);
  });

  it('decodes addresses', function() {
    expect(colCache.decodeAddress('A1')).to.deep.equal({address: 'A1', col: 1, row: 1, $col$row: '$A$1'});
    expect(colCache.decodeAddress('AA11')).to.deep.equal({address: 'AA11', col: 27, row: 11, $col$row: '$AA$11'});
  });

  it('convert [sheetName!][$]col[$]row[[$]col[$]row] into address or range structures', function() {
    expect(colCache.decodeEx('Sheet1!$H$1')).to.deep.equal({$col$row: '$H$1', address: 'H1', col: 8, row: 1, sheetName: 'Sheet1'});
    expect(colCache.decodeEx("'Sheet 1'!$H$1")).to.deep.equal({$col$row: '$H$1', address: 'H1', col: 8, row: 1, sheetName: 'Sheet 1'});
    expect(colCache.decodeEx("'Sheet !$:1'!$H$1")).to.deep.equal({$col$row: '$H$1', address: 'H1', col: 8, row: 1, sheetName: 'Sheet !$:1'});
    expect(colCache.decodeEx("'Sheet !$:1'!#REF!")).to.deep.equal({sheetName: 'Sheet !$:1', error: '#REF!'});
  });

  it('gets address structures (and caches them)', function() {
    var addr = colCache.getAddress('D5');
    expect(addr.address).to.equal('D5');
    expect(addr.row).to.equal(5);
    expect(addr.col).to.equal(4);
    expect(colCache.getAddress('D5')).to.equal(addr);
    expect(colCache.getAddress(5, 4)).to.equal(addr);

    addr = colCache.getAddress('E4');
    expect(addr.address).to.equal('E4');
    expect(addr.row).to.equal(4);
    expect(addr.col).to.equal(5);
    expect(colCache.getAddress('E4')).to.equal(addr);
    expect(colCache.getAddress(4, 5)).to.equal(addr);
  });

  it('decodes addresses and ranges', function() {
    // address
    expect(colCache.decode('A1')).to.deep.equal({address: 'A1', col: 1, row: 1, $col$row: '$A$1'});
    expect(colCache.decode('AA11')).to.deep.equal({address: 'AA11', col: 27, row: 11, $col$row: '$AA$11'});

    // range
    expect(colCache.decode('A1:B2')).to.deep.equal({
      dimensions: 'A1:B2',
      tl: 'A1',
      br: 'B2',
      top: 1,
      left: 1,
      bottom: 2,
      right: 2
    });

    // wonky ranges
    expect(colCache.decode('A2:B1')).to.deep.equal({
      dimensions: 'A1:B2',
      tl: 'A1',
      br: 'B2',
      top: 1,
      left: 1,
      bottom: 2,
      right: 2
    });
    expect(colCache.decode('B2:A1')).to.deep.equal({
      dimensions: 'A1:B2',
      tl: 'A1',
      br: 'B2',
      top: 1,
      left: 1,
      bottom: 2,
      right: 2
    });
  });
});
<|endoftext|>


<commit_before>define(["ist"], function(ist) {
	return function() {
		it("should enable updating by passing a new context object and previously rendered nodes to Template#update()", function() {
			var template = ist("div\n '{{ variable }}'"),
				nodes = template.render({ variable: "value" }),
				updated = template.update({ variable: "new value" }, nodes);

			expect( updated.firstChild ).toHaveTextContent( "new value" );
		});

		it("should update nodes and not create new ones when updating", function() {
			var template = ist("div\n '{{ variable }}'"),
				nodes = template.render({ variable: "value" }),
				node = nodes.firstChild,
				updated = template.update({ variable: "new value" }, nodes);

			expect( node ).toBeSameNodeAs( updated.firstChild );
		});

		it("should accept node arrays in Template#update()", function() {
			var template = ist("div\n '{{ variable }}'"),
				nodes = template.render({ variable: "value" }),
				upnodes = Array.prototype.slice.call(nodes.childNodes),
				updated = template.update({ variable: "new value" }, upnodes);

			expect( updated.firstChild ).toHaveTextContent( "new value" );
		});

		it("should accept NodeLists in Template#update()", function() {
			var template = ist("div\n '{{ variable }}'"),
				nodes = template.render({ variable: "value" }),
				upnodes = nodes.childNodes,
				updated = template.update({ variable: "new value" }, upnodes);

			expect( updated.firstChild ).toHaveTextContent( "new value" );
		});

		it("should accept DocumentFragments in Template#update()", function() {
			var template = ist("div\n '{{ variable }}'"),
				nodes = template.render({ variable: "value" }),
				upnodes = document.createDocumentFragment(),
				updated;

			upnodes.appendChild(nodes);
			updated = template.update({ variable: "new value" }, upnodes);

			expect( updated.firstChild ).toHaveTextContent( "new value" );
		});
	};
});
<commit_msg>Added tests for renderInto and RenderedTemplate<commit_after>define(["ist"], function(ist) {
	return function() {
		it("should enable updating by passing a new context object and " +
			"previously rendered nodes to Template#update()", function() {
			var template = ist("div '{{ variable }}'"),
				nodes = template.render({ variable: "value" }),
				updated = template.update({ variable: "new value" }, nodes);

			expect( updated.firstChild ).toHaveTextContent( "new value" );
		});

		it("should update nodes and not create new ones when updating",
			function() {
			var template = ist("div '{{ variable }}'"),
				nodes = template.render({ variable: "value" }),
				node = nodes.firstChild,
				updated = template.update({ variable: "new value" }, nodes);

			expect( node ).toBeSameNodeAs( updated.firstChild );
		});

		it("should accept node arrays in Template#update()", function() {
			var template = ist("div '{{ variable }}'"),
				nodes = template.render({ variable: "value" }),
				upnodes = Array.prototype.slice.call(nodes.childNodes),
				updated = template.update({ variable: "new value" }, upnodes);

			expect( updated.firstChild ).toHaveTextContent( "new value" );
		});

		it("should accept NodeLists in Template#update()", function() {
			var template = ist("div '{{ variable }}'"),
				nodes = template.render({ variable: "value" }),
				upnodes = nodes.childNodes,
				updated = template.update({ variable: "new value" }, upnodes);

			expect( updated.firstChild ).toHaveTextContent( "new value" );
		});

		it("should accept DocumentFragments in Template#update()", function() {
			var template = ist("div '{{ variable }}'"),
				nodes = template.render({ variable: "value" }),
				upnodes = document.createDocumentFragment(),
				updated;

			upnodes.appendChild(nodes);
			updated = template.update({ variable: "new value" }, upnodes);

			expect( updated.firstChild ).toHaveTextContent( "new value" );
		});

		it("should render into container when using Template#renderInto",
			function() {
			var template = ist("div '{{ variable }}'"),
				container = document.createElement("div");

			template.renderInto(container, { variable: "value" });

			expect( container.firstChild ).toBeElement( "div" );
			expect( container.firstChild ).toHaveTextContent( "value" );
		});

		it("should enable updating by using #update() on the return value of " +
			"Template#renderInto", function() {
			var template = ist("div '{{ variable }}'"),
				div = document.createElement("div"),
				rendered = template.renderInto(div, { variable: "value" });

			rendered.update({ variable: "new value" });
			expect( div.firstChild ).toHaveTextContent( "new value" );
		});

		it("should enable updating when using Template#renderInto even when " +
			"no nodes have been rendered in the first place", function() {
			var template = ist("@if cond\n div '{{ variable }}'"),
				container = document.createElement("div"),
				rendered = template.renderInto(container, {
					cond: false, variable: "value"
				});

			rendered.update({ cond: true, variable: "new value" });
			expect( container.firstChild ).toHaveTextContent( "new value" );
		});
	};
});
<|endoftext|>


<commit_before>var Cleverbot = require('cleverbot-node')
  // , Discordbot = require("discord.js")
  , Eris = require('eris')
  , fs = require("fs")
  , config = require("./config.json")
  , DBots = []
  , CBots = []
  , randombot = Math.floor(Math.random() * (config.bots.length - 1))
  , newtext = undefined
  , lastMessage = "Hello there!"
  , voters = []
  , votes = 0;

var botNum = 0
for (var ii = 0; ii < config.bots.length; ii++) {
  DBots.push(new Eris.Client(config.bots[ii]))
  DBots[ii].on("ready", function () {
    if (++botNum == DBots.length) {
      ready()
    }
  });
  DBots[ii].connect();
  CBots.push(new Cleverbot)
}

function ready() {
  for (var ii = 0; ii < DBots.length; ii++) {
    console.log("[info] Bot " + ii + " logged in as " + DBots[ii].user.username
      + "#" + DBots[ii].user.discriminator + " (" + DBots[ii].user.id + ")");
  }
  Cleverbot.prepare(function () {
    lastMessage = config.startMessage; callback({ message: config.startMessage })
  });
}

var i = 0, callback = function callback(resp) {
  setTimeout(function (str1, str2) {
    DBots[i].sendChannelTyping(config.botChannel);
    var toWrite = resp['message'];
    if (newtext) {
      toWrite = newtext;
      newtext = undefined;
    }
    CBots[i].write(toWrite, callback);
    // console.log(config.botChannel, toWrite);

    //   console.log(i)
    //  console.log(DBots[i].user.username)
    DBots[i = ((i + 1) % DBots.length)].createMessage(config.botChannel, toWrite).catch(err => console.log(err));
  }, config.bot_speed);
};

var commandsProcessed = 0, talkedToTimes = 0;

DBots[i].on("messageCreate", (msg) => {
  if (!msg.content.startsWith(config.command_prefix)) return;
  if (msg.content.indexOf(" ") === 1 && msg.content.length > 2) msg.content = msg.content.replace(" ", "");
  let cmd = msg.content.split(" ")[0].substring(1).toLowerCase();
  let suffix = msg.content.substring(cmd.length + 2).trim();
  if (msg.content.startsWith(config.command_prefix)) {
    if (commands.hasOwnProperty(cmd)) {
      if (!(msg.channel instanceof Eris.PrivateChannel))
        execCommand(msg, cmd, suffix);
    }
  }
});

/* COMMANDS | START */
var commands = {
  "help": {
    desc: "Sends a PM with all commands that can be used",
    usage: "[command]",
    deleteCommand: true, shouldDisplay: false, cooldown: 1,
    process: function (DBots, msg, suffix) {
      let toSend = [];
      if (!suffix) {
        toSend.push("Use `" + config.command_prefix + "help <command name>` to get more info on a command.\n");
        toSend.push("**Commands:**");
        toSend.push("```glsl\n");
        Object.keys(commands).forEach(cmd => {
          if (!commands[cmd].hasOwnProperty("shouldDisplay") || (commands[cmd].hasOwnProperty("shouldDisplay") && commands[cmd].shouldDisplay))
            toSend.push("\n" + config.command_prefix + cmd + " " + commands[cmd].usage + "\n\t#" + commands[cmd].desc);
        });
        toSend = toSend.join('');
        DBots[i].getDMChannel(msg.author.id).then(pc => {
          if (toSend.length >= 1990) {
            DBots[i].createMessage(pc.id, toSend.substr(0, 1990).substr(0, toSend.substr(0, 1990).lastIndexOf('\n\t')) + "```"); //part 1
            setTimeout(() => { DBots[i].createMessage(pc.id, "```glsl" + toSend.substr(toSend.substr(0, 1990).lastIndexOf('\n\t')) + "```"); }, 1000); //2
          } else DBots[i].createMessage(pc.id, toSend + "```"); DBots[i].createMessage(msg.channel.id, "**" + msg.author.username + "** I have sent you help in PM 📬");
        })
      } else {
        suffix = suffix.toLowerCase();
        if (commands.hasOwnProperty(suffix)) {
          toSend.push("`" + config.command_prefix + suffix + ' ' + commands[suffix].usage + "`");
          if (commands[suffix].hasOwnProperty("info")) toSend.push(commands[suffix].info); //if extra info
          else if (commands[suffix].hasOwnProperty("desc")) toSend.push(commands[suffix].desc); //else usse the desc
          DBots[i].createMessage(msg.channel.id, toSend);
        } else
          DBots[i].createMessage(msg.channel.id, "Command `" + suffix + "` not found.").then(wMessage => {
            setTimeout(() => {
              DBots[i].deleteMessage(wMessage.channel.id, wMessage.id);
            }, 10000)
          });
      }
    }
  },
  "restart": {
    desc: "Restart the bots to say something different", usage: "<sentence|word>",
    process: function (DBots, msg, suffix) {
      if (msg.channel.permissionsOf(msg.author.id).json["manageGuild"]) {
        var nexttext = msg.content.substring(8).trim();
        CBots.length = 0;
        for (var ii = 0; ii < DBots.length; ii++) {
          CBots.push(new Cleverbot);
        }
        if (nexttext.length == 0) {
          nexttext = lastMessage;
        } else {
          lastMessage = nexttext;
        }
        newtext = nexttext;
      } else DBots[i].createMessage(msg.channel.id, "⚠ Access Denied `Permission Required - manageServer`");
    }
  },
  "checkhost": {
    desc: "Checks who is hosting", usage: "",
    process: function (DBots, msg, suffix) {
      DBots[i].createMessage(msg.channel.id, config.host)
    }
  },
  "vote": {
    desc: "Vote to restart the bots", usage: "",
    process: function (DBots, msg, suffix) {
      if (votes == config.voteThreshold) {
        newtext = lastMessage;
        voters = [];
        votes = 0;
        CBots.length = 0;
        for (var ii = 0; ii < DBots.length; ii++) {
          CBots.push(new Cleverbot);
        }
        DBots[i].createMessage(msg.channel.id, "Cleverbutts *should* be restarted.")
      }
      if (voters.includes(msg.author.id)) {
        DBots[i].createMessage(msg.channel.id, "You have already voted!")
      } else {
        var remainingvotes = config.voteThreshold - votes;
        voters.push(msg.author.id);
        //console.log(i)
        DBots[i].createMessage(msg.channel.id, "**" + remainingvotes + "** more votes are required to restart.");
        ++votes
      }
    }
  },
  "shutdown": {
    desc: "Turns off the bots (and reboots if using script)", usage: "<sentence|word>",
    process: function (DBots, msg, suffix) {
      var startMSG = msg.content.substring(15, 2000).trim();
      if (startMSG.length == 0) {
        startMSG = lastMessage;
      } else {
        lastMessage = startMSG;
      }
      if (msg.channel.permissionsOf(msg.author.id).json["manageGuild"]) {
        if (startMSG != "") {
          fs.readFile("./config.json", "utf8", function (err, ctx) {
            var parts = ctx.split(config.startMessage)
            fs.writeFile("./config.json", parts[0] + startMSG + parts[1], function () {
              process.exit()
            });
          });
        }
        else {
          process.exit()
        }
      } else DBots[i].createMessage(msg.channel.id, "⚠ Access Denied `Permission Required - manageServer`");
    }
  }
}

/* COMMANDS | END */

function execCommand(msg, cmd, suffix, type = "normal") {
  try {
    commandsProcessed += 1;
    if (type == "normal") {
      commands[cmd].process(DBots, msg, suffix);
    }
  } catch (err) { console.log(err.stack); }
}

DBots[i].on("guildBanAdd", function (guild, user) {
  if (config.hasOwnProperty('logChannel')) {
    if (guild.id === DBots[i].guilds.get(DBots[i].channelGuildMap[config.logChannel]).id) {
      DBots[i].createMessage(config.logChannel, "🔨 " + user.username
        + "#" + user.discriminator + " (" + user.id + ") was banned.")
    }
  }
})

DBots[i].on("guildBanRemove", function (guild, user) {
  if (config.hasOwnProperty('logChannel')) {
    if (guild.id === DBots[i].guilds.get(DBots[i].channelGuildMap[config.logChannel]).id) {
      DBots[i].createMessage(config.logChannel, "🍪 " + user.username
        + "#" + user.discriminator + " (" + user.id + ") was unbanned.")
    }
  }
})

exports.commands = commands;<commit_msg>bot header<commit_after>var Cleverbot = require('cleverbot-node')
  // , Discordbot = require("discord.js")
  , Eris = require('eris')
  , fs = require("fs")
  , config = require("./config.json")
  , DBots = []
  , CBots = []
  , randombot = Math.floor(Math.random() * (config.bots.length - 1))
  , newtext = undefined
  , lastMessage = "Hello there!"
  , voters = []
  , votes = 0;

var botNum = 0
for (var ii = 0; ii < config.bots.length; ii++) {
  DBots.push(new Eris.Client("Bot " + config.bots[ii]))
  DBots[ii].on("ready", function () {
    if (++botNum == DBots.length) {
      ready()
    }
  });
  DBots[ii].connect();
  CBots.push(new Cleverbot)
}

function ready() {
  for (var ii = 0; ii < DBots.length; ii++) {
    console.log("[info] Bot " + ii + " logged in as " + DBots[ii].user.username
      + "#" + DBots[ii].user.discriminator + " (" + DBots[ii].user.id + ")");
  }
  Cleverbot.prepare(function () {
    lastMessage = config.startMessage; callback({ message: config.startMessage })
  });
}

var i = 0, callback = function callback(resp) {
  setTimeout(function (str1, str2) {
    DBots[i].sendChannelTyping(config.botChannel);
    var toWrite = resp['message'];
    if (newtext) {
      toWrite = newtext;
      newtext = undefined;
    }
    CBots[i].write(toWrite, callback);
    // console.log(config.botChannel, toWrite);

    //   console.log(i)
    //  console.log(DBots[i].user.username)
    DBots[i = ((i + 1) % DBots.length)].createMessage(config.botChannel, toWrite).catch(err => console.log(err));
  }, config.bot_speed);
};

var commandsProcessed = 0, talkedToTimes = 0;

DBots[i].on("messageCreate", (msg) => {
  if (!msg.content.startsWith(config.command_prefix)) return;
  if (msg.content.indexOf(" ") === 1 && msg.content.length > 2) msg.content = msg.content.replace(" ", "");
  let cmd = msg.content.split(" ")[0].substring(1).toLowerCase();
  let suffix = msg.content.substring(cmd.length + 2).trim();
  if (msg.content.startsWith(config.command_prefix)) {
    if (commands.hasOwnProperty(cmd)) {
      if (!(msg.channel instanceof Eris.PrivateChannel))
        execCommand(msg, cmd, suffix);
    }
  }
});

/* COMMANDS | START */
var commands = {
  "help": {
    desc: "Sends a PM with all commands that can be used",
    usage: "[command]",
    deleteCommand: true, shouldDisplay: false, cooldown: 1,
    process: function (DBots, msg, suffix) {
      let toSend = [];
      if (!suffix) {
        toSend.push("Use `" + config.command_prefix + "help <command name>` to get more info on a command.\n");
        toSend.push("**Commands:**");
        toSend.push("```glsl\n");
        Object.keys(commands).forEach(cmd => {
          if (!commands[cmd].hasOwnProperty("shouldDisplay") || (commands[cmd].hasOwnProperty("shouldDisplay") && commands[cmd].shouldDisplay))
            toSend.push("\n" + config.command_prefix + cmd + " " + commands[cmd].usage + "\n\t#" + commands[cmd].desc);
        });
        toSend = toSend.join('');
        DBots[i].getDMChannel(msg.author.id).then(pc => {
          if (toSend.length >= 1990) {
            DBots[i].createMessage(pc.id, toSend.substr(0, 1990).substr(0, toSend.substr(0, 1990).lastIndexOf('\n\t')) + "```"); //part 1
            setTimeout(() => { DBots[i].createMessage(pc.id, "```glsl" + toSend.substr(toSend.substr(0, 1990).lastIndexOf('\n\t')) + "```"); }, 1000); //2
          } else DBots[i].createMessage(pc.id, toSend + "```"); DBots[i].createMessage(msg.channel.id, "**" + msg.author.username + "** I have sent you help in PM 📬");
        })
      } else {
        suffix = suffix.toLowerCase();
        if (commands.hasOwnProperty(suffix)) {
          toSend.push("`" + config.command_prefix + suffix + ' ' + commands[suffix].usage + "`");
          if (commands[suffix].hasOwnProperty("info")) toSend.push(commands[suffix].info); //if extra info
          else if (commands[suffix].hasOwnProperty("desc")) toSend.push(commands[suffix].desc); //else usse the desc
          DBots[i].createMessage(msg.channel.id, toSend);
        } else
          DBots[i].createMessage(msg.channel.id, "Command `" + suffix + "` not found.").then(wMessage => {
            setTimeout(() => {
              DBots[i].deleteMessage(wMessage.channel.id, wMessage.id);
            }, 10000)
          });
      }
    }
  },
  "restart": {
    desc: "Restart the bots to say something different", usage: "<sentence|word>",
    process: function (DBots, msg, suffix) {
      if (msg.channel.permissionsOf(msg.author.id).json["manageGuild"]) {
        var nexttext = msg.content.substring(8).trim();
        CBots.length = 0;
        for (var ii = 0; ii < DBots.length; ii++) {
          CBots.push(new Cleverbot);
        }
        if (nexttext.length == 0) {
          nexttext = lastMessage;
        } else {
          lastMessage = nexttext;
        }
        newtext = nexttext;
      } else DBots[i].createMessage(msg.channel.id, "⚠ Access Denied `Permission Required - manageServer`");
    }
  },
  "checkhost": {
    desc: "Checks who is hosting", usage: "",
    process: function (DBots, msg, suffix) {
      DBots[i].createMessage(msg.channel.id, config.host)
    }
  },
  "vote": {
    desc: "Vote to restart the bots", usage: "",
    process: function (DBots, msg, suffix) {
      if (votes == config.voteThreshold) {
        newtext = lastMessage;
        voters = [];
        votes = 0;
        CBots.length = 0;
        for (var ii = 0; ii < DBots.length; ii++) {
          CBots.push(new Cleverbot);
        }
        DBots[i].createMessage(msg.channel.id, "Cleverbutts *should* be restarted.")
      }
      if (voters.includes(msg.author.id)) {
        DBots[i].createMessage(msg.channel.id, "You have already voted!")
      } else {
        var remainingvotes = config.voteThreshold - votes;
        voters.push(msg.author.id);
        //console.log(i)
        DBots[i].createMessage(msg.channel.id, "**" + remainingvotes + "** more votes are required to restart.");
        ++votes
      }
    }
  },
  "shutdown": {
    desc: "Turns off the bots (and reboots if using script)", usage: "<sentence|word>",
    process: function (DBots, msg, suffix) {
      var startMSG = msg.content.substring(15, 2000).trim();
      if (startMSG.length == 0) {
        startMSG = lastMessage;
      } else {
        lastMessage = startMSG;
      }
      if (msg.channel.permissionsOf(msg.author.id).json["manageGuild"]) {
        if (startMSG != "") {
          fs.readFile("./config.json", "utf8", function (err, ctx) {
            var parts = ctx.split(config.startMessage)
            fs.writeFile("./config.json", parts[0] + startMSG + parts[1], function () {
              process.exit()
            });
          });
        }
        else {
          process.exit()
        }
      } else DBots[i].createMessage(msg.channel.id, "⚠ Access Denied `Permission Required - manageServer`");
    }
  }
}

/* COMMANDS | END */

function execCommand(msg, cmd, suffix, type = "normal") {
  try {
    commandsProcessed += 1;
    if (type == "normal") {
      commands[cmd].process(DBots, msg, suffix);
    }
  } catch (err) { console.log(err.stack); }
}

DBots[i].on("guildBanAdd", function (guild, user) {
  if (config.hasOwnProperty('logChannel')) {
    if (guild.id === DBots[i].guilds.get(DBots[i].channelGuildMap[config.logChannel]).id) {
      DBots[i].createMessage(config.logChannel, "🔨 " + user.username
        + "#" + user.discriminator + " (" + user.id + ") was banned.")
    }
  }
})

DBots[i].on("guildBanRemove", function (guild, user) {
  if (config.hasOwnProperty('logChannel')) {
    if (guild.id === DBots[i].guilds.get(DBots[i].channelGuildMap[config.logChannel]).id) {
      DBots[i].createMessage(config.logChannel, "🍪 " + user.username
        + "#" + user.discriminator + " (" + user.id + ") was unbanned.")
    }
  }
})

exports.commands = commands;
<|endoftext|>


<commit_before>require('../src/function-create');

var Promise = require('bluebird'),

	arrProto = Array.prototype,

	protoFn = function() {};

//
// [NOTE] function.length and array.length don't play nice together,
//        so we can't just use Function.create(Array.prototype, function(){ ... })

Object.getOwnPropertyNames(arrProto).forEach(function(fname){
	// assign array methods to proto function
	// skip length, toString, etc.
	if (typeof protoFn[fname] !== 'undefined') return;
	var fn = arrProto[fname];
	protoFn[fname] = function(){
		return fn.apply(this.__fnlist__, arguments);
	};
});

protoFn.invoke = function(scope, args, opts){
	scope = scope || null;
	opts = opts || {};
	var res, spread = opts.spread, i, l = this.__fnlist__.length;
	switch (opts.mode) {
		case 'pipe':
			// execute as a synchronous series
			res = this.__fnlist__[0].apply(scope, args);
			for (i = 1; i < l; i++) {
				res = this.__fnlist__[i].apply(scope, Array.isArray(res) && spread ? res : [res]);
			}
		break;
		case 'async':
			// execute it as an asynchronous series;
			res = Promise.all(args).bind(scope);
			this.__fnlist__.forEach(function(fn) { res = res.spread(fn); });
		break;
		case 'linear':
			/* falls through */
		default:
			// execute as a list of functions, all with the same original arguments
			for (i = 0; i < l; i++) res = this.__fnlist__[i].apply(scope, args);
		break;
	}
	return res;
};

// a factory function to create executable arrays.

function ExecutableArray(opts, fns) {
	var hooked = Function.create(protoFn, function() {
		var args = arrProto.slice.call(arguments);
		return hooked.invoke(this, args, opts);
	}, {
		__fnlist__: {
			value: fns || []
		}
	});
	return hooked;
}

module.exports = ExecutableArray;

///////////////////////////////////////////////////////////
////////////////////////  EXAMPLE  ////////////////////////
///////////////////////////////////////////////////////////

var fibbonaciStart		= function() { return [1, 1]; },
	fibbonaciStep		= function(l, r) { return [r, l+r]; },
	fibbonaciFinish		= function(l, r) { return l+r; },

	_log = function(msg){
		return function(l, r){ console.log(l + '\t' +  msg); return [l, r]; };
	};

var fibbonaci = ExecutableArray({mode: 'pipe', spread: true}, [
	fibbonaciStep,
	fibbonaciStep,
	_log('I\'m in the original fn list' ),
	fibbonaciStep,
	fibbonaciStep,
	fibbonaciStep,
	fibbonaciStep,
	fibbonaciStep,
]);

fibbonaci.unshift(fibbonaciStart);
fibbonaci.splice(4, 0, _log('I was spliced into position 4'));
fibbonaci.splice(8, 0, _log('I was spliced into position 8'));
fibbonaci.push(_log('I\'m the final _log() before the finishing function'));
fibbonaci.push(fibbonaciFinish);

fibbonaci();
	// logs: 3  (spliced-in _log function #1)
	// logs: 13 (spliced-in _log function #2)
	// logs: 55 (spliced-in _log function)
	// -> output: 55
<commit_msg>fixed execarr demo<commit_after>require('../src/function-create');

var Promise = require('bluebird'),

	arrProto = Array.prototype,

	protoFn = function() {};

//
// [NOTE] function.length and array.length don't play nice together,
//        so we can't just use Function.create(Array.prototype, function(){ ... })

Object.getOwnPropertyNames(arrProto).forEach(function(fname){
	// assign array methods to proto function
	// skip length, toString, etc.
	if (typeof protoFn[fname] !== 'undefined') return;
	var fn = arrProto[fname];
	protoFn[fname] = function(){
		return fn.apply(this.__fnlist__, arguments);
	};
});

protoFn.invoke = function(scope, args, opts){
	scope = scope || null;
	opts = opts || {};
	var res, spread = opts.spread, i, l = this.__fnlist__.length;
	switch (opts.mode) {
		case 'pipe':
			// execute as a synchronous series
			res = this.__fnlist__[0].apply(scope, args);
			for (i = 1; i < l; i++) {
				res = this.__fnlist__[i].apply(scope, Array.isArray(res) && spread ? res : [res]);
			}
		break;
		case 'async':
			// execute it as an asynchronous series;
			res = Promise.all(args).bind(scope);
			this.__fnlist__.forEach(function(fn) { res = res.spread(fn); });
		break;
		case 'linear':
			/* falls through */
		default:
			// execute as a list of functions, all with the same original arguments
			for (i = 0; i < l; i++) res = this.__fnlist__[i].apply(scope, args);
		break;
	}
	return res;
};

// a factory function to create executable arrays.

function ExecutableArray(opts, fns) {
	var hooked = Function.create(protoFn, function() {
		var args = arrProto.slice.call(arguments);
		return hooked.invoke(this, args, opts);
	}, {
		__fnlist__: {
			value: fns || []
		}
	});
	return hooked;
}

module.exports = ExecutableArray;

///////////////////////////////////////////////////////////
////////////////////////  EXAMPLE  ////////////////////////
///////////////////////////////////////////////////////////

var fibbonaciStart		= function() { return [1, 1]; },
	fibbonaciStep		= function(l, r) { return [r, l+r]; },
	fibbonaciFinish		= function(l, r) { return l+r; },

	_log = function(msg){
		return function(l, r){ console.log(l + '\t' +  msg); return [l, r]; };
	};

var fibbonaci = ExecutableArray({mode: 'pipe', spread: true}, [
	fibbonaciStep,
	fibbonaciStep,
	_log('I\'m in the original fn list' ),
	fibbonaciStep,
	fibbonaciStep,
	fibbonaciStep,
	fibbonaciStep,
	fibbonaciStep,
]);

fibbonaci.unshift(fibbonaciStart);
fibbonaci.splice(5, 0, _log('I was spliced into position 4'));
fibbonaci.splice(8, 0, _log('I was spliced into position 8'));
fibbonaci.push(_log('I\'m the final _log() before the finishing function'));
fibbonaci.push(fibbonaciFinish);

fibbonaci();
	// logs: 2	I'm in the original fn list
	// logs: 3	I was spliced into position 4
	// logs: 8	I was spliced into position 8
	// logs: 21	I'm the final _log() before the finishing function
	// -> output: 55
<|endoftext|>


<commit_before>'use strict';

var React = require('react-native');
var {
  Dimensions,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
  Animated,
} = React;

var deviceWidth = Dimensions.get('window').width;

var styles = StyleSheet.create({
  tab: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    paddingBottom: 10,
  },

  tabs: {
    height: 50,
    flexDirection: 'row',
    justifyContent: 'space-around',
    marginTop: 20,
    borderWidth: 1,
    borderTopWidth: 0,
    borderLeftWidth: 0,
    borderRightWidth: 0,
    borderBottomColor: '#ccc',
  },
});

var DefaultTabBar = React.createClass({
  propTypes: {
    goToPage: React.PropTypes.func,
    activeTab: React.PropTypes.number,
    tabs: React.PropTypes.array
  },

  renderTabOption(name, page) {
    var isTabActive = this.props.activeTab === page;

    return (
      <TouchableOpacity key={name} onPress={() => this.props.goToPage(page)}>
        <View style={[styles.tab]}>
          <Text style={{color: isTabActive ? 'navy' : 'black', fontWeight: isTabActive ? 'bold' : 'normal'}}>{name}</Text>
        </View>
      </TouchableOpacity>
    );
  },

  render() {
    var numberOfTabs = this.props.tabs.length;
    var tabUnderlineStyle = {
      position: 'absolute',
      width: deviceWidth / numberOfTabs,
      height: 4,
      backgroundColor: 'navy',
      bottom: 0,
    };

    var left = this.props.scrollValue.interpolate({
      inputRange: [0, 1], outputRange: [0, deviceWidth / numberOfTabs]
    });

    return (
      <View style={styles.tabs}>
        {this.props.tabs.map((tab, i) => this.renderTabOption(tab, i))}
        <Animated.View style={[tabUnderlineStyle, {left}]} />
      </View>
    );
  },
});

module.exports = DefaultTabBar;
<commit_msg>Fixes layout problem with more recent versions of React Native.<commit_after>'use strict';

var React = require('react-native');
var {
  Dimensions,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
  Animated,
} = React;

var deviceWidth = Dimensions.get('window').width;

var styles = StyleSheet.create({
  tab: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    paddingBottom: 10,
  },

  tabs: {
    height: 50,
    flexDirection: 'row',
    justifyContent: 'space-around',
    marginTop: 20,
    borderWidth: 1,
    borderTopWidth: 0,
    borderLeftWidth: 0,
    borderRightWidth: 0,
    borderBottomColor: '#ccc',
  },
});

var DefaultTabBar = React.createClass({
  propTypes: {
    goToPage: React.PropTypes.func,
    activeTab: React.PropTypes.number,
    tabs: React.PropTypes.array
  },

  renderTabOption(name, page) {
    var isTabActive = this.props.activeTab === page;

    return (
      <TouchableOpacity style={[styles.tab]} key={name} onPress={() => this.props.goToPage(page)}>
        <View>
          <Text style={{color: isTabActive ? 'navy' : 'black', fontWeight: isTabActive ? 'bold' : 'normal'}}>{name}</Text>
        </View>
      </TouchableOpacity>
    );
  },

  render() {
    var numberOfTabs = this.props.tabs.length;
    var tabUnderlineStyle = {
      position: 'absolute',
      width: deviceWidth / numberOfTabs,
      height: 4,
      backgroundColor: 'navy',
      bottom: 0,
    };

    var left = this.props.scrollValue.interpolate({
      inputRange: [0, 1], outputRange: [0, deviceWidth / numberOfTabs]
    });

    return (
      <View style={styles.tabs}>
        {this.props.tabs.map((tab, i) => this.renderTabOption(tab, i))}
        <Animated.View style={[tabUnderlineStyle, {left}]} />
      </View>
    );
  },
});

module.exports = DefaultTabBar;
<|endoftext|>


<commit_before>/* globals module */
import {applyMiddleware, createStore, compose} from 'redux'
import promiseMiddleware from 'redux-promise'
import thunkMiddleware from 'redux-thunk'
import {createLogger as loggingMiddleware} from 'redux-logger'
import checkStudentsMiddleware from './middleware/check-students'
import saveStudentsMiddleware from './middleware/save-students'
import rootReducer from './reducer'
import freezingMiddleware from 'redux-freeze'

const finalCreateStore = compose(
	applyMiddleware(
		promiseMiddleware,
		thunkMiddleware,
		freezingMiddleware,
		checkStudentsMiddleware,
		saveStudentsMiddleware,
		loggingMiddleware({duration: true, collapsed: true}),
	),
	window && window.devToolsExtension ? window.devToolsExtension() : f => f,
)(createStore)

export default function configureStore(initialState) {
	const store = finalCreateStore(rootReducer, initialState)

	return store
}
<commit_msg>fix verbose redux logging during tests<commit_after>/* globals module */
import {applyMiddleware, createStore, compose} from 'redux'
import promiseMiddleware from 'redux-promise'
import thunkMiddleware from 'redux-thunk'
import {createLogger as loggingMiddleware} from 'redux-logger'
import checkStudentsMiddleware from './middleware/check-students'
import saveStudentsMiddleware from './middleware/save-students'
import rootReducer from './reducer'
import freezingMiddleware from 'redux-freeze'

let middleware = [
	promiseMiddleware,
	thunkMiddleware,
	freezingMiddleware,
	checkStudentsMiddleware,
	saveStudentsMiddleware,
]

if (!global.TESTING) {
	middleware.push(loggingMiddleware({duration: true, collapsed: true}))
}

const finalCreateStore = compose(
	applyMiddleware(...middleware),
	window && window.devToolsExtension ? window.devToolsExtension() : f => f,
)(createStore)

export default function configureStore(initialState) {
	const store = finalCreateStore(rootReducer, initialState)

	return store
}
<|endoftext|>


<commit_before>/**
 * DropdownInputWidget is a {@link OO.ui.DropdownWidget DropdownWidget} intended to be used
 * within an HTML form, such as a OO.ui.FormLayout. The selected value is synchronized with the value
 * of a hidden HTML `input` tag. Please see the [OOjs UI documentation on MediaWiki][1] for
 * more information about input widgets.
 *
 * A DropdownInputWidget always has a value (one of the options is always selected), unless there
 * are no options. If no `value` configuration option is provided, the first option is selected.
 * If you need a state representing no value (no option being selected), use a DropdownWidget.
 *
 * This and OO.ui.RadioSelectInputWidget support the same configuration options.
 *
 *     @example
 *     // Example: A DropdownInputWidget with three options
 *     var dropdownInput = new OO.ui.DropdownInputWidget( {
 *         options: [
 *             { data: 'a', label: 'First' },
 *             { data: 'b', label: 'Second'},
 *             { data: 'c', label: 'Third' }
 *         ]
 *     } );
 *     $( 'body' ).append( dropdownInput.$element );
 *
 * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs
 *
 * @class
 * @extends OO.ui.InputWidget
 * @mixins OO.ui.mixin.TitledElement
 *
 * @constructor
 * @param {Object} [config] Configuration options
 * @cfg {Object[]} [options=[]] Array of menu options in the format `{ data: …, label: … }`
 * @cfg {Object} [dropdown] Configuration options for {@link OO.ui.DropdownWidget DropdownWidget}
 */
OO.ui.DropdownInputWidget = function OoUiDropdownInputWidget( config ) {
	// Configuration initialization
	config = config || {};

	// See InputWidget#reusePreInfuseDOM about config.$input
	if ( config.$input ) {
		config.$input.addClass( 'oo-ui-element-hidden' );
	}

	// Properties (must be done before parent constructor which calls #setDisabled)
	this.dropdownWidget = new OO.ui.DropdownWidget( config.dropdown );

	// Parent constructor
	OO.ui.DropdownInputWidget.parent.call( this, config );

	// Mixin constructors
	OO.ui.mixin.TitledElement.call( this, config );

	// Events
	this.dropdownWidget.getMenu().connect( this, { select: 'onMenuSelect' } );

	// Initialization
	this.setOptions( config.options || [] );
	this.$element
		.addClass( 'oo-ui-dropdownInputWidget' )
		.append( this.dropdownWidget.$element );
	this.setTabIndexedElement( null );
};

/* Setup */

OO.inheritClass( OO.ui.DropdownInputWidget, OO.ui.InputWidget );
OO.mixinClass( OO.ui.DropdownInputWidget, OO.ui.mixin.TitledElement );

/* Methods */

/**
 * @inheritdoc
 * @protected
 */
OO.ui.DropdownInputWidget.prototype.getInputElement = function () {
	return $( '<input>' ).attr( 'type', 'hidden' );
};

/**
 * Handles menu select events.
 *
 * @private
 * @param {OO.ui.MenuOptionWidget} item Selected menu item
 */
OO.ui.DropdownInputWidget.prototype.onMenuSelect = function ( item ) {
	this.setValue( item.getData() );
};

/**
 * @inheritdoc
 */
OO.ui.DropdownInputWidget.prototype.setValue = function ( value ) {
	var selected;
	value = this.cleanUpValue( value );
	this.dropdownWidget.getMenu().selectItemByData( value );
	// Only allow setting values that are actually present in the dropdown
	selected = this.dropdownWidget.getMenu().getSelectedItem();
	value = selected ? selected.getData() : '';
	OO.ui.DropdownInputWidget.parent.prototype.setValue.call( this, value );
	return this;
};

/**
 * @inheritdoc
 */
OO.ui.DropdownInputWidget.prototype.setDisabled = function ( state ) {
	this.dropdownWidget.setDisabled( state );
	OO.ui.DropdownInputWidget.parent.prototype.setDisabled.call( this, state );
	return this;
};

/**
 * Set the options available for this input.
 *
 * @param {Object[]} options Array of menu options in the format `{ data: …, label: … }`
 * @chainable
 */
OO.ui.DropdownInputWidget.prototype.setOptions = function ( options ) {
	var
		value = this.getValue(),
		widget = this;

	// Rebuild the dropdown menu
	this.dropdownWidget.getMenu()
		.clearItems()
		.addItems( options.map( function ( opt ) {
			var optValue = widget.cleanUpValue( opt.data );

			if ( opt.optgroup === undefined ) {
				return new OO.ui.MenuOptionWidget( {
					data: optValue,
					label: opt.label !== undefined ? opt.label : optValue
				} );
			} else {
				return new OO.ui.MenuSectionOptionWidget( {
					label: opt.optgroup
				} );
			}
		} ) );

	// Restore the previous value, or reset to something sensible
	if ( this.dropdownWidget.getMenu().getItemFromData( value ) ) {
		// Previous value is still available, ensure consistency with the dropdown
		this.setValue( value );
	} else {
		// No longer valid, reset
		if ( options.length ) {
			this.setValue( options[ 0 ].data );
		}
	}

	return this;
};

/**
 * @inheritdoc
 */
OO.ui.DropdownInputWidget.prototype.focus = function () {
	this.dropdownWidget.focus();
	return this;
};

/**
 * @inheritdoc
 */
OO.ui.DropdownInputWidget.prototype.blur = function () {
	this.dropdownWidget.blur();
	return this;
};
<commit_msg>DropdownInputWidget: Unbreak setting 'value' via config options<commit_after>/**
 * DropdownInputWidget is a {@link OO.ui.DropdownWidget DropdownWidget} intended to be used
 * within an HTML form, such as a OO.ui.FormLayout. The selected value is synchronized with the value
 * of a hidden HTML `input` tag. Please see the [OOjs UI documentation on MediaWiki][1] for
 * more information about input widgets.
 *
 * A DropdownInputWidget always has a value (one of the options is always selected), unless there
 * are no options. If no `value` configuration option is provided, the first option is selected.
 * If you need a state representing no value (no option being selected), use a DropdownWidget.
 *
 * This and OO.ui.RadioSelectInputWidget support the same configuration options.
 *
 *     @example
 *     // Example: A DropdownInputWidget with three options
 *     var dropdownInput = new OO.ui.DropdownInputWidget( {
 *         options: [
 *             { data: 'a', label: 'First' },
 *             { data: 'b', label: 'Second'},
 *             { data: 'c', label: 'Third' }
 *         ]
 *     } );
 *     $( 'body' ).append( dropdownInput.$element );
 *
 * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs
 *
 * @class
 * @extends OO.ui.InputWidget
 * @mixins OO.ui.mixin.TitledElement
 *
 * @constructor
 * @param {Object} [config] Configuration options
 * @cfg {Object[]} [options=[]] Array of menu options in the format `{ data: …, label: … }`
 * @cfg {Object} [dropdown] Configuration options for {@link OO.ui.DropdownWidget DropdownWidget}
 */
OO.ui.DropdownInputWidget = function OoUiDropdownInputWidget( config ) {
	// Configuration initialization
	config = config || {};

	// See InputWidget#reusePreInfuseDOM about config.$input
	if ( config.$input ) {
		config.$input.addClass( 'oo-ui-element-hidden' );
	}

	// Properties (must be done before parent constructor which calls #setDisabled)
	this.dropdownWidget = new OO.ui.DropdownWidget( config.dropdown );

	// Parent constructor
	OO.ui.DropdownInputWidget.parent.call( this, config );

	// Mixin constructors
	OO.ui.mixin.TitledElement.call( this, config );

	// Events
	this.dropdownWidget.getMenu().connect( this, { select: 'onMenuSelect' } );

	// Initialization
	this.setOptions( config.options || [] );
	// Set the value again, after we did setOptions(). The call from parent doesn't work because the
	// widget has no valid options when it happens.
	this.setValue( config.value );
	this.$element
		.addClass( 'oo-ui-dropdownInputWidget' )
		.append( this.dropdownWidget.$element );
	this.setTabIndexedElement( null );
};

/* Setup */

OO.inheritClass( OO.ui.DropdownInputWidget, OO.ui.InputWidget );
OO.mixinClass( OO.ui.DropdownInputWidget, OO.ui.mixin.TitledElement );

/* Methods */

/**
 * @inheritdoc
 * @protected
 */
OO.ui.DropdownInputWidget.prototype.getInputElement = function () {
	return $( '<input>' ).attr( 'type', 'hidden' );
};

/**
 * Handles menu select events.
 *
 * @private
 * @param {OO.ui.MenuOptionWidget|null} item Selected menu item
 */
OO.ui.DropdownInputWidget.prototype.onMenuSelect = function ( item ) {
	this.setValue( item ? item.getData() : '' );
};

/**
 * @inheritdoc
 */
OO.ui.DropdownInputWidget.prototype.setValue = function ( value ) {
	var selected;
	value = this.cleanUpValue( value );
	// Only allow setting values that are actually present in the dropdown
	selected = this.dropdownWidget.getMenu().getItemFromData( value ) ||
		this.dropdownWidget.getMenu().getFirstSelectableItem();
	this.dropdownWidget.getMenu().selectItem( selected );
	value = selected ? selected.getData() : '';
	OO.ui.DropdownInputWidget.parent.prototype.setValue.call( this, value );
	return this;
};

/**
 * @inheritdoc
 */
OO.ui.DropdownInputWidget.prototype.setDisabled = function ( state ) {
	this.dropdownWidget.setDisabled( state );
	OO.ui.DropdownInputWidget.parent.prototype.setDisabled.call( this, state );
	return this;
};

/**
 * Set the options available for this input.
 *
 * @param {Object[]} options Array of menu options in the format `{ data: …, label: … }`
 * @chainable
 */
OO.ui.DropdownInputWidget.prototype.setOptions = function ( options ) {
	var
		value = this.getValue(),
		widget = this;

	// Rebuild the dropdown menu
	this.dropdownWidget.getMenu()
		.clearItems()
		.addItems( options.map( function ( opt ) {
			var optValue = widget.cleanUpValue( opt.data );

			if ( opt.optgroup === undefined ) {
				return new OO.ui.MenuOptionWidget( {
					data: optValue,
					label: opt.label !== undefined ? opt.label : optValue
				} );
			} else {
				return new OO.ui.MenuSectionOptionWidget( {
					label: opt.optgroup
				} );
			}
		} ) );

	// Restore the previous value, or reset to something sensible
	if ( this.dropdownWidget.getMenu().getItemFromData( value ) ) {
		// Previous value is still available, ensure consistency with the dropdown
		this.setValue( value );
	} else {
		// No longer valid, reset
		if ( options.length ) {
			this.setValue( options[ 0 ].data );
		}
	}

	return this;
};

/**
 * @inheritdoc
 */
OO.ui.DropdownInputWidget.prototype.focus = function () {
	this.dropdownWidget.focus();
	return this;
};

/**
 * @inheritdoc
 */
OO.ui.DropdownInputWidget.prototype.blur = function () {
	this.dropdownWidget.blur();
	return this;
};
<|endoftext|>