<commit_before>const config = require('../config/config.json').PREFIX
let channelsArr = [];
exports.run = async (client, guild) => {

  let Id = guild.channels.get(guild.channels.filter(i=> i.type === "text").map(i => i)[0].id);
  let p = guild.channels.filter(o => o.type === 'text').map(o => o)
  Id.send(`Hey :wave:, Thank you very much for adding me to \`${guild.name}\` to get access to the command list do \`${config}help\``);

  for (var i = 0; i < p.length; i++) {
    channelsArr.push(p[i].name)
  }

  if(!channelsArr.includes('may-log')) {
    guild.createChannel("may-log", "text").then(channel => channel.overwritePermissions(guild.id, {
      SEND_MESSAGES: false
    }))
    .catch(e => {
      logger.error(e)
    })
  }

  guild.createRole({
    data: {
      name: 'may-muted',
      color: 'BLUE',
      permissions: ["USE_VAD", "ADD_REACTIONS", "READ_MESSAGE_HISTORY", "CREATE_INSTANT_INVITE", "READ_MESSAGES"]
    },
    reason: 'we needed a role for muted',
  })
  .then(role => logger.info(`Created role ${role}`))
  .catch(e => {
    logger.error(e)
  })
}
<commit_msg>added comments<commit_after>const config = require('../config/config.json').PREFIX
let channelsArr = [];
exports.run = async (client, guild) => {

  let Id = guild.channels.get(guild.channels.filter(i=> i.type === "text").map(i => i)[0].id);
  let p = guild.channels.filter(o => o.type === 'text').map(o => o)
  Id.send(`Hey :wave:, Thank you very much for adding me to \`${guild.name}\` to get access to the command list do \`${config}help\``);

  /**
  * Check if there's a channel with the name of may-log
  * @type {Array}
  */
  for (var i = 0; i < p.length; i++) {
    channelsArr.push(p[i].name)
  }

  /**
  * Create a channel for may to print out punishments
  * @returns {Error}
  * @returns {Promise}
  */
  if(!channelsArr.includes('may-log')) {
    guild.createChannel("may-log", "text").then(channel => channel.overwritePermissions(guild.id, {
      SEND_MESSAGES: false
    }))
    .catch(e => {
      logger.error(e)
    })
  }

  /**
  * Create muted role
  * @param {Object} data
  * @param {String} name
  * @param {String} color
  * @param {Array} permissions
  * @param {String} reason
  * @returns {Error}
  * @returns {Promise}
  */
  guild.createRole({
    data: {
      name: 'may-muted',
      color: 'BLUE',
      permissions: ["USE_VAD", "ADD_REACTIONS", "READ_MESSAGE_HISTORY", "CREATE_INSTANT_INVITE", "READ_MESSAGES"]
    },
    reason: 'we needed a role for muted',
  })
  .then(role => logger.info(`Created role ${role}`))
  .catch(e => {
    logger.error(e)
  })

  /*
    Loop through all the channels and block muted people to talk there
  */
  message.guild.channels.filter(textchannel => textchannel.type === 'text').forEach(cnl => {
    cnl.overwritePermissions(muteRole, {
        SEND_MESSAGES: false
    })
      .catch(e => logger.error(e))
});
}
<|endoftext|>


<commit_before>/**
* Copyright 2012-2018, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var Axes = require('../../plots/cartesian/axes');
var Lib = require('../../lib');

var orientations = ['v', 'h'];

function getPosition(di) {
    return di.pos;
}

function crossTraceCalc(gd, plotinfo) {
    var calcdata = gd.calcdata;
    var xa = plotinfo.xaxis;
    var ya = plotinfo.yaxis;

    for(var i = 0; i < orientations.length; i++) {
        var orientation = orientations[i];
        var posAxis = orientation === 'h' ? ya : xa;
        var boxList = [];
        var minPad = 0;
        var maxPad = 0;

        // make list of boxes / candlesticks
        // For backward compatibility, candlesticks are treated as if they *are* box traces here
        for(var j = 0; j < calcdata.length; j++) {
            var cd = calcdata[j];
            var t = cd[0].t;
            var trace = cd[0].trace;

            if(trace.visible === true &&
                    (trace.type === 'box' || trace.type === 'candlestick') &&
                    !t.empty &&
                    (trace.orientation || 'v') === orientation &&
                    trace.xaxis === xa._id &&
                    trace.yaxis === ya._id
              ) {
                boxList.push(j);

                if(trace.boxpoints) {
                    minPad = Math.max(minPad, trace.jitter - trace.pointpos - 1);
                    maxPad = Math.max(maxPad, trace.jitter + trace.pointpos - 1);
                }
            }
        }

        setPositionOffset('box', gd, boxList, posAxis, [minPad, maxPad]);
    }
}

function setPositionOffset(traceType, gd, boxList, posAxis, pad) {
    var calcdata = gd.calcdata;
    var fullLayout = gd._fullLayout;
    var pointList = [];

    // N.B. reused in violin
    var numKey = traceType === 'violin' ? '_numViolins' : '_numBoxes';

    var i, j, calcTrace;

    // make list of box points
    for(i = 0; i < boxList.length; i++) {
        calcTrace = calcdata[boxList[i]];
        for(j = 0; j < calcTrace.length; j++) {
            pointList.push(calcTrace[j].pos);
        }
    }

    if(!pointList.length) return;

    // box plots - update dPos based on multiple traces
    // and then use for posAxis autorange
    var boxdv = Lib.distinctVals(pointList);
    var dPos = boxdv.minDiff / 2;

    // if there's no duplication of x points,
    // disable 'group' mode by setting counter to 1
    if(pointList.length === boxdv.vals.length) {
        fullLayout[numKey] = 1;
    }

    // check for forced minimum dtick
    Axes.minDtick(posAxis, boxdv.minDiff, boxdv.vals[0], true);

    var gap = fullLayout[traceType + 'gap'];
    var groupgap = fullLayout[traceType + 'groupgap'];
    var padfactor = (1 - gap) * (1 - groupgap) * dPos / fullLayout[numKey];

    // Find maximum trace width
    // we baseline this at dPos
    var maxHalfWidth = dPos;
    for(i = 0; i < boxList.length; i++) {
        calcTrace = calcdata[boxList[i]];

        if(calcTrace[0].trace.width) {
            if(calcTrace[0].trace.width / 2 > maxHalfWidth) {
                maxHalfWidth = calcTrace[0].trace.width / 2;
            }
        }
    }

    for(i = 0; i < boxList.length; i++) {
        calcTrace = calcdata[boxList[i]];
        // set the width of this box
        // override dPos with trace.width if present
        var thisDPos = calcTrace[0].t.dPos = (calcTrace[0].trace.width / 2) || dPos;
        var positions = calcTrace.map(getPosition);
        // autoscale the x axis - including space for points if they're off the side
        // TODO: this will overdo it if the outermost boxes don't have
        // their points as far out as the other boxes
        var vpadminus = 0;
        var vpadplus = 0;
        if(calcTrace[0].trace.side) {
            if(calcTrace[0].trace.side === 'positive') {
                vpadminus = 0;
                vpadplus = thisDPos + pad[1] * padfactor;
            } else if(calcTrace[0].trace.side === 'negative') {
                vpadminus = thisDPos + pad[0] * padfactor;
                vpadplus = 0;
            }
        } else {
            vpadminus = thisDPos + pad[0] * padfactor;
            vpadplus = thisDPos + pad[1] * padfactor;
        }

        var extremes = Axes.findExtremes(posAxis, positions, {
            vpadminus: vpadminus,
            vpadplus: vpadplus
        });
        calcTrace[0].trace._extremes[posAxis._id] = extremes;
    }

}

module.exports = {
    crossTraceCalc: crossTraceCalc,
    setPositionOffset: setPositionOffset
};
<commit_msg>update algo for padding<commit_after>/**
* Copyright 2012-2018, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var Axes = require('../../plots/cartesian/axes');
var Lib = require('../../lib');

var orientations = ['v', 'h'];

function getPosition(di) {
    return di.pos;
}

function crossTraceCalc(gd, plotinfo) {
    var calcdata = gd.calcdata;
    var xa = plotinfo.xaxis;
    var ya = plotinfo.yaxis;

    for(var i = 0; i < orientations.length; i++) {
        var orientation = orientations[i];
        var posAxis = orientation === 'h' ? ya : xa;
        var boxList = [];
        var minPad = 0;
        var maxPad = 0;

        // make list of boxes / candlesticks
        // For backward compatibility, candlesticks are treated as if they *are* box traces here
        for(var j = 0; j < calcdata.length; j++) {
            var cd = calcdata[j];
            var t = cd[0].t;
            var trace = cd[0].trace;

            if(trace.visible === true &&
                    (trace.type === 'box' || trace.type === 'candlestick') &&
                    !t.empty &&
                    (trace.orientation || 'v') === orientation &&
                    trace.xaxis === xa._id &&
                    trace.yaxis === ya._id
              ) {
                boxList.push(j);

                if(trace.boxpoints) {
                    minPad = Math.max(minPad, trace.jitter - trace.pointpos - 1);
                    maxPad = Math.max(maxPad, trace.jitter + trace.pointpos - 1);
                }
            }
        }

        setPositionOffset('box', gd, boxList, posAxis, [minPad, maxPad]);
    }
}

function setPositionOffset(traceType, gd, boxList, posAxis, pad) {
    var calcdata = gd.calcdata;
    var fullLayout = gd._fullLayout;
    var pointList = [];

    // N.B. reused in violin
    var numKey = traceType === 'violin' ? '_numViolins' : '_numBoxes';

    var i, j, calcTrace;

    // make list of box points
    for(i = 0; i < boxList.length; i++) {
        calcTrace = calcdata[boxList[i]];
        for(j = 0; j < calcTrace.length; j++) {
            pointList.push(calcTrace[j].pos);
        }
    }

    if(!pointList.length) return;

    // box plots - update dPos based on multiple traces
    // and then use for posAxis autorange
    var boxdv = Lib.distinctVals(pointList);
    var dPos = boxdv.minDiff / 2;

    // if there's no duplication of x points,
    // disable 'group' mode by setting counter to 1
    if(pointList.length === boxdv.vals.length) {
        fullLayout[numKey] = 1;
    }

    // check for forced minimum dtick
    Axes.minDtick(posAxis, boxdv.minDiff, boxdv.vals[0], true);

    var gap = fullLayout[traceType + 'gap'];
    var groupgap = fullLayout[traceType + 'groupgap'];
    var padfactor = (1 - gap) * (1 - groupgap) * dPos / fullLayout[numKey];

    // Find maximum trace width
    // we baseline this at dPos
    var maxHalfWidth = dPos;
    for(i = 0; i < boxList.length; i++) {
        calcTrace = calcdata[boxList[i]];

        if(calcTrace[0].trace.width) {
            if(calcTrace[0].trace.width / 2 > maxHalfWidth) {
                maxHalfWidth = calcTrace[0].trace.width / 2;
            }
        }
    }

    for(i = 0; i < boxList.length; i++) {
        calcTrace = calcdata[boxList[i]];
        // set the width of this box
        // override dPos with trace.width if present
        var thisDPos = calcTrace[0].t.dPos = (calcTrace[0].trace.width / 2) || dPos;
        var positions = calcTrace.map(getPosition);
        // autoscale the x axis - including space for points if they're off the side
        // TODO: this will overdo it if the outermost boxes don't have
        // their points as far out as the other boxes

        // var vpadminus = 0;
        // var vpadplus = 0;
        // if(calcTrace[0].trace.side) {
        //     if(calcTrace[0].trace.side === 'positive') {
        //         vpadminus = 0;
        //         vpadplus = thisDPos + pad[1] * padfactor;
        //     } else if(calcTrace[0].trace.side === 'negative') {
        //         vpadminus = thisDPos + pad[0] * padfactor;
        //         vpadplus = 0;
        //     }
        // } else {
        //     vpadminus = thisDPos + pad[0] * padfactor;
        //     vpadplus = thisDPos + pad[1] * padfactor;
        // }

        console.log('*****');
        console.log(calcTrace[0].trace.side);
        console.log('*****');

        var vpadminus = 0;
        var vpadplus = 0;
        if(calcTrace[0].trace.side === 'positive') {
            vpadminus = 0;
            vpadplus = thisDPos + pad[1] * padfactor;
        } else if(calcTrace[0].trace.side === 'negative') {
            vpadminus = thisDPos + pad[0] * padfactor;
            vpadplus = 0;
        } else {
            // if side === 'both'
            vpadminus = thisDPos + pad[0] * padfactor;
            vpadplus = thisDPos + pad[1] * padfactor;
        }

        var extremes = Axes.findExtremes(posAxis, positions, {
            vpadminus: vpadminus,
            vpadplus: vpadplus
        });
        calcTrace[0].trace._extremes[posAxis._id] = extremes;
    }

}

module.exports = {
    crossTraceCalc: crossTraceCalc,
    setPositionOffset: setPositionOffset
};
<|endoftext|>


<commit_before>import babelFunctions from "./babelFunctions"
import {makeTraceObject} from "./FromJSString"

describe("babelFunctions", function(){
    describe("f__add", function(){
        it("Supports adding a string to an object", function(){
            var obj = {
                toString: () => "obj"
            }
            var res = babelFunctions.f__add(obj, "sth")
            expect(res.value).toBe("objsth")
            expect(res.origin.inputValues[0]).not.toBe(undefined)
            expect(res.origin.inputValues[1]).not.toBe(undefined)
        })
        it("Doesn't break adding two numbers together", function(){
            var res = babelFunctions.f__add(1,2)
            expect(res).toBe(3)
        })
        it("Supports adding booleans", function(){
            var res = babelFunctions.f__add(false, true)
            expect(res).toBe(1)
        })
        it("Supports adding booleans and numbers", function(){
            var res = babelFunctions.f__add(3, true)
            expect(res).toBe(4)
        })
    })

    describe("f__tripleEqual", function(){
        it("Knowns that traced 'a' and traced 'a' are equal", function(){
            var a = makeTraceObject({
                value: 'a',
                origin: null
            })
            var b = makeTraceObject({
                value: 'a',
                origin: null
            })
            var res = babelFunctions.f__tripleEqual(a, b)
            expect(res).toBe(true)
        })
        it("Knowns that traced 'a' and traced 'b' are not equal", function(){
            var a = makeTraceObject({
                value: 'a',
                origin: null
            })
            var b = makeTraceObject({
                value: 'b',
                origin: null
            })
            var res = babelFunctions.f__tripleEqual(a, b)
            expect(res).toBe(false)
        })
    })

    describe("f__subtract", function(){
        it("Supports subtracting undfined from a number", function(){
            var result = babelFunctions.f__subtract(5,  undefined)
            expect(isNaN(result)).toBe(true)
        })
    })

    describe("f__doubleEqual", function(){
        it("Can compare a string to an object that returns a traced value from toString", function(){
            var obj = {
                toString: function(){
                    return makeTraceObject({
                        value: "Cake",
                        origin: {}
                    })
                }
            }

            expect(babelFunctions.f__doubleEqual(obj, "Cake")).toBe(true)
        })
    })

    describe("f__assign", function(){
        it("Allows assigning to a null key", function(){
            var obj = {}
            babelFunctions.f__assign(obj, null, 123)

            expect(obj["null"]).toBe(123)
        })
    })
})
<commit_msg>Add tests checking for String("a") === "a" support.<commit_after>import babelFunctions from "./babelFunctions"
import {makeTraceObject} from "./FromJSString"

describe("babelFunctions", function(){
    describe("f__add", function(){
        it("Supports adding a string to an object", function(){
            var obj = {
                toString: () => "obj"
            }
            var res = babelFunctions.f__add(obj, "sth")
            expect(res.value).toBe("objsth")
            expect(res.origin.inputValues[0]).not.toBe(undefined)
            expect(res.origin.inputValues[1]).not.toBe(undefined)
        })
        it("Doesn't break adding two numbers together", function(){
            var res = babelFunctions.f__add(1,2)
            expect(res).toBe(3)
        })
        it("Supports adding booleans", function(){
            var res = babelFunctions.f__add(false, true)
            expect(res).toBe(1)
        })
        it("Supports adding booleans and numbers", function(){
            var res = babelFunctions.f__add(3, true)
            expect(res).toBe(4)
        })
    })

    describe("f__tripleEqual", function(){
        it("Knowns that traced 'a' and traced 'a' are equal", function(){
            var a = makeTraceObject({
                value: 'a',
                origin: null
            })
            var b = makeTraceObject({
                value: 'a',
                origin: null
            })
            var res = babelFunctions.f__tripleEqual(a, b)
            expect(res).toBe(true)
        })
        it("Knowns that traced 'a' and traced 'b' are not equal", function(){
            var a = makeTraceObject({
                value: 'a',
                origin: null
            })
            var b = makeTraceObject({
                value: 'b',
                origin: null
            })
            var res = babelFunctions.f__tripleEqual(a, b)
            expect(res).toBe(false)
        })
        it("Knows that String('a') and 'a' are equal", function(){
            var a = nativeStringObject("a")
            var res = babelFunctions.f__tripleEqual(a, "a")
            expect(res).toBe(true)
        })
    })

    describe("f__subtract", function(){
        it("Supports subtracting undfined from a number", function(){
            var result = babelFunctions.f__subtract(5,  undefined)
            expect(isNaN(result)).toBe(true)
        })
    })

    describe("f__doubleEqual", function(){
        it("Can compare a string to an object that returns a traced value from toString", function(){
            var obj = {
                toString: function(){
                    return makeTraceObject({
                        value: "Cake",
                        origin: {}
                    })
                }
            }

            expect(babelFunctions.f__doubleEqual(obj, "Cake")).toBe(true)
        })

        it("Knows that String('a') and 'a' are equal", function(){
            var a = nativeStringObject("a")
            var res = babelFunctions.f__doubleEqual(a, "a")
            expect(res).toBe(true)
        })
    })

    describe("f__assign", function(){
        it("Allows assigning to a null key", function(){
            var obj = {}
            babelFunctions.f__assign(obj, null, 123)

            expect(obj["null"]).toBe(123)
        })
    })
})
<|endoftext|>


<commit_before>export default ( parentDom, item, nextItem ) => {

    let domItem = item.dom,
    domRefItem = nextItem && nextItem.dom;

    if ( domItem !== domRefItem ) {

        if ( domRefItem ) {

            parentDom.insertBefore( domItem, domRefItem );

        } else {

            parentDom.appendChild( domItem );

        }
    }
};
<commit_msg>removed space<commit_after>export default ( parentDom, item, nextItem ) => {

    let domItem = item.dom,
    domRefItem = nextItem && nextItem.dom;

    if ( domItem !== domRefItem ) {

        if ( domRefItem ) {

            parentDom.insertBefore( domItem, domRefItem );

        } else {

            parentDom.appendChild( domItem );
        }
    }
};
<|endoftext|>


<commit_before>#!/usr/bin/env node

// Copyright 2016 Circonus, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

'use strict';

const path = require('path');

const app = require('commander');
const chalk = require('chalk');
const sprintf = require('sprintf-js').sprintf;

const cosi = require(path.resolve(path.join(__dirname, '..', 'lib', 'cosi')));
const templateList = require(path.join(cosi.lib_dir, 'template', 'list'));

/**
 * generic function to print lines
 * @arg {String} id of template
 * @arg {String} type of template
 * @arg {String} description of template
 * @returns {Undefined} nothing
 */
function emitLine(id, type, description) {
    const lineFormat = '%-8s %-8s %-60s';

    if (id) {
        console.log(sprintf(lineFormat, id, type, description));
    } else {
        console.log(chalk.underline(sprintf(lineFormat, 'ID', 'Type', 'Description')));
    }
}

app.
    version(cosi.app_version).
    option('-q, --quiet', 'no header lines').
    parse(process.argv);

if (!app.quiet) {
    console.log(chalk.bold(app.name()), `v${app.version()}`);
}

templateList(cosi.reg_dir, (err, list) => {
    if (err) {
        console.log('template list', list, err);
        process.exit(1);
    }

    if (list.length === 0) {
        console.error(chalk.red('No templates found'));
        process.exit(1);
    }

    if (!app.quiet) {
        emitLine();
    }

    for (const template of list) {
        emitLine(
            template.id,
            template.type,
            template.description
        );
    }
});
<commit_msg>convert to promise<commit_after>#!/usr/bin/env node

// Copyright 2016 Circonus, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

'use strict';

const path = require('path');

const app = require('commander');
const chalk = require('chalk');
const sprintf = require('sprintf-js').sprintf;

const cosi = require(path.resolve(path.join(__dirname, '..', 'lib', 'cosi')));
const templateList = require(path.join(cosi.lib_dir, 'template', 'list'));

/**
 * generic function to print lines
 * @arg {String} id of template
 * @arg {String} type of template
 * @arg {String} description of template
 * @returns {Undefined} nothing
 */
function emitLine(id, type, description) {
    const lineFormat = '%-8s %-8s %-60s';

    if (id) {
        console.log(sprintf(lineFormat, id, type, description));
    } else {
        console.log(chalk.underline(sprintf(lineFormat, 'ID', 'Type', 'Description')));
    }
}

app.
    version(cosi.app_version).
    option('-q, --quiet', 'no header lines').
    parse(process.argv);

if (!app.quiet) {
    console.log(chalk.bold(app.name()), `v${app.version()}`);
}

templateList(cosi.reg_dir).
    then((list) => {
        if (list.length === 0) {
            console.error(chalk.red('No templates found'));
            process.exit(1);
        }

        if (!app.quiet) {
            emitLine();
        }

        for (const template of list) {
            emitLine(
                template.config.id,
                template.config.type,
                template.config.description
            );
        }
    }).
    catch((err) => {
        console.log('template list', err);
        process.exit(1);
    });
<|endoftext|>


<commit_before>// lodash-contrib (lodash.util.strings.js 0.0.1)
// (c) 2013 Michael Fogus, DocumentCloud and Investigative Reporters & Editors
// lodash-contrib may be freely distributed under the MIT license.

(function (root) {

  // Baseline setup
  // --------------

  // Establish the root object, `window` in the browser, or `global` on the server.
  var _ = root._ || require('lodash');

  // Helpers
  // -------

  // No reason to create regex more than once
  var plusRegex = /\+/g;

  var urlDecode = function (s) {
    return decodeURIComponent(s.replace(plusRegex, '%20'));
  };

  // Mixing in the string utils
  // ----------------------------

  _.mixin({
    // Explodes a string into an array of chars
    explode: function (s) {
      return s.split('');
    },

    // Parses a query string into a hash
    fromQuery: function(str) {
      var obj = str.split('&').reduce(function (seed, param) {
        var pair = param.split('=');
        var key = urlDecode(pair[0]);
        var val = urlDecode(pair[1]);
        seed[key] = val;
        return seed;
      }, {});
      return obj;
    },

    // Implodes and array of chars into a string
    implode: function (a) {
      return a.join('');
    },

    // Converts a string to camel case
    camelCase: function (string) {
      return  string.replace(/-([a-z])/g, function (g) {
        return g[1].toUpperCase();
      });
    },

    // Converts camel case to dashed (opposite of _.camelCase)
    toDash: function (string) {
      string = string.replace(/([A-Z])/g, function ($1) {
        return "-" + $1.toLowerCase();
      });
      // remove first dash
      return  ( string.charAt(0) == '-' ) ? string.substr(1) : string;
    },

    // Creates a query string from a hash
    toQuery: function(obj) {
      var parameters = _.map(obj, function (v, k) {
        return encodeURIComponent(k) + '=' + encodeURIComponent(v);
      });
      return parameters.join('&');
    },

    // Reports whether a string contains a search string.
    strContains: function (str, search) {
      if (typeof str != 'string') throw new TypeError;
      return (str.indexOf(search) != -1);
    },

    // Reports whether a string contains a search string.
    capitalize: function capitalize(string) {
      return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
    },

    // Slugify a string. Makes lowercase, and converts dots and spaces to dashes.
    slugify: function (urlString) {
      return urlString.replace(/ /g, '-').replace(/\./, '').toLowerCase();
    },

    // Slugify a string. Makes lowercase, and converts dots and spaces to dashes.
    regexEscape: function (regexCandidate) {
      return regexCandidate.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
    },

    humanize: function (slugish) {
      return slugish
        // Replace _ with a space
        .replace(/_/g, ' ')
        // insert a space between lower & upper
        .replace(/([a-z])([A-Z])/g, '$1 $2')
        // space before last upper in a sequence followed by lower
        .replace(/\b([A-Z]+)([A-Z])([a-z])/, '$1 $2$3')
        // uppercase the first character
        .replace(/^./, function(str){ return str.toUpperCase(); });
    }

  });
})(this);
<commit_msg>Adding stripTags<commit_after>// lodash-contrib (lodash.util.strings.js 0.0.1)
// (c) 2013 Michael Fogus, DocumentCloud and Investigative Reporters & Editors
// lodash-contrib may be freely distributed under the MIT license.

(function (root) {

  // Baseline setup
  // --------------

  // Establish the root object, `window` in the browser, or `global` on the server.
  var _ = root._ || require('lodash');

  // Helpers
  // -------

  // No reason to create regex more than once
  var plusRegex = /\+/g;

  var urlDecode = function (s) {
    return decodeURIComponent(s.replace(plusRegex, '%20'));
  };

  // Mixing in the string utils
  // ----------------------------

  _.mixin({
    // Explodes a string into an array of chars
    explode: function (s) {
      return s.split('');
    },

    // Parses a query string into a hash
    fromQuery: function(str) {
      var obj = str.split('&').reduce(function (seed, param) {
        var pair = param.split('=');
        var key = urlDecode(pair[0]);
        var val = urlDecode(pair[1]);
        seed[key] = val;
        return seed;
      }, {});
      return obj;
    },

    // Implodes and array of chars into a string
    implode: function (a) {
      return a.join('');
    },

    // Converts a string to camel case
    camelCase: function (string) {
      return  string.replace(/-([a-z])/g, function (g) {
        return g[1].toUpperCase();
      });
    },

    // Converts camel case to dashed (opposite of _.camelCase)
    toDash: function (string) {
      string = string.replace(/([A-Z])/g, function ($1) {
        return "-" + $1.toLowerCase();
      });
      // remove first dash
      return  ( string.charAt(0) == '-' ) ? string.substr(1) : string;
    },

    // Creates a query string from a hash
    toQuery: function(obj) {
      var parameters = _.map(obj, function (v, k) {
        return encodeURIComponent(k) + '=' + encodeURIComponent(v);
      });
      return parameters.join('&');
    },

    // Reports whether a string contains a search string.
    strContains: function (str, search) {
      if (typeof str != 'string') throw new TypeError;
      return (str.indexOf(search) != -1);
    },

    // Reports whether a string contains a search string.
    capitalize: function capitalize(string) {
      return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
    },

    // Slugify a string. Makes lowercase, and converts dots and spaces to dashes.
    slugify: function (urlString) {
      return urlString.replace(/ /g, '-').replace(/\./, '').toLowerCase();
    },

    // Slugify a string. Makes lowercase, and converts dots and spaces to dashes.
    regexEscape: function (regexCandidate) {
      return regexCandidate.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
    },

    humanize: function (slugish) {
      return slugish
        // Replace _ with a space
        .replace(/_/g, ' ')
        // insert a space between lower & upper
        .replace(/([a-z])([A-Z])/g, '$1 $2')
        // space before last upper in a sequence followed by lower
        .replace(/\b([A-Z]+)([A-Z])([a-z])/, '$1 $2$3')
        // uppercase the first character
        .replace(/^./, function(str){ return str.toUpperCase(); });
    },

    stripTags: function (suspectString) {
      var str = suspectString.replace(/<\/?[^<>]*>/gi, '');
      return str;
    }

  });
})(this);
<|endoftext|>


<commit_before>//* @flow */
import React, { PropTypes } from 'react'
import { connect } from 'react-redux'
import { Link } from 'react-router'
import { browserHistory } from 'react-router'
import classes from 'styles/sitewide/index.scss'
import d3 from 'd3'
import { loadDensityComposite,loadNewValues,loadShare,loadShareEmpNoAccRet,loadShareEmpHighTech, } from 'redux/modules/densityData'
import { loadFluidityComposite,loadInc5000Data, loadNetMigrationIrs, loadTotalMigration,loadAnnualChurn } from 'redux/modules/fluidityData'
import { loadDiversityComposite,loadOpportunityData,loadForeignBornData,loadEmpVarianceData } from 'redux/modules/diversityData'
import { loadCombinedComposite } from 'redux/modules/combinedData'
import RankingsTable from 'components/tables/RankingsTable'
import HoverBox from 'components/ranks/HoverBox'
import CategoryNames from 'components/misc/categoryNames'
import Select from 'react-select'
import {StickyContainer, Sticky} from 'react-sticky'
import 'react-select/dist/react-select.css';

let roundFormat = d3.format(".2f")

export class RankingsView extends React.Component<void, Props, void> {
   constructor () {
    super()

    this.state = {
      active:'combinedcomposite',
      category:'combined',
      year:2013,
      hoverMetro:null
    }

    this._onHover = this._onHover.bind(this);

  }
  componentWillMount () {
    this._initGraph();
  }

  _onHover(feature){
    this.setState({hoverMetro:feature});
  }

  _initGraph () {
    if(!this.props['densitycomposite']){
      this.props['getdensitycomposite']()
    }
    if(!this.props['fluiditycomposite']){
      this.props['getfluiditycomposite']()
    }
    if(!this.props['diversitycomposite']){
      this.props['getdiversitycomposite']()
    }
    if(!this.props['combinedcomposite']){
      this.props['getcombinedcomposite']()
    }
  }

  render () {
    var scope = this;
    if(!this.props[this.state.active]){
      this.props['get'+this.state.active]()
      return
Loading...

    }

    var data = Array.isArray(this.props[this.state.active]) ? this.props[this.state.active] : this.props[this.state.active]['relative'] ? this.props[this.state.active]['relative'] : this.props[this.state.active]['raw']

    var yearOptions = d3.range(
            [d3.min(data, function(c) { return d3.min(c.values, function(v) { return v.x }); })],
            [d3.max(data, function(c) { return d3.max(c.values, function(v) { return v.x }); })+1]
        ).map(year => {
      return {value:year,label:year}
    })

    if(this.state.active == "diversityincomebasedonchildhood"){
      yearOptions = [
        {value:"lowIncome",label:"Low"},
        {value:"highIncome",label:"High"},
        {value:"combined",label:"Combined"}
      ]
    }

    var metricOptions = [
        {value:{category:"combined",metric:"combinedcomposite"},label:"Combined Composite"},
        {value:{category:"density",metric:"densitycomposite"},label:"Density Composite"},
        {value:{category:"diversity",metric:"diversitycomposite"},label:"Diversity Composite"},
        {value:{category:"fluidity",metric:"fluiditycomposite"},label:"Fluidity Composite"},
        {value:{category:"density",metric:"densitynewfirms"},label:CategoryNames['densitynewfirms']},
        {value:{category:"density",metric:"densityshareofemploymentinnewfirms"},label:CategoryNames['densityshareofemploymentinnewfirms']},
        {value:{category:"density",metric:"densityshareEmpNoAccRet"},label:CategoryNames['densityshareEmpNoAccRet']},
        {value:{category:"density",metric:"densityshareEmpHighTech"},label:CategoryNames['densityshareEmpHighTech']},
        {value:{category:"fluidity",metric:"fluidityhighgrowthfirms"},label:CategoryNames['fluidityhighgrowthfirms']},
        {value:{category:"fluidity",metric:"fluiditynetmigration"},label:CategoryNames['fluiditynetmigration']},
        {value:{category:"fluidity",metric:"fluiditytotalmigration"},label:CategoryNames['fluiditytotalmigration']},
        {value:{category:"fluidity",metric:"fluidityannualchurn"},label:CategoryNames['fluidityannualchurn']},
        {value:{category:"diversity",metric:"diversityincomebasedonchildhood"},label:CategoryNames['diversityincomebasedonchildhood']},
        {value:{category:"diversity",metric:"diversitypercentageofforeignbornpopulation"},label:CategoryNames['diversitypercentageofforeignbornpopulation']},
        {value:{category:"diversity",metric:"diversityemploymentlocationquotientvariance"},label:CategoryNames['diversityemploymentlocationquotientvariance']}
    ]

    function metricSelectChange (value){

      if(value.value.metric == "diversityincomebasedonchildhood"){
        var newYear = "combined"
      }
      else if(scope.state.active == "diversityincomebasedonchildhood"){
        var newYear = 2013;
      }
      else{
        var newYear = scope.state.year
      }
      scope.setState({active:value.value.metric,category:value.value.category,year:newYear})
    }

    function yearSelectChange (value){
      scope.setState({year:value.value})
    }

    return (

          {metricOptions.filter(d => d.value.metric == this.state.active)[0].label}

        <StickyContainer>
          <Sticky>

                <Select
                className={classes['Select']}
                name="yearSelect"
                value={yearOptions.filter(d => { return d.value == this.state.year })[0]}
                options={yearOptions}
                onChange={yearSelectChange}
                clearable={false}
                />

                <Select
                className={classes['Select']}
                name="metricSelect"
                value={metricOptions.filter(d => { return d.value.metric == this.state.active })[0]}
                options={metricOptions}
                onChange={metricSelectChange}
                clearable={false}
                />

                <HoverBox
                  metroId={this.state.hoverMetro ? this.state.hoverMetro : data[0].key}
                  year={this.state.year}
                  activeComponent={this.state.category}
                />

          </Sticky>
        </StickyContainer>

            <RankingsTable
              data={data}
              active={this.state.active}
              year={this.state.year}
              onHover={this._onHover}
            />

    )
  }
}

const mapStateToProps = (state) => ({
  densitycomposite:state.densityData.compositeData,
  densitynewfirms:state.densityData.newValuesData,
  densityshareofemploymentinnewfirms:state.densityData.shareData,
  densityshareEmpNoAccRet:state.densityData.shareEmpNoAccRet,
  densityshareEmpHighTech:state.densityData.shareEmpHighTech,
  fluiditycomposite:state.fluidityData.compositeData,
  fluidityhighgrowthfirms:state.fluidityData.inc5000,
  fluiditynetmigration:state.fluidityData.irsNet,
  fluiditytotalmigration:state.fluidityData.totalMigrationFlow,
  fluidityannualchurn:state.fluidityData.annualChurn,
  diversitycomposite : state.diversityData.diversitycomposite,
  diversityincomebasedonchildhood:state.diversityData.opportunity,
  diversitypercentageofforeignbornpopulation:state.diversityData.foreignborn,
  diversityemploymentlocationquotientvariance:state.diversityData.empVariance,
  combinedcomposite : state.combinedData.combinedcomposite,
  metros : state.metros,
  homeState : state.homeData
})

export default connect((mapStateToProps), {
  getdensitycomposite: () => loadDensityComposite(),
  getdensitynewfirms: () => loadNewValues(),
  getdensityshareofemploymentinnewfirms: () => loadShare(),
  getdensityshareEmpNoAccRet: () => loadShareEmpNoAccRet(),
  getdensityshareEmpHighTech: () => loadShareEmpHighTech(),
  getfluiditycomposite: () => loadFluidityComposite(),
  getfluidityhighgrowthfirms: () => loadInc5000Data(),
  getfluiditynetmigration: () => loadNetMigrationIrs(),
  getfluiditytotalmigration: () => loadTotalMigration(),
  getfluidityannualchurn:() => loadAnnualChurn(),
  getdiversitycomposite: () => loadDiversityComposite(),
  getdiversityincomebasedonchildhood: () => loadOpportunityData(),
  getdiversitypercentageofforeignbornpopulation: () => loadForeignBornData(),
  getdiversityemploymentlocationquotientvariance: () => loadEmpVarianceData(),
  getcombinedcomposite: () => loadCombinedComposite(),
  changeHomeState: (state) => changeHomeState(state)
})(RankingsView)
<commit_msg>Added react-sticky, so the selectors and hoverbox are stuck as you scroll through the table<commit_after>//* @flow */
import React, { PropTypes } from 'react'
import { connect } from 'react-redux'
import { Link } from 'react-router'
import { browserHistory } from 'react-router'
import classes from 'styles/sitewide/index.scss'
import d3 from 'd3'
import { loadDensityComposite,loadNewValues,loadShare,loadShareEmpNoAccRet,loadShareEmpHighTech, } from 'redux/modules/densityData'
import { loadFluidityComposite,loadInc5000Data, loadNetMigrationIrs, loadTotalMigration,loadAnnualChurn } from 'redux/modules/fluidityData'
import { loadDiversityComposite,loadOpportunityData,loadForeignBornData,loadEmpVarianceData } from 'redux/modules/diversityData'
import { loadCombinedComposite } from 'redux/modules/combinedData'
import RankingsTable from 'components/tables/RankingsTable'
import HoverBox from 'components/ranks/HoverBox'
import CategoryNames from 'components/misc/categoryNames'
import Select from 'react-select'
import {StickyContainer, Sticky} from 'react-sticky'
import 'react-select/dist/react-select.css';

let roundFormat = d3.format(".2f")

export class RankingsView extends React.Component<void, Props, void> {
   constructor () {
    super()

    this.state = {
      active:'combinedcomposite',
      category:'combined',
      year:2013,
      hoverMetro:null
    }

    this._onHover = this._onHover.bind(this);

  }
  componentWillMount () {
    this._initGraph();
  }

  _onHover(feature){
    this.setState({hoverMetro:feature});
  }

  _initGraph () {
    if(!this.props['densitycomposite']){
      this.props['getdensitycomposite']()
    }
    if(!this.props['fluiditycomposite']){
      this.props['getfluiditycomposite']()
    }
    if(!this.props['diversitycomposite']){
      this.props['getdiversitycomposite']()
    }
    if(!this.props['combinedcomposite']){
      this.props['getcombinedcomposite']()
    }
  }

  render () {
    var scope = this;
    if(!this.props[this.state.active]){
      this.props['get'+this.state.active]()
      return
Loading...

    }

    var data = Array.isArray(this.props[this.state.active]) ? this.props[this.state.active] : this.props[this.state.active]['relative'] ? this.props[this.state.active]['relative'] : this.props[this.state.active]['raw']

    var yearOptions = d3.range(
            [d3.min(data, function(c) { return d3.min(c.values, function(v) { return v.x }); })],
            [d3.max(data, function(c) { return d3.max(c.values, function(v) { return v.x }); })+1]
        ).map(year => {
      return {value:year,label:year}
    })

    if(this.state.active == "diversityincomebasedonchildhood"){
      yearOptions = [
        {value:"lowIncome",label:"Low"},
        {value:"highIncome",label:"High"},
        {value:"combined",label:"Combined"}
      ]
    }

    var metricOptions = [
        {value:{category:"combined",metric:"combinedcomposite"},label:"Combined Composite"},
        {value:{category:"density",metric:"densitycomposite"},label:"Density Composite"},
        {value:{category:"diversity",metric:"diversitycomposite"},label:"Diversity Composite"},
        {value:{category:"fluidity",metric:"fluiditycomposite"},label:"Fluidity Composite"},
        {value:{category:"density",metric:"densitynewfirms"},label:CategoryNames['densitynewfirms']},
        {value:{category:"density",metric:"densityshareofemploymentinnewfirms"},label:CategoryNames['densityshareofemploymentinnewfirms']},
        {value:{category:"density",metric:"densityshareEmpNoAccRet"},label:CategoryNames['densityshareEmpNoAccRet']},
        {value:{category:"density",metric:"densityshareEmpHighTech"},label:CategoryNames['densityshareEmpHighTech']},
        {value:{category:"fluidity",metric:"fluidityhighgrowthfirms"},label:CategoryNames['fluidityhighgrowthfirms']},
        {value:{category:"fluidity",metric:"fluiditynetmigration"},label:CategoryNames['fluiditynetmigration']},
        {value:{category:"fluidity",metric:"fluiditytotalmigration"},label:CategoryNames['fluiditytotalmigration']},
        {value:{category:"fluidity",metric:"fluidityannualchurn"},label:CategoryNames['fluidityannualchurn']},
        {value:{category:"diversity",metric:"diversityincomebasedonchildhood"},label:CategoryNames['diversityincomebasedonchildhood']},
        {value:{category:"diversity",metric:"diversitypercentageofforeignbornpopulation"},label:CategoryNames['diversitypercentageofforeignbornpopulation']},
        {value:{category:"diversity",metric:"diversityemploymentlocationquotientvariance"},label:CategoryNames['diversityemploymentlocationquotientvariance']}
    ]

    function metricSelectChange (value){

      if(value.value.metric == "diversityincomebasedonchildhood"){
        var newYear = "combined"
      }
      else if(scope.state.active == "diversityincomebasedonchildhood"){
        var newYear = 2013;
      }
      else{
        var newYear = scope.state.year
      }
      scope.setState({active:value.value.metric,category:value.value.category,year:newYear})
    }

    function yearSelectChange (value){
      scope.setState({year:value.value})
    }

    return (

          {metricOptions.filter(d => d.value.metric == this.state.active)[0].label}

        <StickyContainer>

            <Sticky style={{paddingTop:"5px"}}>

                  <Select
                  className={classes['Select']}
                  name="yearSelect"
                  value={yearOptions.filter(d => { return d.value == this.state.year })[0]}
                  options={yearOptions}
                  onChange={yearSelectChange}
                  clearable={false}
                  />

                  <Select
                  className={classes['Select']}
                  name="metricSelect"
                  value={metricOptions.filter(d => { return d.value.metric == this.state.active })[0]}
                  options={metricOptions}
                  onChange={metricSelectChange}
                  clearable={false}
                  />

                  <HoverBox
                    metroId={this.state.hoverMetro ? this.state.hoverMetro : data[0].key}
                    year={this.state.year}
                    activeComponent={this.state.category}
                  />

            </Sticky>

              <RankingsTable
                data={data}
                active={this.state.active}
                year={this.state.year}
                onHover={this._onHover}
              />

        </StickyContainer>

    )
  }
}

const mapStateToProps = (state) => ({
  densitycomposite:state.densityData.compositeData,
  densitynewfirms:state.densityData.newValuesData,
  densityshareofemploymentinnewfirms:state.densityData.shareData,
  densityshareEmpNoAccRet:state.densityData.shareEmpNoAccRet,
  densityshareEmpHighTech:state.densityData.shareEmpHighTech,
  fluiditycomposite:state.fluidityData.compositeData,
  fluidityhighgrowthfirms:state.fluidityData.inc5000,
  fluiditynetmigration:state.fluidityData.irsNet,
  fluiditytotalmigration:state.fluidityData.totalMigrationFlow,
  fluidityannualchurn:state.fluidityData.annualChurn,
  diversitycomposite : state.diversityData.diversitycomposite,
  diversityincomebasedonchildhood:state.diversityData.opportunity,
  diversitypercentageofforeignbornpopulation:state.diversityData.foreignborn,
  diversityemploymentlocationquotientvariance:state.diversityData.empVariance,
  combinedcomposite : state.combinedData.combinedcomposite,
  metros : state.metros,
  homeState : state.homeData
})

export default connect((mapStateToProps), {
  getdensitycomposite: () => loadDensityComposite(),
  getdensitynewfirms: () => loadNewValues(),
  getdensityshareofemploymentinnewfirms: () => loadShare(),
  getdensityshareEmpNoAccRet: () => loadShareEmpNoAccRet(),
  getdensityshareEmpHighTech: () => loadShareEmpHighTech(),
  getfluiditycomposite: () => loadFluidityComposite(),
  getfluidityhighgrowthfirms: () => loadInc5000Data(),
  getfluiditynetmigration: () => loadNetMigrationIrs(),
  getfluiditytotalmigration: () => loadTotalMigration(),
  getfluidityannualchurn:() => loadAnnualChurn(),
  getdiversitycomposite: () => loadDiversityComposite(),
  getdiversityincomebasedonchildhood: () => loadOpportunityData(),
  getdiversitypercentageofforeignbornpopulation: () => loadForeignBornData(),
  getdiversityemploymentlocationquotientvariance: () => loadEmpVarianceData(),
  getcombinedcomposite: () => loadCombinedComposite(),
  changeHomeState: (state) => changeHomeState(state)
})(RankingsView)
<|endoftext|>


<commit_before>( function( VN ) {

	VN.prototype.screenCharacterId = null;
	VN.prototype.characterContainer = null;
	VN.prototype.characters = [];

	VN.prototype.addCharacter = function addCharacter( character, delay, fadeIn ) {

		var self = this;

		function createCharacter() {

			// show
			self.screenCharacterId.style.display = "block";

			var characterWidth = character.width;
			var characterHeight = character.height;

			var transformX = characterWidth / 2;

			var posY = ( self.screenHeight - characterHeight ) +
					   ( self.screenHeight * character.pos.y );
			var posX = ( self.screenWidth * character.pos.x );

			var position = {
				x : Math.floor( posX ),
				y : Math.floor( posY ),
				z : 0
			};
			var transformOrigin = {
				x : transformX,
				y : 0,
				z : 0
			};

			var c = getCharacterConstructor( self );

			c = c( characterWidth, characterHeight, position, transformOrigin );

			c.setBackground( characterWidth, characterHeight, self.getCharacterImage( character ) );

			// To help us keep track of the character, use their name
			c.name = character.name;

			return c;
		}

		function callAddCharacter( c ) {

			self.characterContainer.addChild( c.sprite );
			self.characters.push( c );

		}

		function eventToAdd() {

			var c = createCharacter();

			if ( fadeIn ) {

				c.fadeIn( delay );

			}

			callAddCharacter( c );

		}

		this.eventTracker.addEvent( "nowait", eventToAdd, delay );

	};

	VN.prototype.getCharacter = function getCharacter( name ) {

		var characterObjectInfo = this.util.getObjectInList( this.characters, "name", name );

		return characterObjectInfo.obj;

	};

	VN.prototype.getCharacterImage = function getCharacterImage( character, type ) {

		// character image is string
		// character = { image : "character/happy.png" };

		// character image is object
		// type = default if not provided
		// character = { image :
		// { default : "character/happy.png", sleep : "character/sleep.png" } }

		var imgPath = this.imgPath;
		var charImage = character && character.image ? character.image : null;

		// TODO: add function to detect if charImage is an object and not an array...?
		if ( charImage && typeof charImage === "object" ) {

			if ( type ) {

				charImage = charImage[ type ];

			} else {

				charImage = charImage[ "default" ];

			}

			if ( typeof charImage === "object" ) {

				charImage = {
					src : imgPath + charImage.src,
					position : charImage.position
				};

			} else {

				charImage = imgPath + charImage;

			}

		} else if ( charImage ) {

			charImage = imgPath + charImage;

		}

		return charImage;

	};

	VN.prototype.changeCharacterImage = function changeCharacterImage( character, type ) {

		var self = this;

		function eventToAdd() {

			self.setCharacterImage( character, type );

		}

		this.eventTracker.addEvent( "nowait", eventToAdd );

	};

	VN.prototype.setCharacterImage = function setCharacterImage( character, type ) {

		var characterObject = this.getCharacter( character.name );
		var characterImage = this.getCharacterImage( character, type );

		if ( typeof characterImage === "object" ) {

				requestAnimationFrame( function() {

					characterObject.sprite.setCSS( "background-position", characterImage.position );
					characterObject.sprite.setCSS( "background-image",
						"url('" + characterImage.src + "')" );

				} );

		} else {

				requestAnimationFrame( function() {

					characterObject.sprite.setCSS( "background-image",
						"url('" + characterImage + "')" );

				} );

		}

	};

	VN.prototype.removeCharacter = function removeCharacter( character, delay, fadeOut ) {

		var self = this;

		// TODO: refactor character object
		function callRemoveCharacter() {

			var characterObjectInfo = self.util.getObjectInList( self.characters, "name", character.name );
			var indexInList = characterObjectInfo.id;

			self.characterContainer.removeChildAt( indexInList + 1 ); // 0 for container so +1
			self.characters.splice( indexInList, 1 );
		}

		function eventToAdd() {

			if ( fadeOut ) {
				var characterObject = self.getCharacter( character.name );
				characterObject.fadeOut( delay );
			}

			self.eventTracker.delayCallback( delay, callRemoveCharacter );
		}

		this.eventTracker.addEvent( "nowait", eventToAdd, delay );

	};

	VN.prototype.removeAllCharacter = function removeAllCharacter( delay ) {

		var self = this;

		function callRemoveAllCharacter() {
			self.resetCharacters();
		}

		function eventToAdd() {
			self.eventTracker.delayCallback( delay, callRemoveAllCharacter );
		}

		this.eventTracker.addEvent( "nowait", eventToAdd, delay );

	};

	VN.prototype.resetCharacters = function resetCharacters() {

		var characters = this.characterContainer ? this.characterContainer.children : [];
		var totalCharacters = characters.length;

		for( var i = totalCharacters - 1; i >= 1; i-- ) {

			this.characterContainer.removeChildAt( i );

		}

		this.characters = [];

	};

	VN.prototype.moveCharacter = function moveCharacter( character, x, y, delay ) {

		var self = this;

		function eventToAdd() {

			var characterObject = self.getCharacter( character.name );
			var sprite = characterObject.sprite;
			var newPos = {
				x : typeof x !== "undefined" ? x > 1 || x < -1 ? x : x * self.screenWidth : sprite.x,
				y : typeof y !== "undefined" ? y > 1 || y < -1 ? y : y * self.screenHeight : sprite.y
			};

			if ( delay ) {

				characterObject.move( newPos.x, newPos.y, 0, delay );

			} else {

				requestAnimationFrame( function() {

					sprite.x = newPos.x;
					sprite.y = newPos.y;
					sprite.update();

				} );

			}

		}

		this.eventTracker.addEvent( "nowait", eventToAdd );

	};

	VN.prototype.fadeCharacter = function fadeCharacter( character, type, speed, from, to ) {

		var self = this;

		function eventToAdd() {

			var characterObject = self.getCharacter( character.name );

			if ( type == "in" ) {

				characterObject.fadeIn( speed, from, to );

			} else if ( type == "out" ) {

				characterObject.fadeOut( speed, from, to );

			}
		}

		this.eventTracker.addEvent( "nowait", eventToAdd );

	};

	VN.prototype.flipCharacter = function flipCharacter( character ) {

		var self = this;

		function eventToAdd() {

			var characterObject = self.getCharacter( character.name );
			var sprite = characterObject.sprite;
			var newScale = sprite.scaleX > 0 ? -1 : 1;

			sprite.setScaleX( newScale ).update();
		}

		this.eventTracker.addEvent( "nowait", eventToAdd );

	};

	/**
	 * Attach module to namespace
	 */
	VN.prototype.modules.push(
		{
			"init": function init( novelId ) {

				// TODO: refactor

				this.screenCharacterId = document.getElementById( this.novelId + "-screen-character" );
				this.characterContainer = null;
				this.characters = [];

				var screenCharacter = this.screenCharacterId;

				// set character container size and hide it
				var newStyle = ";display:none;width:" + this.screenWidth +
					"px;height:" + this.screenHeight + "px;";

				screenCharacter.style.cssText += newStyle;

				// create character sprite container
				var spritely = this.spritely;
				var characterContainer = new spritely( screenCharacter );

				characterContainer.addChild( spritely.createCenteredContainer() );

				this.characterContainer = characterContainer;

			},
			"reset": function reset() {

				this.resetCharacters();

			}
		}
	);

	var getCharacterConstructor = function( novel ) {

		var Sprite = novel.sprite;

		/**
		 *	Object : Character
		 *  States:
		 *		1. sprite
		 *  Behaviors:
		 *		1. Move
		 *		2. Rotate
		 *		3. FadeIn/FadeOut
		 **/
		function Character( width, height, position, transformOrigin, rotate ) {

			if ( this instanceof Character ) {

				// Call the parent constructor
				Sprite.apply( this, arguments );

				// Add states

				this.init( width, height, position, transformOrigin, rotate );

				return this;

			} else {

				return new Character( width, height, position, transformOrigin, rotate );

			}

		}

		// Create a Character.prototype object that inherits from Sprite.prototype
		Character.prototype = Object.create( Sprite.prototype );

		// Set the "constructor" property to refer to Character
		Character.prototype.constructor = Character;

		getCharacterConstructor = function() {

			return Character;

		};

		return Character;

	};

} )( window.VisualNovel = window.VisualNovel || {} );<commit_msg>Update scene character module to attach to novel container<commit_after>( function( VN ) {

	VN.prototype.screenCharacterId = null;
	VN.prototype.characterContainer = null;
	VN.prototype.characters = [];

	VN.prototype.addCharacter = function addCharacter( character, delay, fadeIn ) {

		var self = this;

		function createCharacter() {

			// show
			self.screenCharacterId.style.display = "block";

			var characterWidth = character.width;
			var characterHeight = character.height;

			var transformX = characterWidth / 2;

			var posY = ( self.screenHeight - characterHeight ) +
					   ( self.screenHeight * character.pos.y );
			var posX = ( self.screenWidth * character.pos.x );

			var position = {
				x : Math.floor( posX ),
				y : Math.floor( posY ),
				z : 0
			};
			var transformOrigin = {
				x : transformX,
				y : 0,
				z : 0
			};

			var c = getCharacterConstructor( self );

			c = c( characterWidth, characterHeight, position, transformOrigin );

			c.setBackground( characterWidth, characterHeight, self.getCharacterImage( character ) );

			// To help us keep track of the character, use their name
			c.name = character.name;

			return c;
		}

		function callAddCharacter( c ) {

			self.characterContainer.addChild( c.sprite );
			self.characters.push( c );

		}

		function eventToAdd() {

			var c = createCharacter();

			if ( fadeIn ) {

				c.fadeIn( delay );

			}

			callAddCharacter( c );

		}

		this.eventTracker.addEvent( "nowait", eventToAdd, delay );

	};

	VN.prototype.getCharacter = function getCharacter( name ) {

		var characterObjectInfo = this.util.getObjectInList( this.characters, "name", name );

		return characterObjectInfo.obj;

	};

	VN.prototype.getCharacterImage = function getCharacterImage( character, type ) {

		// character image is string
		// character = { image : "character/happy.png" };

		// character image is object
		// type = default if not provided
		// character = { image :
		// { default : "character/happy.png", sleep : "character/sleep.png" } }

		var imgPath = this.imgPath;
		var charImage = character && character.image ? character.image : null;

		// TODO: add function to detect if charImage is an object and not an array...?
		if ( charImage && typeof charImage === "object" ) {

			if ( type ) {

				charImage = charImage[ type ];

			} else {

				charImage = charImage[ "default" ];

			}

			if ( typeof charImage === "object" ) {

				charImage = {
					src : imgPath + charImage.src,
					position : charImage.position
				};

			} else {

				charImage = imgPath + charImage;

			}

		} else if ( charImage ) {

			charImage = imgPath + charImage;

		}

		return charImage;

	};

	VN.prototype.changeCharacterImage = function changeCharacterImage( character, type ) {

		var self = this;

		function eventToAdd() {

			self.setCharacterImage( character, type );

		}

		this.eventTracker.addEvent( "nowait", eventToAdd );

	};

	VN.prototype.setCharacterImage = function setCharacterImage( character, type ) {

		var characterObject = this.getCharacter( character.name );
		var characterImage = this.getCharacterImage( character, type );

		if ( typeof characterImage === "object" ) {

				requestAnimationFrame( function() {

					characterObject.sprite.setCSS( "background-position", characterImage.position );
					characterObject.sprite.setCSS( "background-image",
						"url('" + characterImage.src + "')" );

				} );

		} else {

				requestAnimationFrame( function() {

					characterObject.sprite.setCSS( "background-image",
						"url('" + characterImage + "')" );

				} );

		}

	};

	VN.prototype.removeCharacter = function removeCharacter( character, delay, fadeOut ) {

		var self = this;

		// TODO: refactor character object
		function callRemoveCharacter() {

			var characterObjectInfo = self.util.getObjectInList( self.characters, "name", character.name );
			var indexInList = characterObjectInfo.id;

			self.characterContainer.removeChildAt( indexInList + 1 ); // 0 for container so +1
			self.characters.splice( indexInList, 1 );
		}

		function eventToAdd() {

			if ( fadeOut ) {
				var characterObject = self.getCharacter( character.name );
				characterObject.fadeOut( delay );
			}

			self.eventTracker.delayCallback( delay, callRemoveCharacter );
		}

		this.eventTracker.addEvent( "nowait", eventToAdd, delay );

	};

	VN.prototype.removeAllCharacter = function removeAllCharacter( delay ) {

		var self = this;

		function callRemoveAllCharacter() {
			self.resetCharacters();
		}

		function eventToAdd() {
			self.eventTracker.delayCallback( delay, callRemoveAllCharacter );
		}

		this.eventTracker.addEvent( "nowait", eventToAdd, delay );

	};

	VN.prototype.resetCharacters = function resetCharacters() {

		var characters = this.characterContainer ? this.characterContainer.children : [];
		var totalCharacters = characters.length;

		for( var i = totalCharacters - 1; i >= 1; i-- ) {

			this.characterContainer.removeChildAt( i );

		}

		this.characters = [];

	};

	VN.prototype.moveCharacter = function moveCharacter( character, x, y, delay ) {

		var self = this;

		function eventToAdd() {

			var characterObject = self.getCharacter( character.name );
			var sprite = characterObject.sprite;
			var newPos = {
				x : typeof x !== "undefined" ? x > 1 || x < -1 ? x : x * self.screenWidth : sprite.x,
				y : typeof y !== "undefined" ? y > 1 || y < -1 ? y : y * self.screenHeight : sprite.y
			};

			if ( delay ) {

				characterObject.move( newPos.x, newPos.y, 0, delay );

			} else {

				requestAnimationFrame( function() {

					sprite.x = newPos.x;
					sprite.y = newPos.y;
					sprite.update();

				} );

			}

		}

		this.eventTracker.addEvent( "nowait", eventToAdd );

	};

	VN.prototype.fadeCharacter = function fadeCharacter( character, type, speed, from, to ) {

		var self = this;

		function eventToAdd() {

			var characterObject = self.getCharacter( character.name );

			if ( type == "in" ) {

				characterObject.fadeIn( speed, from, to );

			} else if ( type == "out" ) {

				characterObject.fadeOut( speed, from, to );

			}
		}

		this.eventTracker.addEvent( "nowait", eventToAdd );

	};

	VN.prototype.flipCharacter = function flipCharacter( character ) {

		var self = this;

		function eventToAdd() {

			var characterObject = self.getCharacter( character.name );
			var sprite = characterObject.sprite;
			var newScale = sprite.scaleX > 0 ? -1 : 1;

			sprite.setScaleX( newScale ).update();
		}

		this.eventTracker.addEvent( "nowait", eventToAdd );

	};

	/**
	 * Attach module to namespace
	 */
	VN.prototype.modules.push(
		{
			"init": function init( novelId ) {

				// TODO: refactor

				var template = this.parser.parseTemplate(
						"

",
						{
							"novelId": novelId,
							"width": this.screenWidth,
							"height": this.screenHeight
						}
					);

				var screenCharacterId = this.screenCharacterId = this.attachToNovelContainer( template );

				this.characterContainer = null;
				this.characters = [];

				// set character container size and hide it
				var newStyle = ";display:none;width:" + this.screenWidth +
					"px;height:" + this.screenHeight + "px;";

				screenCharacterId.style.cssText += newStyle;

				// create character sprite container
				var spritely = this.spritely;
				var characterContainer = new spritely( screenCharacterId );

				characterContainer.addChild( spritely.createCenteredContainer() );

				this.characterContainer = characterContainer;

			},
			"reset": function reset() {

				this.resetCharacters();

			}
		}
	);

	var getCharacterConstructor = function( novel ) {

		var Sprite = novel.sprite;

		/**
		 *	Object : Character
		 *  States:
		 *		1. sprite
		 *  Behaviors:
		 *		1. Move
		 *		2. Rotate
		 *		3. FadeIn/FadeOut
		 **/
		function Character( width, height, position, transformOrigin, rotate ) {

			if ( this instanceof Character ) {

				// Call the parent constructor
				Sprite.apply( this, arguments );

				// Add states

				this.init( width, height, position, transformOrigin, rotate );

				return this;

			} else {

				return new Character( width, height, position, transformOrigin, rotate );

			}

		}

		// Create a Character.prototype object that inherits from Sprite.prototype
		Character.prototype = Object.create( Sprite.prototype );

		// Set the "constructor" property to refer to Character
		Character.prototype.constructor = Character;

		getCharacterConstructor = function() {

			return Character;

		};

		return Character;

	};

} )( window.VisualNovel = window.VisualNovel || {} );<|endoftext|>


<commit_before>/**
 * ComboBoxInputWidgets combine a {@link OO.ui.TextInputWidget text input} (where a value
 * can be entered manually) and a {@link OO.ui.MenuSelectWidget menu of options} (from which
 * a value can be chosen instead). Users can choose options from the combo box in one of two ways:
 *
 * - by typing a value in the text input field. If the value exactly matches the value of a menu
 *   option, that option will appear to be selected.
 * - by choosing a value from the menu. The value of the chosen option will then appear in the text
 *   input field.
 *
 * After the user chooses an option, its `data` will be used as a new value for the widget.
 * A `label` also can be specified for each option: if given, it will be shown instead of the
 * `data` in the dropdown menu.
 *
 * This widget can be used inside an HTML form, such as a OO.ui.FormLayout.
 *
 * For more information about menus and options, please see the
 * [OOUI documentation on MediaWiki][1].
 *
 *     @example
 *     // A ComboBoxInputWidget.
 *     var comboBox = new OO.ui.ComboBoxInputWidget( {
 *         value: 'Option 1',
 *         options: [
 *             { data: 'Option 1' },
 *             { data: 'Option 2' },
 *             { data: 'Option 3' }
 *         ]
 *     } );
 *     $( document.body ).append( comboBox.$element );
 *
 *     @example
 *     // Example: A ComboBoxInputWidget with additional option labels.
 *     var comboBox = new OO.ui.ComboBoxInputWidget( {
 *         value: 'Option 1',
 *         options: [
 *             {
 *                 data: 'Option 1',
 *                 label: 'Option One'
 *             },
 *             {
 *                 data: 'Option 2',
 *                 label: 'Option Two'
 *             },
 *             {
 *                 data: 'Option 3',
 *                 label: 'Option Three'
 *             }
 *         ]
 *     } );
 *     $( document.body ).append( comboBox.$element );
 *
 * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Selects_and_Options#Menu_selects_and_options
 *
 * @class
 * @extends OO.ui.TextInputWidget
 *
 * @constructor
 * @param {Object} [config] Configuration options
 * @cfg {Object[]} [options=[]] Array of menu options in the format `{ data: …, label: … }`
 * @cfg {Object} [menu] Configuration options to pass to the {@link OO.ui.MenuSelectWidget menu
 *  select widget}.
 * @cfg {jQuery} [$overlay] Render the menu into a separate layer. This configuration is useful
 *  in cases where the expanded menu is larger than its containing `<div>`. The specified overlay
 *  layer is usually on top of the containing `<div>` and has a larger area. By default, the menu
 *  uses relative positioning.
 *  See <https://www.mediawiki.org/wiki/OOUI/Concepts#Overlays>.
 */
OO.ui.ComboBoxInputWidget = function OoUiComboBoxInputWidget( config ) {
	// Configuration initialization
	config = $.extend( {
		autocomplete: false
	}, config );

	// ComboBoxInputWidget shouldn't support `multiline`
	config.multiline = false;

	// See InputWidget#reusePreInfuseDOM about `config.$input`
	if ( config.$input ) {
		config.$input.removeAttr( 'list' );
	}

	// Parent constructor
	OO.ui.ComboBoxInputWidget.super.call( this, config );

	// Properties
	this.$overlay = ( config.$overlay === true ?
		OO.ui.getDefaultOverlay() : config.$overlay ) || this.$element;
	this.dropdownButton = new OO.ui.ButtonWidget( {
		classes: [ 'oo-ui-comboBoxInputWidget-dropdownButton' ],
		label: OO.ui.msg( 'ooui-combobox-button-label' ),
		indicator: 'down',
		invisibleLabel: true,
		disabled: this.disabled
	} );
	this.menu = new OO.ui.MenuSelectWidget( $.extend(
		{
			widget: this,
			input: this,
			$floatableContainer: this.$element,
			disabled: this.isDisabled()
		},
		config.menu
	) );

	// Events
	this.connect( this, {
		change: 'onInputChange',
		enter: 'onInputEnter'
	} );
	this.dropdownButton.connect( this, {
		click: 'onDropdownButtonClick'
	} );
	this.menu.connect( this, {
		choose: 'onMenuChoose',
		add: 'onMenuItemsChange',
		remove: 'onMenuItemsChange',
		toggle: 'onMenuToggle'
	} );

	// Initialization
	this.$input.attr( {
		role: 'combobox',
		'aria-owns': this.menu.getElementId(),
		'aria-autocomplete': 'list'
	} );
	this.dropdownButton.$button.attr( {
		'aria-controls': this.menu.getElementId()
	} );
	// Do not override options set via config.menu.items
	if ( config.options !== undefined ) {
		this.setOptions( config.options );
	}
	this.$field = $( '<div>' )
		.addClass( 'oo-ui-comboBoxInputWidget-field' )
		.append( this.$input, this.dropdownButton.$element );
	this.$element
		.addClass( 'oo-ui-comboBoxInputWidget' )
		.append( this.$field );
	this.$overlay.append( this.menu.$element );
	this.onMenuItemsChange();
};

/* Setup */

OO.inheritClass( OO.ui.ComboBoxInputWidget, OO.ui.TextInputWidget );

/* Methods */

/**
 * Get the combobox's menu.
 *
 * @return {OO.ui.MenuSelectWidget} Menu widget
 */
OO.ui.ComboBoxInputWidget.prototype.getMenu = function () {
	return this.menu;
};

/**
 * Get the combobox's text input widget.
 *
 * @return {OO.ui.TextInputWidget} Text input widget
 */
OO.ui.ComboBoxInputWidget.prototype.getInput = function () {
	return this;
};

/**
 * Handle input change events.
 *
 * @private
 * @param {string} value New value
 */
OO.ui.ComboBoxInputWidget.prototype.onInputChange = function ( value ) {
	var match = this.menu.findItemFromData( value );

	this.menu.selectItem( match );
	if ( this.menu.findHighlightedItem() ) {
		this.menu.highlightItem( match );
	}

	if ( !this.isDisabled() ) {
		this.menu.toggle( true );
	}
};

/**
 * Handle input enter events.
 *
 * @private
 */
OO.ui.ComboBoxInputWidget.prototype.onInputEnter = function () {
	if ( !this.isDisabled() ) {
		this.menu.toggle( false );
	}
};

/**
 * Handle button click events.
 *
 * @private
 */
OO.ui.ComboBoxInputWidget.prototype.onDropdownButtonClick = function () {
	this.menu.toggle();
	this.focus();
};

/**
 * Handle menu choose events.
 *
 * @private
 * @param {OO.ui.OptionWidget} item Chosen item
 */
OO.ui.ComboBoxInputWidget.prototype.onMenuChoose = function ( item ) {
	this.setValue( item.getData() );
};

/**
 * Handle menu item change events.
 *
 * @private
 */
OO.ui.ComboBoxInputWidget.prototype.onMenuItemsChange = function () {
	var match = this.menu.findItemFromData( this.getValue() );
	this.menu.selectItem( match );
	if ( this.menu.findHighlightedItem() ) {
		this.menu.highlightItem( match );
	}
	this.$element.toggleClass( 'oo-ui-comboBoxInputWidget-empty', this.menu.isEmpty() );
};

/**
 * Handle menu toggle events.
 *
 * @private
 * @param {boolean} isVisible Open state of the menu
 */
OO.ui.ComboBoxInputWidget.prototype.onMenuToggle = function ( isVisible ) {
	this.$element.toggleClass( 'oo-ui-comboBoxInputWidget-open', isVisible );
};

/**
 * Update the disabled state of the controls
 *
 * @chainable
 * @protected
 * @return {OO.ui.ComboBoxInputWidget} The widget, for chaining
 */
OO.ui.ComboBoxInputWidget.prototype.updateControlsDisabled = function () {
	var disabled = this.isDisabled() || this.isReadOnly();
	if ( this.dropdownButton ) {
		this.dropdownButton.setDisabled( disabled );
	}
	if ( this.menu ) {
		this.menu.setDisabled( disabled );
	}
	return this;
};

/**
 * @inheritdoc
 */
OO.ui.ComboBoxInputWidget.prototype.setDisabled = function () {
	// Parent method
	OO.ui.ComboBoxInputWidget.super.prototype.setDisabled.apply( this, arguments );
	this.updateControlsDisabled();
	return this;
};

/**
 * @inheritdoc
 */
OO.ui.ComboBoxInputWidget.prototype.setReadOnly = function () {
	// Parent method
	OO.ui.ComboBoxInputWidget.super.prototype.setReadOnly.apply( this, arguments );
	this.updateControlsDisabled();
	return this;
};

/**
 * Set the options available for this input.
 *
 * @param {Object[]} options Array of menu options in the format `{ data: …, label: … }`
 * @chainable
 * @return {OO.ui.Widget} The widget, for chaining
 */
OO.ui.ComboBoxInputWidget.prototype.setOptions = function ( options ) {
	this.getMenu()
		.clearItems()
		.addItems( options.map( function ( opt ) {
			return new OO.ui.MenuOptionWidget( {
				data: opt.data,
				label: opt.label !== undefined ? opt.label : opt.data
			} );
		} ) );

	return this;
};
<commit_msg>ComboBoxInputWidget: Only show menu on user triggered events<commit_after>/**
 * ComboBoxInputWidgets combine a {@link OO.ui.TextInputWidget text input} (where a value
 * can be entered manually) and a {@link OO.ui.MenuSelectWidget menu of options} (from which
 * a value can be chosen instead). Users can choose options from the combo box in one of two ways:
 *
 * - by typing a value in the text input field. If the value exactly matches the value of a menu
 *   option, that option will appear to be selected.
 * - by choosing a value from the menu. The value of the chosen option will then appear in the text
 *   input field.
 *
 * After the user chooses an option, its `data` will be used as a new value for the widget.
 * A `label` also can be specified for each option: if given, it will be shown instead of the
 * `data` in the dropdown menu.
 *
 * This widget can be used inside an HTML form, such as a OO.ui.FormLayout.
 *
 * For more information about menus and options, please see the
 * [OOUI documentation on MediaWiki][1].
 *
 *     @example
 *     // A ComboBoxInputWidget.
 *     var comboBox = new OO.ui.ComboBoxInputWidget( {
 *         value: 'Option 1',
 *         options: [
 *             { data: 'Option 1' },
 *             { data: 'Option 2' },
 *             { data: 'Option 3' }
 *         ]
 *     } );
 *     $( document.body ).append( comboBox.$element );
 *
 *     @example
 *     // Example: A ComboBoxInputWidget with additional option labels.
 *     var comboBox = new OO.ui.ComboBoxInputWidget( {
 *         value: 'Option 1',
 *         options: [
 *             {
 *                 data: 'Option 1',
 *                 label: 'Option One'
 *             },
 *             {
 *                 data: 'Option 2',
 *                 label: 'Option Two'
 *             },
 *             {
 *                 data: 'Option 3',
 *                 label: 'Option Three'
 *             }
 *         ]
 *     } );
 *     $( document.body ).append( comboBox.$element );
 *
 * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Selects_and_Options#Menu_selects_and_options
 *
 * @class
 * @extends OO.ui.TextInputWidget
 *
 * @constructor
 * @param {Object} [config] Configuration options
 * @cfg {Object[]} [options=[]] Array of menu options in the format `{ data: …, label: … }`
 * @cfg {Object} [menu] Configuration options to pass to the {@link OO.ui.MenuSelectWidget menu
 *  select widget}.
 * @cfg {jQuery} [$overlay] Render the menu into a separate layer. This configuration is useful
 *  in cases where the expanded menu is larger than its containing `<div>`. The specified overlay
 *  layer is usually on top of the containing `<div>` and has a larger area. By default, the menu
 *  uses relative positioning.
 *  See <https://www.mediawiki.org/wiki/OOUI/Concepts#Overlays>.
 */
OO.ui.ComboBoxInputWidget = function OoUiComboBoxInputWidget( config ) {
	// Configuration initialization
	config = $.extend( {
		autocomplete: false
	}, config );

	// ComboBoxInputWidget shouldn't support `multiline`
	config.multiline = false;

	// See InputWidget#reusePreInfuseDOM about `config.$input`
	if ( config.$input ) {
		config.$input.removeAttr( 'list' );
	}

	// Parent constructor
	OO.ui.ComboBoxInputWidget.super.call( this, config );

	// Properties
	this.$overlay = ( config.$overlay === true ?
		OO.ui.getDefaultOverlay() : config.$overlay ) || this.$element;
	this.dropdownButton = new OO.ui.ButtonWidget( {
		classes: [ 'oo-ui-comboBoxInputWidget-dropdownButton' ],
		label: OO.ui.msg( 'ooui-combobox-button-label' ),
		indicator: 'down',
		invisibleLabel: true,
		disabled: this.disabled
	} );
	this.menu = new OO.ui.MenuSelectWidget( $.extend(
		{
			widget: this,
			input: this,
			$floatableContainer: this.$element,
			disabled: this.isDisabled()
		},
		config.menu
	) );

	// Events
	this.connect( this, {
		change: 'onInputChange',
		enter: 'onInputEnter'
	} );
	this.dropdownButton.connect( this, {
		click: 'onDropdownButtonClick'
	} );
	this.menu.connect( this, {
		choose: 'onMenuChoose',
		add: 'onMenuItemsChange',
		remove: 'onMenuItemsChange',
		toggle: 'onMenuToggle'
	} );

	// Initialization
	this.$input.attr( {
		role: 'combobox',
		'aria-owns': this.menu.getElementId(),
		'aria-autocomplete': 'list'
	} );
	this.dropdownButton.$button.attr( {
		'aria-controls': this.menu.getElementId()
	} );
	// Do not override options set via config.menu.items
	if ( config.options !== undefined ) {
		this.setOptions( config.options );
	}
	this.$field = $( '<div>' )
		.addClass( 'oo-ui-comboBoxInputWidget-field' )
		.append( this.$input, this.dropdownButton.$element );
	this.$element
		.addClass( 'oo-ui-comboBoxInputWidget' )
		.append( this.$field );
	this.$overlay.append( this.menu.$element );
	this.onMenuItemsChange();
};

/* Setup */

OO.inheritClass( OO.ui.ComboBoxInputWidget, OO.ui.TextInputWidget );

/* Methods */

/**
 * Get the combobox's menu.
 *
 * @return {OO.ui.MenuSelectWidget} Menu widget
 */
OO.ui.ComboBoxInputWidget.prototype.getMenu = function () {
	return this.menu;
};

/**
 * Get the combobox's text input widget.
 *
 * @return {OO.ui.TextInputWidget} Text input widget
 */
OO.ui.ComboBoxInputWidget.prototype.getInput = function () {
	return this;
};

/**
 * @inheritdoc
 */
OO.ui.ComboBoxInputWidget.prototype.onEdit = function () {
	// Parent method
	OO.ui.ComboBoxInputWidget.super.prototype.onEdit.apply( this, arguments );

	if ( !this.menu.isVisible() && !this.isDisabled() && this.isVisible() ) {
		this.menu.toggle( true );
	}
};

/**
 * Handle input change events.
 *
 * @private
 * @param {string} value New value
 */
OO.ui.ComboBoxInputWidget.prototype.onInputChange = function ( value ) {
	var match = this.menu.findItemFromData( value );

	this.menu.selectItem( match );
	if ( this.menu.findHighlightedItem() ) {
		this.menu.highlightItem( match );
	}
};

/**
 * Handle input enter events.
 *
 * @private
 */
OO.ui.ComboBoxInputWidget.prototype.onInputEnter = function () {
	if ( !this.isDisabled() ) {
		this.menu.toggle( false );
	}
};

/**
 * Handle button click events.
 *
 * @private
 */
OO.ui.ComboBoxInputWidget.prototype.onDropdownButtonClick = function () {
	this.menu.toggle();
	this.focus();
};

/**
 * Handle menu choose events.
 *
 * @private
 * @param {OO.ui.OptionWidget} item Chosen item
 */
OO.ui.ComboBoxInputWidget.prototype.onMenuChoose = function ( item ) {
	this.setValue( item.getData() );
};

/**
 * Handle menu item change events.
 *
 * @private
 */
OO.ui.ComboBoxInputWidget.prototype.onMenuItemsChange = function () {
	var match = this.menu.findItemFromData( this.getValue() );
	this.menu.selectItem( match );
	if ( this.menu.findHighlightedItem() ) {
		this.menu.highlightItem( match );
	}
	this.$element.toggleClass( 'oo-ui-comboBoxInputWidget-empty', this.menu.isEmpty() );
};

/**
 * Handle menu toggle events.
 *
 * @private
 * @param {boolean} isVisible Open state of the menu
 */
OO.ui.ComboBoxInputWidget.prototype.onMenuToggle = function ( isVisible ) {
	this.$element.toggleClass( 'oo-ui-comboBoxInputWidget-open', isVisible );
};

/**
 * Update the disabled state of the controls
 *
 * @chainable
 * @protected
 * @return {OO.ui.ComboBoxInputWidget} The widget, for chaining
 */
OO.ui.ComboBoxInputWidget.prototype.updateControlsDisabled = function () {
	var disabled = this.isDisabled() || this.isReadOnly();
	if ( this.dropdownButton ) {
		this.dropdownButton.setDisabled( disabled );
	}
	if ( this.menu ) {
		this.menu.setDisabled( disabled );
	}
	return this;
};

/**
 * @inheritdoc
 */
OO.ui.ComboBoxInputWidget.prototype.setDisabled = function () {
	// Parent method
	OO.ui.ComboBoxInputWidget.super.prototype.setDisabled.apply( this, arguments );
	this.updateControlsDisabled();
	return this;
};

/**
 * @inheritdoc
 */
OO.ui.ComboBoxInputWidget.prototype.setReadOnly = function () {
	// Parent method
	OO.ui.ComboBoxInputWidget.super.prototype.setReadOnly.apply( this, arguments );
	this.updateControlsDisabled();
	return this;
};

/**
 * Set the options available for this input.
 *
 * @param {Object[]} options Array of menu options in the format `{ data: …, label: … }`
 * @chainable
 * @return {OO.ui.Widget} The widget, for chaining
 */
OO.ui.ComboBoxInputWidget.prototype.setOptions = function ( options ) {
	this.getMenu()
		.clearItems()
		.addItems( options.map( function ( opt ) {
			return new OO.ui.MenuOptionWidget( {
				data: opt.data,
				label: opt.label !== undefined ? opt.label : opt.data
			} );
		} ) );

	return this;
};
<|endoftext|>


<commit_before>/**
 * Wait until the test condition is true or a timeout occurs. Useful for waiting
 * on a server response or for a ui change (fadeIn, etc.) to occur.
 *
 * @param testFx javascript condition that evaluates to a boolean,
 * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
 * as a callback function.
 * @param onReady what to do when testFx condition is fulfilled,
 * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
 * as a callback function.
 * @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
 */
function waitFor(testFx, onReady, timeOutMillis) {
    var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3001, //< Default Max Timout is 3s
        start = new Date().getTime(),
        condition = false,
        interval = setInterval(function() {
            if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
                // If not time-out yet and condition not yet fulfilled
                condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
            } else {
                if(!condition) {
                    // If condition still not fulfilled (timeout but condition is 'false')
                    console.log("'waitFor()' timeout");
                    phantom.exit(1);
                } else {
                    // Condition fulfilled (timeout and/or condition is 'true')
                    console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
                    typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
                    clearInterval(interval); //< Stop this interval
                }
            }
        }, 100); //< repeat check every 250ms
};

if (phantom.args.length === 0 || phantom.args.length > 2) {
    console.log('Usage: run-qunit.js URL');
    phantom.exit();
}

var page = new WebPage();

// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
page.onConsoleMessage = function(msg) {
    console.log(msg);
};

page.open(phantom.args[0], function(status){
    if (status !== "success") {
        console.log("Unable to access network");
        phantom.exit();
    } else {
        waitFor(function(){
            return page.evaluate(function(){
                var el = document.getElementById('qunit-testresult');
                if (el && el.innerText.match('completed')) {
                    return true;
                }
                return false;
            });
        }, function(){
            var failedNum = page.evaluate(function(){
                var el = document.getElementById('qunit-testresult');
                console.log(el.innerText);
                try {
                    return el.getElementsByClassName('failed')[0].innerHTML;
                } catch (e) { }
                return 10000;
            });
            phantom.exit((parseInt(failedNum, 10) > 0) ? 1 : 0);
        });
    }
});
<commit_msg>Old QUnit file removed.<commit_after><|endoftext|>


<commit_before>var referee = require("referee");
var bt = require("buster-test");

var assertions = 0;
var count = function () { assertions += 1; };
referee.on("pass", count);
referee.on("failure", count);

bt.testRunner.assertionCount = function () {
    return assertions;
};

bt.testRunner.onCreate(function (runner) {
    runner.on("suite:end", function (results) {
        if (!results.ok) {
            setTimeout(function () {
                process.exit(1);
            }, 50);
        }
    });
});

bt.testContext.on("create", bt.autoRun());

require("./test/ansi-colorizer-test.js");
<commit_msg>Fix test run script<commit_after>var referee = require("referee");
var bt = require("buster-test");

bt.testRunner.onCreate(function (runner) {
    referee.on("pass", runner.assertionPass.bind(runner));

    runner.on("suite:end", function (results) {
        if (!results.ok) {
            setTimeout(function () {
                process.exit(1);
            }, 50);
        }
    });
});

bt.testContext.on("create", bt.autoRun());

require("./test/ansi-colorizer-test.js");
<|endoftext|>