<commit_before>"use strict";

let errors = require('../errors.js');
let Type = require('./type.js');
let Value = require('./value.js');
let makeType = require('./factory.js');
let RecordType = require('./record.js');

// An instance of an EitherVariant.
// 'eithertype' is the EitherType and doesn't change,
// 'varianttype' is the current EitherVariant.
// 'type' is eithertype unless the Variant is known statically, then it's varianttype.
// If the variant has record fields, those will be in an attribute named
// 'fields'; otherwise, it'll be set to undefined.
class EitherValue extends Value {
  constructor(type, eithertype, varianttype) {
    super(type);
    this.eithertype = eithertype;
    this.varianttype = varianttype;
    if (this.varianttype.recordtype === null) {
      this.fields = undefined;
    } else {
      this.fields = this.varianttype.recordtype.makeDefaultValue();
    }
  }

  // call this from JS as follows:
  // let x = thing.match({
  //    Variant1: (t) => 1,
  //    Variant2: (t) => { return t.two + 2; },
  // });
  match(variants) {
    let fn = variants[this.varianttype.name];
    if (fn === undefined) {
      return undefined;
    }
    if (typeof fn === "function") {
      return fn(this.fields);
    } else { // maybe it's an expression
      return fn;
    }
  }

  assign(newValue) {
    let ok = false;
    if (this.type == this.eithertype) {
      ok = (newValue instanceof EitherValue &&
        this.eithertype == newValue.eithertype);
    } else { // this.type == this.varianttype
      ok = (newValue instanceof EitherValue &&
        this.varianttype == newValue.varianttype);
    }
    if (ok) {
      this.varianttype = newValue.varianttype;
      this.fields = newValue.fields;
    } else {
      throw new errors.Internal(`Cannot assign value of ${newValue} to ` +
        `either-type ${this.type.getName()}`);
    }
  }

  lookup(name) {
    return this.fields.lookup(name);
  }

  set(name, value) {
    return this.fields.set(name, value);
  }

  equals(other) {
    if (this.varianttype != other.varianttype) {
      return false;
    }
    if (this.fields !== undefined) {
      return this.fields.equals(other.fields);
    }
    return true;
  }

  innerToString() {
    if (this.fields !== undefined) {
      return this.fields.toString();
    } else {
      return this.varianttype.name;
    }
  }

  toString() {
    if (this.fields !== undefined) {
      return `${this.varianttype.name} { ${this.fields.innerToString()} }`;
    } else {
      return `${this.varianttype.name}`;
    }
  }

  toJSON() {
    if (this.fields !== undefined) {
      let o = {};
      o.tag = this.varianttype.name;
      o.fields = this.fields.toJSON();
      return o;
    } else {
      return this.varianttype.name;
    }
  }
}

// In:
//   type T: either { A, B }
// this represents an A or a B, and its parenttype is T.
// Sometimes we know statically that we have an A or a B.
class EitherVariant extends Type {
  constructor(decl, env, name, parenttype) {
    super(decl, env, name);
    this.parenttype = parenttype;
    if (this.decl.kind == 'enumvariant') {
      this.recordtype = null;
      let constant = new EitherValue(this, this.parenttype, this);
      constant.isConstant = true;
      this.env.vars.set(this.name, constant, this.decl.id.source);
    } else {
      this.recordtype = makeType.make(decl.type, this.env, this.name);
      this.env.assignType(this.name, this);
    }
  }

  makeDefaultValue() {
    return new EitherValue(this, this.parenttype, this);
  }

  fieldType(name) {
    return this.recordtype.fieldType(name);
  }

  toString() {
    return `${this.name} (EitherVariant)`;
  }
}

// The type T in:
//   type T: either { A, B }
// An EitherType is made up of a set of EitherVariant types (A and B in this
// example).
class EitherType extends Type {
  constructor(decl, env, name) {
    super(decl, env, name);
    this.variants = this.decl.fields.map(
      (field) => new EitherVariant(field, this.env, field.id.value, this)
    );
  }

  getVariant(tag) {
    let variant = undefined;
    this.variants.forEach((v) => {
      if (v.name == tag) {
        variant = v;
      }
    });
    return variant;
  }

  makeDefaultValue() {
    return new EitherValue(this, this, this.variants[0]);
  }

  toString() {
    let name = this.getName();
    if (name !== undefined) {
      return name;
    }
    return `anonymous either (${this.decl.source})`;
  }
}

module.exports = {
  Variant: EitherVariant,
  Type: EitherType,
};
<commit_msg>Fix aliasing bug in either assignment<commit_after>"use strict";

let errors = require('../errors.js');
let Type = require('./type.js');
let Value = require('./value.js');
let makeType = require('./factory.js');
let RecordType = require('./record.js');

// An instance of an EitherVariant.
// 'eithertype' is the EitherType and doesn't change,
// 'varianttype' is the current EitherVariant.
// 'type' is eithertype unless the Variant is known statically, then it's varianttype.
// If the variant has record fields, those will be in an attribute named
// 'fields'; otherwise, it'll be set to undefined.
class EitherValue extends Value {
  constructor(type, eithertype, varianttype) {
    super(type);
    this.eithertype = eithertype;
    this.varianttype = varianttype;
    if (this.varianttype.recordtype === null) {
      this.fields = undefined;
    } else {
      this.fields = this.varianttype.recordtype.makeDefaultValue();
    }
  }

  // call this from JS as follows:
  // let x = thing.match({
  //    Variant1: (t) => 1,
  //    Variant2: (t) => { return t.two + 2; },
  // });
  match(variants) {
    let fn = variants[this.varianttype.name];
    if (fn === undefined) {
      return undefined;
    }
    if (typeof fn === "function") {
      return fn(this.fields);
    } else { // maybe it's an expression
      return fn;
    }
  }

  assign(newValue) {
    let ok = false;
    if (this.type == this.eithertype) {
      ok = (newValue instanceof EitherValue &&
        this.eithertype == newValue.eithertype);
    } else { // this.type == this.varianttype
      ok = (newValue instanceof EitherValue &&
        this.varianttype == newValue.varianttype);
    }
    if (ok) {
      this.varianttype = newValue.varianttype;
      if (this.varianttype.recordtype === null) {
        this.fields = undefined;
      } else {
        this.fields = this.varianttype.recordtype.makeDefaultValue();
        this.fields.assign(newValue.fields);
      }
    } else {
      throw new errors.Internal(`Cannot assign value of ${newValue} to ` +
        `either-type ${this.type.getName()}`);
    }
  }

  lookup(name) {
    return this.fields.lookup(name);
  }

  set(name, value) {
    return this.fields.set(name, value);
  }

  equals(other) {
    if (this.varianttype != other.varianttype) {
      return false;
    }
    if (this.fields !== undefined) {
      return this.fields.equals(other.fields);
    }
    return true;
  }

  innerToString() {
    if (this.fields !== undefined) {
      return this.fields.toString();
    } else {
      return this.varianttype.name;
    }
  }

  toString() {
    if (this.fields !== undefined) {
      return `${this.varianttype.name} { ${this.fields.innerToString()} }`;
    } else {
      return `${this.varianttype.name}`;
    }
  }

  toJSON() {
    if (this.fields !== undefined) {
      let o = {};
      o.tag = this.varianttype.name;
      o.fields = this.fields.toJSON();
      return o;
    } else {
      return this.varianttype.name;
    }
  }
}

// In:
//   type T: either { A, B }
// this represents an A or a B, and its parenttype is T.
// Sometimes we know statically that we have an A or a B.
class EitherVariant extends Type {
  constructor(decl, env, name, parenttype) {
    super(decl, env, name);
    this.parenttype = parenttype;
    if (this.decl.kind == 'enumvariant') {
      this.recordtype = null;
      let constant = new EitherValue(this, this.parenttype, this);
      constant.isConstant = true;
      this.env.vars.set(this.name, constant, this.decl.id.source);
    } else {
      this.recordtype = makeType.make(decl.type, this.env, this.name);
      this.env.assignType(this.name, this);
    }
  }

  makeDefaultValue() {
    return new EitherValue(this, this.parenttype, this);
  }

  fieldType(name) {
    return this.recordtype.fieldType(name);
  }

  toString() {
    return `${this.name} (EitherVariant)`;
  }
}

// The type T in:
//   type T: either { A, B }
// An EitherType is made up of a set of EitherVariant types (A and B in this
// example).
class EitherType extends Type {
  constructor(decl, env, name) {
    super(decl, env, name);
    this.variants = this.decl.fields.map(
      (field) => new EitherVariant(field, this.env, field.id.value, this)
    );
  }

  getVariant(tag) {
    let variant = undefined;
    this.variants.forEach((v) => {
      if (v.name == tag) {
        variant = v;
      }
    });
    return variant;
  }

  makeDefaultValue() {
    return new EitherValue(this, this, this.variants[0]);
  }

  toString() {
    let name = this.getName();
    if (name !== undefined) {
      return name;
    }
    return `anonymous either (${this.decl.source})`;
  }
}

module.exports = {
  Variant: EitherVariant,
  Type: EitherType,
};
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import ReactTooltip from 'react-tooltip';
import { connect } from 'react-redux';

import Icon from 'common/Icon';
import isLatestPatch from 'game/isLatestPatch';
import DiscordButton from 'interface/common/thirdpartybuttons/Discord';
import GitHubButton from 'interface/common/thirdpartybuttons/GitHub';
import makeAnalyzerUrl from 'interface/common/makeAnalyzerUrl';
import { ignoreSpecNotSupportedWarning } from 'interface/actions/specNotSupported';
import { getSpecsIgnoredNotSupportedWarning } from 'interface/selectors/skipSpecNotSupported';

import Background from './images/weirdnelf.png';

class SupportChecker extends React.PureComponent {
  static propTypes = {
    children: PropTypes.node.isRequired,
    config: PropTypes.shape({
      patchCompatibility: PropTypes.string.isRequired,
      spec: PropTypes.shape({
        id: PropTypes.number.isRequired,
      }).isRequired,
    }).isRequired,
    report: PropTypes.object.isRequired,
    fight: PropTypes.shape({
      id: PropTypes.number.isRequired,
    }).isRequired,
    player: PropTypes.shape({
      name: PropTypes.string.isRequired,
    }).isRequired,
    ignoreSpecNotSupportedWarning: PropTypes.func.isRequired,
    ignored: PropTypes.array.isRequired,
  };

  constructor() {
    super();
    this.handleClickContinue = this.handleClickContinue.bind(this);
  }
  componentDidMount() {
    ReactTooltip.rebuild();
  }
  componentDidUpdate() {
    ReactTooltip.hide();
  }

  handleClickContinue() {
    this.props.ignoreSpecNotSupportedWarning(this.props.config.spec.id);
  }

  get continue() {
    return this.props.ignored.includes(this.props.config.spec.id);
  }

  render() {
    const { children, config, report, fight, player } = this.props;

    const spec = config.spec;

    if (!this.continue && !isLatestPatch(config.patchCompatibility)) {
      return (

              <Link to={makeAnalyzerUrl(report, fight.id)} data-tip="Back to player selection">

              </Link>

            {player.name} - {spec.specName} {spec.className}

Sorry, this spec is currently not supported

                  This spec hasn't been updated for the latest patch so we're afraid it might be outdated and misleading. We recommend reading the  Wowhead and Icy Veins guides to gain more knowledge about your spec and use this to analyze yourself. You can try asking for help in a class Discord, but they're likely too busy memeing to do thorough analysis for you.

                  We have no ETA for support for {spec.specName} {spec.className}. We need volunteer contributors to maintain specs, and seeing as {spec.specName} {spec.className} is out of date, it's likely nobody is currently maintaining it. If you are interested or know someone who might be interested helping people help themselves, check out GitHub or Discord for more information.

                    <GitHubButton />{' '}
                    <DiscordButton />

                  <Link
                    to={makeAnalyzerUrl(report, fight.id, player.id)}
                    onClick={this.handleClickContinue}
                    style={{ fontSize: '1.1em' }}
                    data-tip="Khadgar approves your bravery"
                  >
                    <Icon icon="quest_khadgar" /> Continue anyway
                  </Link>

      );
    }

    return children;
  }
}

const mapStateToProps = state => ({
  ignored: getSpecsIgnoredNotSupportedWarning(state),
});
export default connect(mapStateToProps, {
  ignoreSpecNotSupportedWarning,
})(SupportChecker);
<commit_msg>And a comment<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import ReactTooltip from 'react-tooltip';
import { connect } from 'react-redux';

import Icon from 'common/Icon';
import isLatestPatch from 'game/isLatestPatch';
import DiscordButton from 'interface/common/thirdpartybuttons/Discord';
import GitHubButton from 'interface/common/thirdpartybuttons/GitHub';
import makeAnalyzerUrl from 'interface/common/makeAnalyzerUrl';
import { ignoreSpecNotSupportedWarning } from 'interface/actions/specNotSupported';
import { getSpecsIgnoredNotSupportedWarning } from 'interface/selectors/skipSpecNotSupported';

import Background from './images/weirdnelf.png';

class SupportChecker extends React.PureComponent {
  static propTypes = {
    children: PropTypes.node.isRequired,
    config: PropTypes.shape({
      patchCompatibility: PropTypes.string.isRequired,
      spec: PropTypes.shape({
        id: PropTypes.number.isRequired,
      }).isRequired,
    }).isRequired,
    report: PropTypes.object.isRequired,
    fight: PropTypes.shape({
      id: PropTypes.number.isRequired,
    }).isRequired,
    player: PropTypes.shape({
      name: PropTypes.string.isRequired,
    }).isRequired,
    ignoreSpecNotSupportedWarning: PropTypes.func.isRequired,
    ignored: PropTypes.array.isRequired,
  };

  constructor() {
    super();
    this.handleClickContinue = this.handleClickContinue.bind(this);
  }
  componentDidMount() {
    ReactTooltip.rebuild();
  }
  componentDidUpdate() {
    ReactTooltip.hide();
  }

  handleClickContinue() {
    // I chose on purpose not to store this in a cookie since I don't want this to be forgotten. It should not be a big deal if this happens every time the page is loaded, so long as it isn't shown every fight.
    this.props.ignoreSpecNotSupportedWarning(this.props.config.spec.id);
  }

  get continue() {
    return this.props.ignored.includes(this.props.config.spec.id);
  }

  render() {
    const { children, config, report, fight, player } = this.props;

    const spec = config.spec;

    if (!this.continue && !isLatestPatch(config.patchCompatibility)) {
      return (

              <Link to={makeAnalyzerUrl(report, fight.id)} data-tip="Back to player selection">

              </Link>

            {player.name} - {spec.specName} {spec.className}

Sorry, this spec is currently not supported

                  This spec hasn't been updated for the latest patch so we're afraid it might be outdated and misleading. We recommend reading the  Wowhead and Icy Veins guides to gain more knowledge about your spec and use this to analyze yourself. You can try asking for help in a class Discord, but they're likely too busy memeing to do thorough analysis for you.

                  We have no ETA for support for {spec.specName} {spec.className}. We need volunteer contributors to maintain specs, and seeing as {spec.specName} {spec.className} is out of date, it's likely nobody is currently maintaining it. If you are interested or know someone who might be interested helping people help themselves, check out GitHub or Discord for more information.

                    <GitHubButton />{' '}
                    <DiscordButton />

                  <Link
                    to={makeAnalyzerUrl(report, fight.id, player.id)}
                    onClick={this.handleClickContinue}
                    style={{ fontSize: '1.1em' }}
                    data-tip="Khadgar approves your bravery"
                  >
                    <Icon icon="quest_khadgar" /> Continue anyway
                  </Link>

      );
    }

    return children;
  }
}

const mapStateToProps = state => ({
  ignored: getSpecsIgnoredNotSupportedWarning(state),
});
export default connect(mapStateToProps, {
  ignoreSpecNotSupportedWarning,
})(SupportChecker);
<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
'use strict';

var express = require('express');
var Ringpop = require('../index.js');
var TChannel = require('tchannel');
var url = require('url');

function Cluster(opts) {
    opts = opts || {};
    this.name = opts.name || 'mycluster';
    this.size = opts.size || 3;
    this.basePort = opts.basePort || 3000;
    this.bootstrapNodes = opts.bootstrapNodes;
    this.host = opts.host || '127.0.0.1';

    if (!this.bootstrapNodes) {
        this.bootstrapNodes = [];

        // Create the bootstrap list of nodes that'll
        // be used to seed Ringpop for its join request.
        for (var i = 0; i < this.size; i++) {
            this.bootstrapNodes.push('127.0.0.1:' + (this.basePort + i));
        }
    }
    else  {
      for(var bs in bootstrapNodes) {
        console.log(bs);
      }
    }
}

Cluster.prototype.launch = function launch(callback) {
    var self = this;
    var ringpops = [];
    var done = after(self.size, function onDone(err) {
        callback(err, ringpops);
    });

    for (var index = 0; index < this.size; index++) {
        var tchannel = new TChannel();
        var ringpop = new Ringpop({
            app: this.name,
            hostPort: this.host + ':' + (index + this.basePort),
            channel: tchannel.makeSubChannel({
                serviceName: 'ringpop',
                trace: false
            })
        });
        ringpop.appChannel = tchannel.makeSubChannel({
            serviceName: this.name
        });
        ringpop.setupChannel();
        ringpops.push(ringpop);

        // First make sure TChannel is accepting connections.
        console.log('TChannel is listening on port ' + (this.basePort + index));
        tchannel.listen(index + this.basePort, this.host, listenCb(ringpop));
    }

    function listenCb(ringpop, index) {
        // When TChannel is listening, bootstrap Ringpop. It'll
        // try to join its friends in the bootstrap list.
        return function onListen() {
          ringpop.bootstrap(self.bootstrapNodes, done);

          // This is how you wire up a handler for forwarded requests
          ringpop.on('request', forwardedCallback(ringpop));
        };
    }
};

// IGNORE THIS! It's a little utility function that invokes
// a callback after a specified number of invocations
// of its shim.
function after(count, callback) {
    var countdown = count;

    return function shim(err) {
        if (typeof callback !== 'function') return;

        if (err) {
            callback(err);
            callback = null;
            return;
        }

        if (--countdown === 0) {
            callback();
            callback = null;
        }
    };
}

// In this example, forwarded requests are immediately ended. Fill in with
// your own application logic.
function forwardedCallback(ringpop) {
    return function onRequest(req, res) {
        var url_parts = url.parse(req.url, true);
        console.log("print out url_parts");
        for(var b in url_parts.query) {
          console.log(b);
        }
        console.log('Ringpop ' + ringpop.whoami() + ' handled forwarded ' + url_parts.query);
        res.end();
    }
}

if (require.main === module) {
    // Launch a Ringpop cluster of arbitrary size.
    var cluster = new Cluster({
        name: 'mycluster',
        size: 2,
        basePort: 3000
    });

    // When all nodes have been bootstrapped, your
    // Ringpop cluster will be ready for use.
    cluster.launch(function onLaunch(err, ringpops) {
        if (err) {
            console.error('Error: failed to launch cluster');
            process.exit(1);
        }

        console.log('Ringpop cluster is ready!');
    });
}

module.exports = Cluster;
<commit_msg>--amend<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
'use strict';

var express = require('express');
var Ringpop = require('../index.js');
var TChannel = require('tchannel');
var url = require('url');

function Cluster(opts) {
    opts = opts || {};
    this.name = opts.name || 'mycluster';
    this.size = opts.size || 3;
    this.basePort = opts.basePort || 3000;
    this.bootstrapNodes = opts.bootstrapNodes;
    this.host = opts.host || '127.0.0.1';

    if (!this.bootstrapNodes) {
        this.bootstrapNodes = [];

        // Create the bootstrap list of nodes that'll
        // be used to seed Ringpop for its join request.
        for (var i = 0; i < this.size; i++) {
            this.bootstrapNodes.push('127.0.0.1:' + (this.basePort + i));
        }
    }
    else  {
      for(var bs in this.bootstrapNodes) {
        console.log(bs);
        console.log(bootstrapNodes[bs]);
      }
    }
}

Cluster.prototype.launch = function launch(callback) {
    var self = this;
    var ringpops = [];
    var done = after(self.size, function onDone(err) {
        callback(err, ringpops);
    });

    for (var index = 0; index < this.size; index++) {
        var tchannel = new TChannel();
        var ringpop = new Ringpop({
            app: this.name,
            hostPort: this.host + ':' + (index + this.basePort),
            channel: tchannel.makeSubChannel({
                serviceName: 'ringpop',
                trace: false
            })
        });
        ringpop.appChannel = tchannel.makeSubChannel({
            serviceName: this.name
        });
        ringpop.setupChannel();
        ringpops.push(ringpop);

        // First make sure TChannel is accepting connections.
        console.log('TChannel is listening on port ' + (this.basePort + index));
        tchannel.listen(index + this.basePort, this.host, listenCb(ringpop));
    }

    function listenCb(ringpop, index) {
        // When TChannel is listening, bootstrap Ringpop. It'll
        // try to join its friends in the bootstrap list.
        return function onListen() {
          ringpop.bootstrap(self.bootstrapNodes, done);

          // This is how you wire up a handler for forwarded requests
          ringpop.on('request', forwardedCallback(ringpop));
        };
    }
};

// IGNORE THIS! It's a little utility function that invokes
// a callback after a specified number of invocations
// of its shim.
function after(count, callback) {
    var countdown = count;

    return function shim(err) {
        if (typeof callback !== 'function') return;

        if (err) {
            callback(err);
            callback = null;
            return;
        }

        if (--countdown === 0) {
            callback();
            callback = null;
        }
    };
}

// In this example, forwarded requests are immediately ended. Fill in with
// your own application logic.
function forwardedCallback(ringpop) {
    return function onRequest(req, res) {
        var url_parts = url.parse(req.url, true);
        console.log("print out url_parts");
        for(var b in url_parts.query) {
          console.log(b);
        }
        console.log('Ringpop ' + ringpop.whoami() + ' handled forwarded ' + url_parts.query);
        res.end();
    }
}

if (require.main === module) {
    // Launch a Ringpop cluster of arbitrary size.
    var cluster = new Cluster({
        name: 'mycluster',
        size: 2,
        basePort: 3000
    });

    // When all nodes have been bootstrapped, your
    // Ringpop cluster will be ready for use.
    cluster.launch(function onLaunch(err, ringpops) {
        if (err) {
            console.error('Error: failed to launch cluster');
            process.exit(1);
        }

        console.log('Ringpop cluster is ready!');
    });
}

module.exports = Cluster;
<|endoftext|>


<commit_before>ngapp.controller('profilesModalController', function ($scope, profileService, modalService) {
    // initialize scope variables
    $scope.games = xelib.games;
    $scope.languages = profileService.languages;
    $scope.profiles = profileService.profiles;
    $scope.defaultProfile = profileService.getDefaultProfile();

    // scope functions
    $scope.addProfile = function() {
        $scope.profiles.push({
            name: profileService.newProfileName('New Profile'),
            gameMode: 3,
            gamePath: '',
            language: 'English',
            valid: false
        });
        if (!$scope.defaultProfile) {
            $scope.defaultProfile = $scope.profiles[0];
        }
    };

    $scope.removeProfile = function(profile) {
        let index = $scope.profiles.indexOf(profile);
        $scope.profiles.splice(index, 1);
        if ($scope.profiles.length === 0) {
            $scope.defaultProfile = undefined;
        }
    };

    $scope.validateProfile = function(profile) {
        profileService.validateProfile(profile);
    };

    $scope.close = function() {
        profileService.setDefaultProfile($scope.defaultProfile);
        profileService.saveProfiles();
        $scope.$root.$broadcast('profilesUpdated');
        $scope.$emit('closeModal');
    };

    $scope.browse = function(profile) {
        let game = profileService.getGame(profile.gameMode);
        profile.gamePath = fh.selectDirectory(`Select your ${game.name} directory`, profile.gamePath) + '\\';
        $scope.validateProfile(profile);
    };
});
<commit_msg>broke long line into two lines<commit_after>ngapp.controller('profilesModalController', function ($scope, profileService, modalService) {
    // initialize scope variables
    $scope.games = xelib.games;
    $scope.languages = profileService.languages;
    $scope.profiles = profileService.profiles;
    $scope.defaultProfile = profileService.getDefaultProfile();

    // scope functions
    $scope.addProfile = function() {
        $scope.profiles.push({
            name: profileService.newProfileName('New Profile'),
            gameMode: 3,
            gamePath: '',
            language: 'English',
            valid: false
        });
        if (!$scope.defaultProfile) {
            $scope.defaultProfile = $scope.profiles[0];
        }
    };

    $scope.removeProfile = function(profile) {
        let index = $scope.profiles.indexOf(profile);
        $scope.profiles.splice(index, 1);
        if ($scope.profiles.length === 0) {
            $scope.defaultProfile = undefined;
        }
    };

    $scope.validateProfile = function(profile) {
        profileService.validateProfile(profile);
    };

    $scope.close = function() {
        profileService.setDefaultProfile($scope.defaultProfile);
        profileService.saveProfiles();
        $scope.$root.$broadcast('profilesUpdated');
        $scope.$emit('closeModal');
    };

    $scope.browse = function(profile) {
        let game = profileService.getGame(profile.gameMode),
            prompt = `Select your ${game.name} directory`;
        profile.gamePath = fh.selectDirectory(prompt, profile.gamePath) + '\\';
        $scope.validateProfile(profile);
    };
});
<|endoftext|>


<commit_before>const base64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
const base64inv = {'0':52,'1':53,'2':54,'3':55,'4':56,'5':57,'6':58,'7':59,'8':60,'9':61,'A':0,'B':1,'C':2,'D':3,'E':4,'F':5,'G':6,'H':7,'I':8,'J':9,'K':10,'L':11,'M':12,'N':13,'O':14,'P':15,'Q':16,'R':17,'S':18,'T':19,'U':20,'V':21,'W':22,'X':23,'Y':24,'Z':25,'a':26,'b':27,'c':28,'d':29,'e':30,'f':31,'g':32,'h':33,'i':34,'j':35,'k':36,'l':37,'m':38,'n':39,'o':40,'p':41,'q':42,'r':43,'s':44,'t':45,'u':46,'v':47,'w':48,'x':49,'y':50,'z':51,'+':62,'/':63};

function encodeBase64 (buf) {
  let str = new Array(Math.ceil(buf.length * 4 / 3));
  for (let i = 0; i < buf.length; i += 3) {
    const b0 = buf[i], b1 = buf[i + 1], b2 = buf[i + 2], b3 = buf[i + 3];
    str[i * 4 / 3] = base64chars[b0 >>> 2];
    str[i * 4 / 3 + 1] =  base64chars[b0 << 4 & 63 | (b1 || 0) >>> 4];
    if (i + 1 < buf.length) {
      str[i * 4 / 3 + 2] = base64chars[b1 << 2 & 63 | (b2 || 0) >>> 6];
      if (i + 2 < buf.length) {
        str[i * 4 / 3 + 3] = base64chars[b2 & 63];
      } else {
        return str.join('') + '=';
      }
    } else {
      return str.join('') + '==';
    }
  }
  return str.join('');
}

function decodeBase64 (str) {
  let pad = 0;
  for (let i = str.length - 1; i >= 0; --i) {
    if (str.charAt(i) == '=') {
      ++pad;
    } else {
      break;
    }
  }
  let buf = new Uint8Array(str.length * 3 / 4 - pad);
  for (let i = 0; i < str.length - pad; i += 4) {
    const c0 = base64inv[str.charAt(i)], c1 = base64inv[str.charAt(i + 1)], c2 = base64inv[str.charAt(i + 2)], c3 = base64inv[str.charAt(i + 3)];
    buf[i * 3 / 4] = c0 << 2 & 255 | c1 >>> 4;
    if (i + 2 < str.length - pad) {
      buf[i * 3 / 4 + 1] = c1 << 4 & 255 | c2 >>> 2;
      if (i + 3 < str.length - pad) {
        buf[i * 3 / 4 + 2] = c2 << 6 & 255 | c3;
      }
    }
  }
  return buf;
}
<commit_msg>Convert base64 character string to array<commit_after>const base64chars = ['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','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','0','1','2','3','4','5','6','7','8','9','+','/'];
const base64inv = {'0':52,'1':53,'2':54,'3':55,'4':56,'5':57,'6':58,'7':59,'8':60,'9':61,'A':0,'B':1,'C':2,'D':3,'E':4,'F':5,'G':6,'H':7,'I':8,'J':9,'K':10,'L':11,'M':12,'N':13,'O':14,'P':15,'Q':16,'R':17,'S':18,'T':19,'U':20,'V':21,'W':22,'X':23,'Y':24,'Z':25,'a':26,'b':27,'c':28,'d':29,'e':30,'f':31,'g':32,'h':33,'i':34,'j':35,'k':36,'l':37,'m':38,'n':39,'o':40,'p':41,'q':42,'r':43,'s':44,'t':45,'u':46,'v':47,'w':48,'x':49,'y':50,'z':51,'+':62,'/':63};

function encodeBase64 (buf) {
  let str = new Array(Math.ceil(buf.length * 4 / 3));
  for (let i = 0; i < buf.length; i += 3) {
    const b0 = buf[i], b1 = buf[i + 1], b2 = buf[i + 2], b3 = buf[i + 3];
    str[i * 4 / 3] = base64chars[b0 >>> 2];
    str[i * 4 / 3 + 1] =  base64chars[b0 << 4 & 63 | (b1 || 0) >>> 4];
    if (i + 1 < buf.length) {
      str[i * 4 / 3 + 2] = base64chars[b1 << 2 & 63 | (b2 || 0) >>> 6];
      if (i + 2 < buf.length) {
        str[i * 4 / 3 + 3] = base64chars[b2 & 63];
      } else {
        return str.join('') + '=';
      }
    } else {
      return str.join('') + '==';
    }
  }
  return str.join('');
}

function decodeBase64 (str) {
  let pad = 0;
  for (let i = str.length - 1; i >= 0; --i) {
    if (str.charAt(i) == '=') {
      ++pad;
    } else {
      break;
    }
  }
  let buf = new Uint8Array(str.length * 3 / 4 - pad);
  for (let i = 0; i < str.length - pad; i += 4) {
    const c0 = base64inv[str.charAt(i)], c1 = base64inv[str.charAt(i + 1)], c2 = base64inv[str.charAt(i + 2)], c3 = base64inv[str.charAt(i + 3)];
    buf[i * 3 / 4] = c0 << 2 & 255 | c1 >>> 4;
    if (i + 2 < str.length - pad) {
      buf[i * 3 / 4 + 1] = c1 << 4 & 255 | c2 >>> 2;
      if (i + 3 < str.length - pad) {
        buf[i * 3 / 4 + 2] = c2 << 6 & 255 | c3;
      }
    }
  }
  return buf;
}
<|endoftext|>


<commit_before>ngapp.controller('profilesModalController', function ($scope, profileService, modalService) {
    // initialize scope variables
    $scope.games = profileService.games;
    $scope.languages = profileService.languages;
    $scope.profiles = profileService.profiles;
    $scope.defaultProfile = profileService.getDefaultProfile();

    // inherited functions
    modalService.buildUnfocusModalFunction($scope, 'close');

    // scope functions
    $scope.addProfile = function() {
        $scope.profiles.push({
            name: profileService.newProfileName('New Profile'),
            gameMode: 3,
            gamePath: '',
            language: 'English',
            valid: false
        });
        if (!$scope.defaultProfile) {
            $scope.defaultProfile = $scope.profiles[0];
        }
    };

    $scope.removeProfile = function(profile) {
        let index = $scope.profiles.indexOf(profile);
        $scope.profiles.splice(index, 1);
        if ($scope.profiles.length === 0) {
            $scope.defaultProfile = undefined;
        }
    };

    $scope.validateProfile = function(profile) {
        profileService.validateProfile(profile);
    };

    $scope.close = function() {
        profileService.setDefaultProfile($scope.defaultProfile);
        profileService.saveProfiles();
        $scope.$root.$broadcast('profilesUpdated');
        $scope.$emit('closeModal');
    };

    $scope.browse = function(profile) {
        let game = profileService.getGame(profile.gameMode);
        profile.gamePath = fh.selectDirectory(`Select your ${game.name} directory`, profile.gamePath) + '\\';
        $scope.validateProfile(profile);
    };
});<commit_msg>fixed bug with profiles modal game selection<commit_after>ngapp.controller('profilesModalController', function ($scope, profileService, modalService) {
    // initialize scope variables
    $scope.games = xelib.games;
    $scope.languages = profileService.languages;
    $scope.profiles = profileService.profiles;
    $scope.defaultProfile = profileService.getDefaultProfile();

    // inherited functions
    modalService.buildUnfocusModalFunction($scope, 'close');

    // scope functions
    $scope.addProfile = function() {
        $scope.profiles.push({
            name: profileService.newProfileName('New Profile'),
            gameMode: 3,
            gamePath: '',
            language: 'English',
            valid: false
        });
        if (!$scope.defaultProfile) {
            $scope.defaultProfile = $scope.profiles[0];
        }
    };

    $scope.removeProfile = function(profile) {
        let index = $scope.profiles.indexOf(profile);
        $scope.profiles.splice(index, 1);
        if ($scope.profiles.length === 0) {
            $scope.defaultProfile = undefined;
        }
    };

    $scope.validateProfile = function(profile) {
        profileService.validateProfile(profile);
    };

    $scope.close = function() {
        profileService.setDefaultProfile($scope.defaultProfile);
        profileService.saveProfiles();
        $scope.$root.$broadcast('profilesUpdated');
        $scope.$emit('closeModal');
    };

    $scope.browse = function(profile) {
        let game = profileService.getGame(profile.gameMode);
        profile.gamePath = fh.selectDirectory(`Select your ${game.name} directory`, profile.gamePath) + '\\';
        $scope.validateProfile(profile);
    };
});
<|endoftext|>


<commit_before>/*
 * Vector rendering for all browsers that support canvas.
 */

L.Browser.canvas = (function () {
	return !!document.createElement('canvas').getContext;
}());

L.Path = (L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? L.Path : L.Path.extend({
	statics: {
		//CLIP_PADDING: 0.02, // not sure if there's a need to set it to a small value
		CANVAS: true,
		SVG: false
	},

	_initElements: function () {
		this._map._initPathRoot();
		this._ctx = this._map._canvasCtx;
	},

	_updateStyle: function () {
		var options = this.options;

		if (options.stroke) {
			this._ctx.lineWidth = options.weight;
			this._ctx.strokeStyle = options.color;
		}
		if (options.fill) {
			this._ctx.fillStyle = options.fillColor || options.color;
		}
	},

	_drawPath: function () {
		var i, j, len, len2, point, drawMethod;

		this._ctx.beginPath();

		for (i = 0, len = this._parts.length; i < len; i++) {
			for (j = 0, len2 = this._parts[i].length; j < len2; j++) {
				point = this._parts[i][j];
				drawMethod = (j === 0 ? 'move' : 'line') + 'To';

				this._ctx[drawMethod](point.x, point.y);
			}
			// TODO refactor ugly hack
			if (this instanceof L.Polygon) {
				this._ctx.closePath();
			}
		}
	},

	_checkIfEmpty: function () {
		return !this._parts.length;
	},

	_updatePath: function () {
		if (this._checkIfEmpty()) { return; }

		var ctx = this._ctx,
			options = this.options;

		this._drawPath();
		ctx.save();
		this._updateStyle();

		if (options.fill) {
			if (options.fillOpacity < 1) {
				ctx.globalAlpha = options.fillOpacity;
			}
			ctx.fill();
		}

		if (options.stroke) {
			if (options.opacity < 1) {
				ctx.globalAlpha = options.opacity;
			}
			ctx.stroke();
		}

		ctx.restore();

		// TODO optimization: 1 fill/stroke for all features with equal style instead of 1 for each feature
	},

	_initEvents: function () {
		if (this.options.clickable) {
			// TODO hand cursor
			// TODO mouseover, mouseout, dblclick
			this._map.on('click', this._onClick, this);
		}
	},

	_onClick: function (e) {
		if (this._containsPoint(e.layerPoint)) {
			this.fire('click', e);
		}
	},

    onRemove: function (map) {
        map
	        .off('viewreset', this._projectLatlngs, this)
            .off('moveend', this._updatePath, this)
            .fire('moveend');
    }
});

L.Map.include((L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? {} : {
	_initPathRoot: function () {
		var root = this._pathRoot,
			ctx;

		if (!root) {
			root = this._pathRoot = document.createElement("canvas");
			root.style.position = 'absolute';
			ctx = this._canvasCtx = root.getContext('2d');

			ctx.lineCap = "round";
			ctx.lineJoin = "round";

			this._panes.overlayPane.appendChild(root);

			if (this.options.zoomAnimation) {
				this._pathRoot.className = 'leaflet-zoom-animated';
				this.on('zoomanim', this._animatePathZoom);
				this.on('zoomend', this._endZoom);
			}
			this.on('moveend', this._updateCanvasViewport);
			this._updateCanvasViewport();
		}
	},

	_updateCanvasViewport: function () {
		if (this._pathZooming) {
			//Don't redraw while zooming. See _updateSvgViewport for more details
			return;
		}
		this._updatePathViewport();

		var vp = this._pathViewport,
			min = vp.min,
			size = vp.max.subtract(min),
			root = this._pathRoot;

		//TODO check if this works properly on mobile webkit
		L.DomUtil.setPosition(root, min);
		root.width = size.x;
		root.height = size.y;
		root.getContext('2d').translate(-min.x, -min.y);
	}
});
<commit_msg>Fix canvas zooming<commit_after>/*
 * Vector rendering for all browsers that support canvas.
 */

L.Browser.canvas = (function () {
	return !!document.createElement('canvas').getContext;
}());

L.Path = (L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? L.Path : L.Path.extend({
	statics: {
		//CLIP_PADDING: 0.02, // not sure if there's a need to set it to a small value
		CANVAS: true,
		SVG: false
	},

	_initElements: function () {
		this._map._initPathRoot();
		this._ctx = this._map._canvasCtx;
	},

	_updateStyle: function () {
		var options = this.options;

		if (options.stroke) {
			this._ctx.lineWidth = options.weight;
			this._ctx.strokeStyle = options.color;
		}
		if (options.fill) {
			this._ctx.fillStyle = options.fillColor || options.color;
		}
	},

	_drawPath: function () {
		var i, j, len, len2, point, drawMethod;

		this._ctx.beginPath();

		for (i = 0, len = this._parts.length; i < len; i++) {
			for (j = 0, len2 = this._parts[i].length; j < len2; j++) {
				point = this._parts[i][j];
				drawMethod = (j === 0 ? 'move' : 'line') + 'To';

				this._ctx[drawMethod](point.x, point.y);
			}
			// TODO refactor ugly hack
			if (this instanceof L.Polygon) {
				this._ctx.closePath();
			}
		}
	},

	_checkIfEmpty: function () {
		return !this._parts.length;
	},

	_updatePath: function () {
		if (this._checkIfEmpty()) { return; }

		var ctx = this._ctx,
			options = this.options;

		this._drawPath();
		ctx.save();
		this._updateStyle();

		if (options.fill) {
			if (options.fillOpacity < 1) {
				ctx.globalAlpha = options.fillOpacity;
			}
			ctx.fill();
		}

		if (options.stroke) {
			if (options.opacity < 1) {
				ctx.globalAlpha = options.opacity;
			}
			ctx.stroke();
		}

		ctx.restore();

		// TODO optimization: 1 fill/stroke for all features with equal style instead of 1 for each feature
	},

	_initEvents: function () {
		if (this.options.clickable) {
			// TODO hand cursor
			// TODO mouseover, mouseout, dblclick
			this._map.on('click', this._onClick, this);
		}
	},

	_onClick: function (e) {
		if (this._containsPoint(e.layerPoint)) {
			this.fire('click', e);
		}
	},

    onRemove: function (map) {
        map
	        .off('viewreset', this._projectLatlngs, this)
            .off('moveend', this._updatePath, this)
            .fire('moveend');
    }
});

L.Map.include((L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? {} : {
	_initPathRoot: function () {
		var root = this._pathRoot,
			ctx;

		if (!root) {
			root = this._pathRoot = document.createElement("canvas");
			root.style.position = 'absolute';
			ctx = this._canvasCtx = root.getContext('2d');

			ctx.lineCap = "round";
			ctx.lineJoin = "round";

			this._panes.overlayPane.appendChild(root);

			if (this.options.zoomAnimation) {
				this._pathRoot.className = 'leaflet-zoom-animated';
				this.on('zoomanim', this._animatePathZoom);
				this.on('zoomend', this._endPathZoom);
			}
			this.on('moveend', this._updateCanvasViewport);
			this._updateCanvasViewport();
		}
	},

	_updateCanvasViewport: function () {
		if (this._pathZooming) {
			//Don't redraw while zooming. See _updateSvgViewport for more details
			return;
		}
		this._updatePathViewport();

		var vp = this._pathViewport,
			min = vp.min,
			size = vp.max.subtract(min),
			root = this._pathRoot;

		//TODO check if this works properly on mobile webkit
		L.DomUtil.setPosition(root, min);
		root.width = size.x;
		root.height = size.y;
		root.getContext('2d').translate(-min.x, -min.y);
	}
});
<|endoftext|>


<commit_before>/* global window */

'use strict';

var dom = require('util/dom');

module.exports = {
	paramAttributes: [
		'data-aspect'
	],

	data: function () {
		return {
			aspect: 1

		};
	},

	ready: function () {
		window.addEventListener('resize', this.onResize);
	},

	computed: {
		viewBox: function () {
			return '0 0 ' + this.width + ' ' + this.height;
		}
	},

	methods: {
		onResize: function () {
			if (!this.$el || !this.$el.parentElement) {
				return;
			}

			var content = dom.contentArea(this.$el.parentElement);

			this.$set('width', content.width);

			if (this.aspect) {
				this.$set('height', content.width / Number(this.aspect));
			}

			this.$emit('invalidate-size');
		}
	},

	events: {
		'hook:attached': function () {
			this.onResize();
		}
	}
};
<commit_msg>Set a default width and height<commit_after>/* global window */

'use strict';

var dom = require('util/dom');

module.exports = {
	paramAttributes: [
		'data-aspect'
	],

	data: function () {
		return {
			aspect: 1,
			height: 0,
			width : 0
		};
	},

	ready: function () {
		window.addEventListener('resize', this.onResize);
	},

	computed: {
		viewBox: function () {
			return '0 0 ' + this.width + ' ' + this.height;
		}
	},

	methods: {
		onResize: function () {
			if (!this.$el || !this.$el.parentElement) {
				return;
			}

			var content = dom.contentArea(this.$el.parentElement);

			this.$set('width', content.width);

			if (this.aspect) {
				this.$set('height', content.width / Number(this.aspect));
			}

			this.$emit('invalidate-size');
		}
	},

	events: {
		'hook:attached': function () {
			this.onResize();
		}
	}
};
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/*global window,jQuery*/
(function (window, $, undefined) {

    var TemplateManager,RenderEngine,SingleValueView,TableValueView,HtmlView,ChartView,SlideShow;

    function error(msg){
        if(window.console){
            console.error(msg);
        }
    }

    TableValueView = function(){

    };

    TableValueView.prototype.transformModel = function(model,item){
        var idx,entry;

        if(!model || !model.current || !model.current.data){
            return {table:[]};
        }

        for(idx in model.current.data.table){
            entry = model.current.data.table[idx];
            entry.status = entry.value == 0 ? 'ok' : 'fail';
        }

        return model.current.data;
    };

    SingleValueView = function(views){
        this.views = views;
        this.defaultStatusThreshold = 1;
        this.relations = {
            gt : function(a,b){return a > b},
            lt : function(a,b){return a < b}
        };
        this.defaultRelation = 'lt';
    };

    SingleValueView.prototype.transformModel = function(model,item){

        // fallback
        if (!model || !model.current || !model.current.data || model.current.data.value === null) {
            return {
                current : '?',
                previous: '?',
                status :  'ok',
                diff : '?',
                diffStatus : 'ok',
                since : '?',
                unit : '?'
            }
        }

        var current  = model.current.data.value;
        var previous = null;
        var diff = null;

        if(model.previous){
            previous = model.previous.data.value;
            diff = this.calcDiff(current,previous);
        }

        return {
            current : current,
            previous: previous,
            status :  this.calcStatus(current,item),
            diff : diff,
            diffStatus : this.calcDiffStatus(diff,item),
            since : this.calcSince(model),
            unit : this.calcUnit(item)
        }
    };

    SingleValueView.prototype.calcDiff = function(current,previous){
        var diff = (current - previous);//
        if(diff - Math.floor(diff) > 0){
            diff = diff.toFixed(1);
        }
        if(diff > 0){
            return '+' + diff;
        }

        return diff.toString();
    };

    SingleValueView.prototype.calcUnit = function(item){
        if(item.conf){
            if(item.conf.unit){
                return item.conf.unit
            }
        }
        return null;
    };

    SingleValueView.prototype.calcSince = function(model){
        var creation = model.current.creation;
        var now = new Date().getTime();
        var diff = now - creation;
        var secs = this.intDiv(diff,1000);
        if(secs < 60){
            return "a few seconds ago.";
        }
        var minutes = this.intDiv(secs,60);
        if(minutes < 5){
            return "a few minutes ago.";
        }
        if(minutes < 120) {
            return "about " + minutes + " minutes ago.";
        }
        var hours = this.intDiv(minutes,60);
        if(hours < 48) {
            return "about " + hours + " hours ago.";
        }
        var days = this.intDiv(hours,24);
        return "about " + days + " days ago.";
    };

    SingleValueView.prototype.intDiv = function(a,b){
        return Math.floor( a / b );
    };

    SingleValueView.prototype.calcStatus = function(val,item){
        var statusThreshold = item.statusThreshold || this.defaultStatusThreshold;
        var statusRelation  = item.statusRelation;
        if(this.relation(statusRelation,val,statusThreshold)){
            return 'ok';
        }
        else {
            return 'fail';
        }
    };

    SingleValueView.prototype.calcDiffStatus = function(val,item){
        var diffStatusRelation = item.statusRelation;
        if(this.relation(diffStatusRelation,val,0)){
            return 'ok';
        }
        else {
            return 'fail';
        }
    };

    SingleValueView.prototype.relation = function(name,a,b){
        var rel;
        if(name){
            rel = this.relations[name];
        }
        if(!rel){
            if(name){
                error("relation does not exist: " + name);
            }
            rel = this.relations[this.defaultRelation];
        }
        return rel(a,b);
    };

    HtmlView = function() {
    };

    HtmlView.prototype.transformModel = function(model,item){
        if(!model || !model.current || !model.current.data){
            return {table:[]};
        }
        return model.current.data;
    };

    ChartView = function() {
    };

    ChartView.prototype.transformModel = function(model,item) {
        return model.current;
    };

    ChartView.prototype.onRender = function(html) {
        $elem = $(html);
        var canvasWidth = $elem.width(), //width
        canvasHeight = $elem.height(), //height
        outerRadius = ($elem.height() * 0.7 ) / 2, //radius
        color = d3.scale.category20(); //builtin range of colors

        var dataSet = [
            {"legendLabel":"Firefox", "magnitude":2},
            {"legendLabel":"Two", "magnitude":3},
            {"legendLabel":"Three", "magnitude":2},
            {"legendLabel":"Four", "magnitude":16},
            {"legendLabel":"Five", "magnitude":50},
            {"legendLabel":"Six", "magnitude":8},
            {"legendLabel":"Seven", "magnitude":30}
        ];

        // besser machen mit selecten
        var vis = d3.select($elem.find('.chart')[0])
        .append("svg:svg")//create the SVG element inside the
        .data([dataSet])//associate our data with the document
        .attr("width", canvasWidth)//set the width of the canvas
        .attr("height", canvasHeight)//set the height of the canvas
        .append("svg:g")//make a group to hold our pie chart
        .attr("transform", "translate(" + 1.5 * outerRadius + "," + 1.5 * outerRadius + ")") // relocate center of pie to 'outerRadius,outerRadius'

        // This will create <path> elements for us using arc data...
        var arc = d3.svg.arc()
        .innerRadius(outerRadius * 0.6)
        .outerRadius(outerRadius);
//

        var pie = d3.layout.pie()//this will create arc data for us given a list of values
        .value(function (d) {
            return d.magnitude;
        })// Binding each value to the pie
        .sort(function (d) {
            return null;
        });

        // Select all <g> elements with class slice (there aren't any yet)
        var arcs = vis.selectAll("g.slice")
            // Associate the generated pie data (an array of arcs, each having startAngle,
            // endAngle and value properties)
        .data(pie)
            // This will create <g> elements for every "extra" data element that should be associated
            // with a selection. The result is creating a <g> for every object in the data array
        .enter()
            // Create a group to hold each slice (we will have a <path> and a <text>
            // element associated with each slice)
        .append("svg:g")
        .attr("class", "slice");    //allow us to style things in the slices (like text)

        arcs.append("svg:path")
            //set the color for each slice to be chosen from the color function defined above
        .attr("fill", function (d, i) {
            return color(i);
        })
            //this creates the actual SVG path using the associated data (pie) with the arc drawing function
        .attr("d", arc);

        var legendSpacer = 150;
        var legendTextSize = 40;
        var legend = vis.append("svg")
        .attr("class", "legend")
        .attr("width", canvasWidth - outerRadius - legendSpacer)
        .attr("height", canvasHeight)
        .attr("x", outerRadius + legendSpacer)
        .attr("y",-outerRadius)
        .selectAll("g")
        .data(color.domain().slice().reverse())
        .enter().append("g")
        .attr("transform", function(d, i) { return "translate(0," + i * (legendTextSize + 15) + ")"; });

        legend.append("rect")
        .attr("width", legendTextSize + 2)
        .attr("height", legendTextSize + 2)
        .style("fill", color);

        legend.append("text")
        .attr("x", legendTextSize + 10)
        .attr("y", 0)
        .attr("dy", legendTextSize + "px")
        .style("font","normal " + legendTextSize + "px 'Droid Serif'")
        .text(function(d) {
            var val = dataSet[d];
            return val.legendLabel + " " + val.magnitude + "%";
        });
    };

    /**
     * The TemplateManager is responsible to extract the Mustache template code from the hosting DOM tree.
     *
     * The template has to be embedded in a script tag and there in HTML comments:
     *
     *
     */
	TemplateManager = function () {};

    /**
     * Extracts the template from the DOM Tree.
     *
     * @param container the id of the DOM script Element, which contains the tempalte code.
     */
	TemplateManager.prototype.getTemplate = function (container) {
	    var text = $('#template-' + container).html();
	    if (text === undefined || text === null) {
	        return null;
	    }

	    text = this.trimLines(text);
	    text = this.removeComments(text);

	    return text;
	};

    TemplateManager.prototype.getTemplates = function(containers) {
        var result = {}, container, template,idx;
        for(idx in containers){
            container = containers[idx];
            template = this.getTemplate(container);
            if(template != null){
                result[container] = template;
            }
        }
        return result;
    };

    /**
     * The Template Code is embedded in HTML Comments. Hence we have to remove them.
     *
     * @param str
     */
	TemplateManager.prototype.removeComments = function (str) {
	    return str.replace('', '');
	};

    /**
     * Since we create a lot of HTML, it is a good idea to avoid any non required data. Whitespace
     * as such could be removed without harm, hence we do that for the sake of performance.
     *
     * @param str
     */
	TemplateManager.prototype.trimLines = function (str) {
		var lines, i;

	    lines = str.split('\n');

	    for (i = 0; i < lines.length; i = i +  1) {
	        lines[i] = $.trim(lines[i]);
	    }

	    return lines.join('\n');
	};

    RenderEngine = function(opts){
        opts = opts || {};

        this.defaultViewName = opts.defaultView || 'single-value';
        this.entries = {};

        var items = opts.items || [];
        for(var idx in items){
            var item = items[idx];
            var itemConf = item.conf || {};

            var viewName = itemConf.view || this.defaultViewName;
            var view = opts.views[viewName];
            this.entries[item.name] = {
                item : item,
                view : view,
                viewName : viewName
            }
        }

        this.baseUrl = opts.baseUrl;

        this.templates = opts.templates || {};
    };

    RenderEngine.prototype.renderItem = function(name,dest,callback){
        var entry = this.entries[name];
        if(!entry){
            error('Cannot render item "' + name + '", because it does not consist.');
            return;
        }

        var view = entry.view;
        var item = entry.item;

        var template = this.templates[entry.viewName];
        if(!template){
            error('no template found for "' + view+"'.");
            return;
        }

        $.ajax({
            url : this.baseUrl + "/" + item.name,
            success:function(data){
                var model = view.transformModel(data,item);
                var html = $.mustache(template,model);
                $(dest).html(html);
                console.log("hasonRender?");
                if('onRender' in view) {
                    view.onRender(dest[0]);
                }
                if(callback){
                    callback();
                }
            }
        });

    };

    var slideShowAnimation = {
        slide : {
            initNewSlide : function(elem) {
                var e = $(elem);
                var height = e.height();
                e.offset({left:0,top:height});
            },
            newSlideAnimation : function(elem) {
                return {top:0};
            },
            currentSlideAnimation : function(elem) {
                var width = $(elem).width();
                return {top:-width};
            },
            serializeAnimation : false
        },
        fade : {
            initNewSlide : function(elem) {
                $(elem).css({opacity:0});
            },
            newSlideAnimation : function(elem) {
                return {opacity:1};
            },
            currentSlideAnimation : function(elem) {
                return {opacity:0};
            },
            serializeAnimation:true
        }
    };

    SlideShow = function(opts){
        this.renderEngine = opts.renderEngine;
        this.items = opts.items;
        this.container = $(opts.container);
        this.delay = (opts.delay || 5) * 1000;
        this.fxDuration = opts.fxDuration || 600;
        this.currItemId = 0;
        this.slideShowAnimation = slideShowAnimation[ opts.animation || 'slide' ];
    };

    SlideShow.prototype.start = function(){
        this.replace();
        this.animateNext();
    };

    SlideShow.prototype.animateNext = function(){
        var self = this;
        this.timer = setTimeout(function(){
            self.start();
        },this.delay);
    };

    SlideShow.prototype.replace = function(){
        var item = this.nextItem();
        this.replaceTitle(item);
        this.replaceView(item);
    };

    SlideShow.prototype.replaceTitle = function(item){
        var duration = this.fxDuration/2;
        $('#title')
                .fadeOut(duration)
                .queue(function(next){
                    $(this).html(item.title)
                    next();
                })
                .fadeIn(duration);
    };

    SlideShow.prototype.replaceView = function(item){
        var self = this;
        var elem = $('

').appendTo(this.container);
        var width = $(this.container).width();
        var height = $(this.container).height();
        var fxDuration = this.fxDuration;
        $(elem)
            .width(width)
            .height(height);
        this.initNewSlide(elem);
        this.renderEngine.renderItem(item.name,elem,function(){
            var views = $('.view',this.container);
            var currentAnimation = self.currentSlideAnimation(elem);
            var newAnimation = self.newSlideAnimation(elem);
            var serializeAnimation = self.slideShowAnimation.serializeAnimation;

            var delay = serializeAnimation ? fxDuration  : 0;
            // animate current
            if(views.length > 1){
                $(views[0]).animate( currentAnimation,fxDuration,function(){$(this).remove()});
            }
            // animate new
            $(elem).delay(delay).animate( newAnimation ,{duration: fxDuration} );
        });
    };

    SlideShow.prototype.initNewSlide = function(elem){
        return this.slideShowAnimation.initNewSlide(elem);
    };

    SlideShow.prototype.newSlideAnimation = function(elem){
        return this.slideShowAnimation.newSlideAnimation(elem);
    };

    SlideShow.prototype.currentSlideAnimation = function(elem){
        return this.slideShowAnimation.currentSlideAnimation(elem);
    };

    SlideShow.prototype.nextItem = function(){
        return this.items[this.nextItemId()];
    };

    SlideShow.prototype.nextItemId = function(){
        var curr = this.currItemId;
        this.currItemId = (curr + 1) % this.items.length;
        return curr;
    };

	window.infowall = {};
	window.infowall.TemplateManager = TemplateManager;
    window.infowall.RenderEngine = RenderEngine;
    window.infowall.SingleValueView = SingleValueView;
    window.infowall.TableValueView = TableValueView;
    window.infowall.HtmlView = HtmlView;
    window.infowall.ChartView = ChartView;
    window.infowall.SlideShow = SlideShow;

}(window, jQuery));
<commit_msg>Use actual data from model in pie chart.<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/*global window,jQuery*/
(function (window, $, undefined) {

    var TemplateManager,RenderEngine,SingleValueView,TableValueView,HtmlView,ChartView,SlideShow;

    function error(msg){
        if(window.console){
            console.error(msg);
        }
    }

    TableValueView = function(){

    };

    TableValueView.prototype.transformModel = function(model,item){
        var idx,entry;

        if(!model || !model.current || !model.current.data){
            return {table:[]};
        }

        for(idx in model.current.data.table){
            entry = model.current.data.table[idx];
            entry.status = entry.value == 0 ? 'ok' : 'fail';
        }

        return model.current.data;
    };

    SingleValueView = function(views){
        this.views = views;
        this.defaultStatusThreshold = 1;
        this.relations = {
            gt : function(a,b){return a > b},
            lt : function(a,b){return a < b}
        };
        this.defaultRelation = 'lt';
    };

    SingleValueView.prototype.transformModel = function(model,item){

        // fallback
        if (!model || !model.current || !model.current.data || model.current.data.value === null) {
            return {
                current : '?',
                previous: '?',
                status :  'ok',
                diff : '?',
                diffStatus : 'ok',
                since : '?',
                unit : '?'
            }
        }

        var current  = model.current.data.value;
        var previous = null;
        var diff = null;

        if(model.previous){
            previous = model.previous.data.value;
            diff = this.calcDiff(current,previous);
        }

        return {
            current : current,
            previous: previous,
            status :  this.calcStatus(current,item),
            diff : diff,
            diffStatus : this.calcDiffStatus(diff,item),
            since : this.calcSince(model),
            unit : this.calcUnit(item)
        }
    };

    SingleValueView.prototype.calcDiff = function(current,previous){
        var diff = (current - previous);//
        if(diff - Math.floor(diff) > 0){
            diff = diff.toFixed(1);
        }
        if(diff > 0){
            return '+' + diff;
        }

        return diff.toString();
    };

    SingleValueView.prototype.calcUnit = function(item){
        if(item.conf){
            if(item.conf.unit){
                return item.conf.unit
            }
        }
        return null;
    };

    SingleValueView.prototype.calcSince = function(model){
        var creation = model.current.creation;
        var now = new Date().getTime();
        var diff = now - creation;
        var secs = this.intDiv(diff,1000);
        if(secs < 60){
            return "a few seconds ago.";
        }
        var minutes = this.intDiv(secs,60);
        if(minutes < 5){
            return "a few minutes ago.";
        }
        if(minutes < 120) {
            return "about " + minutes + " minutes ago.";
        }
        var hours = this.intDiv(minutes,60);
        if(hours < 48) {
            return "about " + hours + " hours ago.";
        }
        var days = this.intDiv(hours,24);
        return "about " + days + " days ago.";
    };

    SingleValueView.prototype.intDiv = function(a,b){
        return Math.floor( a / b );
    };

    SingleValueView.prototype.calcStatus = function(val,item){
        var statusThreshold = item.statusThreshold || this.defaultStatusThreshold;
        var statusRelation  = item.statusRelation;
        if(this.relation(statusRelation,val,statusThreshold)){
            return 'ok';
        }
        else {
            return 'fail';
        }
    };

    SingleValueView.prototype.calcDiffStatus = function(val,item){
        var diffStatusRelation = item.statusRelation;
        if(this.relation(diffStatusRelation,val,0)){
            return 'ok';
        }
        else {
            return 'fail';
        }
    };

    SingleValueView.prototype.relation = function(name,a,b){
        var rel;
        if(name){
            rel = this.relations[name];
        }
        if(!rel){
            if(name){
                error("relation does not exist: " + name);
            }
            rel = this.relations[this.defaultRelation];
        }
        return rel(a,b);
    };

    HtmlView = function() {
    };

    HtmlView.prototype.transformModel = function(model,item){
        if(!model || !model.current || !model.current.data){
            return {table:[]};
        }
        return model.current.data;
    };

    ChartView = function() {
    };

    ChartView.prototype.transformModel = function(model,item) {
        return model.current.data;
    };

    ChartView.prototype.onRender = function(html,model) {
        $elem = $(html);
        var canvasWidth = $elem.width(), //width
        canvasHeight = $elem.height(), //height
        outerRadius = ($elem.height() * 0.7 ) / 2, //radius
        color = d3.scale.category20(); //builtin range of colors

        var vis = d3.select($elem.find('.chart')[0])
        .append("svg:svg")//create the SVG element inside the
        .data([model.data])//associate our data with the document
        .attr("width", canvasWidth)//set the width of the canvas
        .attr("height", canvasHeight)//set the height of the canvas
        .append("svg:g")//make a group to hold our pie chart
        .attr("transform", "translate(" + 1.5 * outerRadius + "," + 1.5 * outerRadius + ")"); // relocate center of pie to 'outerRadius,outerRadius'

        // This will create <path> elements for us using arc data...
        var arc = d3.svg.arc()
        .innerRadius(outerRadius * 0.6)
        .outerRadius(outerRadius);

        var pie = d3.layout.pie()//this will create arc data for us given a list of values
        .value(function (d) {
            return d.value;
        })// Binding each value to the pie
//        .sort(null);

        // Select all <g> elements with class slice (there aren't any yet)
        var arcs = vis.selectAll("g.slice")
            // Associate the generated pie data (an array of arcs, each having startAngle,
            // endAngle and value properties)
        .data(pie)
            // This will create <g> elements for every "extra" data element that should be associated
            // with a selection. The result is creating a <g> for every object in the data array
        .enter()
            // Create a group to hold each slice (we will have a <path> and a <text>
            // element associated with each slice)
        .append("svg:g")
        .attr("class", "slice");    //allow us to style things in the slices (like text)

        arcs.append("svg:path")
            //set the color for each slice to be chosen from the color function defined above
        .attr("fill", function (d, i) {
            return color(i);
        })
            //this creates the actual SVG path using the associated data (pie) with the arc drawing function
        .attr("d", arc);

        var legendSpacer = 150;
        var legendTextSize = 40;
        var legend = vis.append("svg")
        .attr("class", "legend")
        .attr("width", canvasWidth - outerRadius - legendSpacer)
        .attr("height", canvasHeight)
        .attr("x", outerRadius + legendSpacer)
        .attr("y",-outerRadius)
        .selectAll("g")
        .data(color.domain().slice().reverse())
        .enter().append("g")
        .attr("transform", function(d, i) { return "translate(0," + i * (legendTextSize + 15) + ")"; });

        legend.append("rect")
        .attr("width", legendTextSize + 2)
        .attr("height", legendTextSize + 2)
        .style("fill", color);

        legend.append("text")
        .attr("x", legendTextSize + 10)
        .attr("y", 0)
        .attr("dy", legendTextSize + "px")
        .style("font","normal " + legendTextSize + "px 'Droid Serif'")
        .text(function(d) {
            var val = model.data[d];
            return val.label + " " + val.value+ "%";
        });
    };

    /**
     * The TemplateManager is responsible to extract the Mustache template code from the hosting DOM tree.
     *
     * The template has to be embedded in a script tag and there in HTML comments:
     *
     *
     */
	TemplateManager = function () {};

    /**
     * Extracts the template from the DOM Tree.
     *
     * @param container the id of the DOM script Element, which contains the tempalte code.
     */
	TemplateManager.prototype.getTemplate = function (container) {
	    var text = $('#template-' + container).html();
	    if (text === undefined || text === null) {
	        return null;
	    }

	    text = this.trimLines(text);
	    text = this.removeComments(text);

	    return text;
	};

    TemplateManager.prototype.getTemplates = function(containers) {
        var result = {}, container, template,idx;
        for(idx in containers){
            container = containers[idx];
            template = this.getTemplate(container);
            if(template != null){
                result[container] = template;
            }
        }
        return result;
    };

    /**
     * The Template Code is embedded in HTML Comments. Hence we have to remove them.
     *
     * @param str
     */
	TemplateManager.prototype.removeComments = function (str) {
	    return str.replace('', '');
	};

    /**
     * Since we create a lot of HTML, it is a good idea to avoid any non required data. Whitespace
     * as such could be removed without harm, hence we do that for the sake of performance.
     *
     * @param str
     */
	TemplateManager.prototype.trimLines = function (str) {
		var lines, i;

	    lines = str.split('\n');

	    for (i = 0; i < lines.length; i = i +  1) {
	        lines[i] = $.trim(lines[i]);
	    }

	    return lines.join('\n');
	};

    RenderEngine = function(opts){
        opts = opts || {};

        this.defaultViewName = opts.defaultView || 'single-value';
        this.entries = {};

        var items = opts.items || [];
        for(var idx in items){
            var item = items[idx];
            var itemConf = item.conf || {};

            var viewName = itemConf.view || this.defaultViewName;
            var view = opts.views[viewName];
            this.entries[item.name] = {
                item : item,
                view : view,
                viewName : viewName
            }
        }

        this.baseUrl = opts.baseUrl;

        this.templates = opts.templates || {};
    };

    RenderEngine.prototype.renderItem = function(name,dest,callback){
        var entry = this.entries[name];
        if(!entry){
            error('Cannot render item "' + name + '", because it does not consist.');
            return;
        }

        var view = entry.view;
        var item = entry.item;

        var template = this.templates[entry.viewName];
        if(!template){
            error('no template found for "' + view+"'.");
            return;
        }

        $.ajax({
            url : this.baseUrl + "/" + item.name,
            success:function(data){
                var model = view.transformModel(data,item);
                var html = $.mustache(template,model);
                $(dest).html(html);
                console.log("hasonRender?");
                if('onRender' in view) {
                    view.onRender(dest[0], model);
                }
                if(callback){
                    callback();
                }
            }
        });

    };

    var slideShowAnimation = {
        slide : {
            initNewSlide : function(elem) {
                var e = $(elem);
                var height = e.height();
                e.offset({left:0,top:height});
            },
            newSlideAnimation : function(elem) {
                return {top:0};
            },
            currentSlideAnimation : function(elem) {
                var width = $(elem).width();
                return {top:-width};
            },
            serializeAnimation : false
        },
        fade : {
            initNewSlide : function(elem) {
                $(elem).css({opacity:0});
            },
            newSlideAnimation : function(elem) {
                return {opacity:1};
            },
            currentSlideAnimation : function(elem) {
                return {opacity:0};
            },
            serializeAnimation:true
        }
    };

    SlideShow = function(opts){
        this.renderEngine = opts.renderEngine;
        this.items = opts.items;
        this.container = $(opts.container);
        this.delay = (opts.delay || 5) * 1000;
        this.fxDuration = opts.fxDuration || 600;
        this.currItemId = 0;
        this.slideShowAnimation = slideShowAnimation[ opts.animation || 'slide' ];
    };

    SlideShow.prototype.start = function(){
        this.replace();
        this.animateNext();
    };

    SlideShow.prototype.animateNext = function(){
        var self = this;
        this.timer = setTimeout(function(){
            self.start();
        },this.delay);
    };

    SlideShow.prototype.replace = function(){
        var item = this.nextItem();
        this.replaceTitle(item);
        this.replaceView(item);
    };

    SlideShow.prototype.replaceTitle = function(item){
        var duration = this.fxDuration/2;
        $('#title')
                .fadeOut(duration)
                .queue(function(next){
                    $(this).html(item.title)
                    next();
                })
                .fadeIn(duration);
    };

    SlideShow.prototype.replaceView = function(item){
        var self = this;
        var elem = $('

').appendTo(this.container);
        var width = $(this.container).width();
        var height = $(this.container).height();
        var fxDuration = this.fxDuration;
        $(elem)
            .width(width)
            .height(height);
        this.initNewSlide(elem);
        this.renderEngine.renderItem(item.name,elem,function(){
            var views = $('.view',this.container);
            var currentAnimation = self.currentSlideAnimation(elem);
            var newAnimation = self.newSlideAnimation(elem);
            var serializeAnimation = self.slideShowAnimation.serializeAnimation;

            var delay = serializeAnimation ? fxDuration  : 0;
            // animate current
            if(views.length > 1){
                $(views[0]).animate( currentAnimation,fxDuration,function(){$(this).remove()});
            }
            // animate new
            $(elem).delay(delay).animate( newAnimation ,{duration: fxDuration} );
        });
    };

    SlideShow.prototype.initNewSlide = function(elem){
        return this.slideShowAnimation.initNewSlide(elem);
    };

    SlideShow.prototype.newSlideAnimation = function(elem){
        return this.slideShowAnimation.newSlideAnimation(elem);
    };

    SlideShow.prototype.currentSlideAnimation = function(elem){
        return this.slideShowAnimation.currentSlideAnimation(elem);
    };

    SlideShow.prototype.nextItem = function(){
        return this.items[this.nextItemId()];
    };

    SlideShow.prototype.nextItemId = function(){
        var curr = this.currItemId;
        this.currItemId = (curr + 1) % this.items.length;
        return curr;
    };

	window.infowall = {};
	window.infowall.TemplateManager = TemplateManager;
    window.infowall.RenderEngine = RenderEngine;
    window.infowall.SingleValueView = SingleValueView;
    window.infowall.TableValueView = TableValueView;
    window.infowall.HtmlView = HtmlView;
    window.infowall.ChartView = ChartView;
    window.infowall.SlideShow = SlideShow;

}(window, jQuery));
<|endoftext|>


<commit_before>'use strict';

module.exports = function(router) {
  /**
   * Middleware to restrict incoming requests by method.
   *
   * @param req
   * @param res
   * @param next
   * @returns {*}
   */
  return function(req, res, next) {
    if (
      req.method === 'OPTIONS'
      || req.method === 'GET'
      || req.method === 'POST'
      || req.method === 'PUT'
      || req.method === 'DELETE'
    ) {
      return next();
    }

    return res.sendStatus(405);
  };
};

<commit_msg>Adding dbg to restrictRequestTypes middleware.<commit_after>'use strict';

var debug = require('debug')('formio:middleware:restrictRequestTypes');

module.exports = function(router) {
  /**
   * Middleware to restrict incoming requests by method.
   *
   * @param req
   * @param res
   * @param next
   * @returns {*}
   */
  return function(req, res, next) {
    if (
      req.method === 'OPTIONS'
      || req.method === 'GET'
      || req.method === 'POST'
      || req.method === 'PUT'
      || req.method === 'DELETE'
    ) {
      return next();
    }

    debug('Blocking request: ' + (req.method || '').toUpperCase() + ' ' + req.url);
    return res.sendStatus(405);
  };
};

<|endoftext|>


<commit_before>
/*
It's expected that there will be at least one EventInstance,
OR that an explicitEventDef is assigned.
*/
var EventInstanceGroup = Class.extend({

	eventInstances: null,
	explicitEventDef: null, // optional

	constructor: function(eventInstances) {
		this.eventInstances = eventInstances || [];
	},

	getAllEventRanges: function() {
		return this.eventInstances.map(eventInstanceToEventRange);
	},

	sliceRenderRanges: function(constraintRange) {
		if (this.isInverse()) {
			return this.sliceInverseRenderRanges(constraintRange);
		}
		else {
			return this.sliceNormalRenderRanges(constraintRange);
		}
	},

	sliceNormalRenderRanges: function(constraintRange) {
		var eventInstances = this.eventInstances;
		var i, eventInstance;
		var slicedRange;
		var slicedEventRanges = [];

		for (i = 0; i < eventInstances.length; i++) {
			eventInstance = eventInstances[i];

			slicedRange = eventInstance.dateProfile.unzonedRange.intersect(constraintRange);

			if (slicedRange) {
				slicedEventRanges.push(
					new EventRange(
						slicedRange,
						eventInstance.def,
						eventInstance
					)
				);
			}
		}

		return slicedEventRanges;
	},

	sliceInverseRenderRanges: function(constraintRange) {
		var unzonedRanges = this.eventInstances.map(eventInstanceToUnzonedRange);
		var ownerDef = this.getEventDef();

		unzonedRanges = invertUnzonedRanges(unzonedRanges, constraintRange);

		return unzonedRanges.map(function(unzonedRange) {
			return new EventRange(unzonedRange, ownerDef); // don't give an EventInstance
		});
	},

	isInverse: function() {
		return this.getEventDef().hasInverseRendering();
	},

	getEventDef: function() {
		return this.explicitEventDef || this.eventInstances[0].def;
	}

});
<commit_msg>EventInstanceGroup more robust<commit_after>
/*
It's expected that there will be at least one EventInstance,
OR that an explicitEventDef is assigned.
*/
var EventInstanceGroup = FC.EventInstanceGroup = Class.extend({

	eventInstances: null,
	explicitEventDef: null, // optional

	constructor: function(eventInstances) {
		this.eventInstances = eventInstances || [];
	},

	getAllEventRanges: function(constraintRange) {
		if (constraintRange) {
			return this.sliceNormalRenderRanges(constraintRange);
		}
		else {
			return this.eventInstances.map(eventInstanceToEventRange);
		}
	},

	sliceRenderRanges: function(constraintRange) {
		if (this.isInverse()) {
			return this.sliceInverseRenderRanges(constraintRange);
		}
		else {
			return this.sliceNormalRenderRanges(constraintRange);
		}
	},

	sliceNormalRenderRanges: function(constraintRange) {
		var eventInstances = this.eventInstances;
		var i, eventInstance;
		var slicedRange;
		var slicedEventRanges = [];

		for (i = 0; i < eventInstances.length; i++) {
			eventInstance = eventInstances[i];

			slicedRange = eventInstance.dateProfile.unzonedRange.intersect(constraintRange);

			if (slicedRange) {
				slicedEventRanges.push(
					new EventRange(
						slicedRange,
						eventInstance.def,
						eventInstance
					)
				);
			}
		}

		return slicedEventRanges;
	},

	sliceInverseRenderRanges: function(constraintRange) {
		var unzonedRanges = this.eventInstances.map(eventInstanceToUnzonedRange);
		var ownerDef = this.getEventDef();

		unzonedRanges = invertUnzonedRanges(unzonedRanges, constraintRange);

		return unzonedRanges.map(function(unzonedRange) {
			return new EventRange(unzonedRange, ownerDef); // don't give an EventInstance
		});
	},

	isInverse: function() {
		return this.getEventDef().hasInverseRendering();
	},

	getEventDef: function() {
		return this.explicitEventDef || this.eventInstances[0].def;
	}

});
<|endoftext|>


<commit_before>/**!
 Plugin toggle trigger
 Triggers hide/show on target elements (or do whatever with classes) from a source element
 */

(function($) {

  $.toggleTrigger = function(el, options) {

    // Default settings values
    var defaults = {
      active:false,
      target:undefined,
      targetInvert:undefined,
      classToggle:'js-hidden',
      classActive:'is-active',
      selectorContainer:undefined, // could be '.js-toggle-container'
      selectorTarget:'.js-toggle-target',
      selectorTargetInvert:undefined,
      selectorToggleInvert:undefined,
      autoOffEvent:false, // toggle off when "outside" event (eg 'click')
      useChecked:false // if true, $element needs to be checked (input radio/checkbox) to activate the target
    };

    var plugin = this;

    plugin.settings = {};

    var $element = $(el),
      element = el;

    // Plugin initialization
    plugin.init = function() {
      plugin.settings = $.extend({}, defaults, options);
      updateSettingsFromHTMLData();
      registerEvents();
      if(plugin.settings.useChecked) plugin.settings.active = $element.is(':checked');
      else plugin.settings.active = $element.hasClass(plugin.settings.classActive);
      if(!plugin.settings.target) {
        if(plugin.settings.selectorContainer) {
          // When using a container
          var $c = $element.closest(plugin.settings.selectorContainer);
          plugin.settings.target = $c.find(plugin.settings.selectorTarget);
          if(plugin.settings.selectorTargetInvert) plugin.settings.targetInvert = $c.find(plugin.settings.selectorTargetInvert);
        } else {
          // Not within a container, search the whole DOM
          plugin.settings.target = $(plugin.settings.selectorTarget);
          if(plugin.settings.selectorTargetInvert) plugin.settings.targetInvert = $(plugin.settings.selectorTargetInvert);
          if(plugin.settings.selectorToggleInvert) plugin.settings.toggleInvert = $(plugin.settings.selectorToggleInvert);
        }
      }
      if(plugin.settings.target && !plugin.settings.active) {
        plugin.settings.target.addClass(plugin.settings.classToggle);
      }
    };

    // Reads plugin settings from HTML data-* attributes (camelCase)
    var updateSettingsFromHTMLData = function() {
      var data = $element.data();
      for (var dat in data) plugin.settings[dat] = data[dat];
    };

    // Set event handlers on HTML elements (private method)
    var registerEvents = function() {
      $element.off('click.toggletrigger').on('click.toggletrigger', plugin.toggleTarget);
      $element.off('toggle-trigger-off').on('toggle-trigger-off', plugin.toggleOff);
      if(plugin.settings.autoOffEvent) {
        $('html').on(plugin.settings.autoOffEvent+'.toggleAutoOff', plugin.toggleOff);
        $element.on(plugin.settings.autoOffEvent+'.toggletriggerOff', function(e) {
          e.stopPropagation();
        });
      }
    };

    // Toggle the state on the target element (public method)
    plugin.toggleTarget = function() {
      if(plugin.settings.useChecked) plugin.settings.active = $element.is(':checked');
      else plugin.settings.active = plugin.settings.target.hasClass(plugin.settings.classToggle);
      // Toggle the active class on the element itself
      $element.toggleClass(plugin.settings.classActive,plugin.settings.active);
      // Toggle the defined class on the target
      if(plugin.settings.target) {
        plugin.settings.target.toggleClass(plugin.settings.classToggle,!plugin.settings.active);
      }
      if(plugin.settings.targetInvert) {
        plugin.settings.targetInvert.toggleClass(plugin.settings.classToggle,plugin.settings.active);
      }
      if(plugin.settings.toggleInvert && plugin.settings.active) {
        plugin.settings.toggleInvert.not($element).trigger('toggle-trigger-off');
      }
      // If needed : toggle internal icon state
      // $('.icon-plus, .icon-minus',$element).toggleClass('icon-plus icon-minus');
      var textLabel = $('span.visually-hidden',$element);
      if(plugin.settings.active) textLabel.text(textLabel.data('togglemsg-on'));
      else textLabel.text(textLabel.data('togglemsg-off'));
    };

    // Toggle the state off the inverted target (public method)
    plugin.toggleOff = function() {
      plugin.settings.target.addClass(plugin.settings.classToggle);
      $element.removeClass(plugin.settings.classActive);
    };

    // Initialization
    plugin.init();

  };

  $.fn.toggleTrigger = function(options) {

    return this.each(function() {
      if (undefined === $(this).data('toggleTrigger')) {
        var plugin = new $.toggleTrigger(this, options);
        $(this).data('toggleTrigger', plugin);
      }
    });

  };

  $(document).ready(function() {
    $('.js-toggle-trigger').toggleTrigger();
  });

})(jQuery);
<commit_msg>Gestion de types d'événements différents<commit_after>/**!
 Plugin toggle trigger
 Triggers hide/show on target elements (or do whatever with classes) from a source element
 */

(function($) {

  $.toggleTrigger = function(el, options) {

    // Default settings values
    var defaults = {
      active:false,
      events:'click',
      target:undefined,
      targetInvert:undefined,
      classToggle:'js-hidden',
      classActive:'is-active',
      selectorContainer:undefined, // could be '.js-toggle-container'
      selectorTarget:'.js-toggle-target',
      selectorTargetInvert:undefined,
      selectorToggleInvert:undefined,
      autoOffEvent:false, // toggle off when "outside" event (eg 'click')
      useChecked:false // if true, $element needs to be checked (input radio/checkbox) to activate the target
    };

    var plugin = this;

    plugin.settings = {};

    var $element = $(el),
      element = el;

    // Plugin initialization
    plugin.init = function() {
      plugin.settings = $.extend({}, defaults, options);
      updateSettingsFromHTMLData();
      registerEvents();
      if(plugin.settings.useChecked) plugin.settings.active = $element.is(':checked');
      else plugin.settings.active = $element.hasClass(plugin.settings.classActive);
      if(!plugin.settings.target) {
        if(plugin.settings.selectorContainer) {
          // When using a container
          var $c = $element.closest(plugin.settings.selectorContainer);
          plugin.settings.target = $c.find(plugin.settings.selectorTarget);
          if(plugin.settings.selectorTargetInvert) plugin.settings.targetInvert = $c.find(plugin.settings.selectorTargetInvert);
        } else {
          // Not within a container, search the whole DOM
          plugin.settings.target = $(plugin.settings.selectorTarget);
          if(plugin.settings.selectorTargetInvert) plugin.settings.targetInvert = $(plugin.settings.selectorTargetInvert);
          if(plugin.settings.selectorToggleInvert) plugin.settings.toggleInvert = $(plugin.settings.selectorToggleInvert);
        }
      }
      if(plugin.settings.target && !plugin.settings.active) {
        plugin.settings.target.addClass(plugin.settings.classToggle);
      }
    };

    // Reads plugin settings from HTML data-* attributes (camelCase)
    var updateSettingsFromHTMLData = function() {
      var data = $element.data();
      for (var dat in data) plugin.settings[dat] = data[dat];
    };

    // Set event handlers on HTML elements (private method)
    var registerEvents = function() {
      var ev = plugin.settings.events.split(' ').map(function(e) { return e+'.toggletrigger'; }).join(' ');
      $element.off(ev).on(ev, plugin.toggleTarget);
      $element.off('toggle-trigger-off').on('toggle-trigger-off', plugin.toggleOff);
      if(plugin.settings.autoOffEvent) {
        $('html').on(plugin.settings.autoOffEvent+'.toggleAutoOff', plugin.toggleOff);
        $element.on(plugin.settings.autoOffEvent+'.toggletriggerOff', function(e) {
          e.stopPropagation();
        });
      }
    };

    // Toggle the state on the target element (public method)
    plugin.toggleTarget = function() {
      if(plugin.settings.useChecked) plugin.settings.active = $element.is(':checked');
      else plugin.settings.active = plugin.settings.target.hasClass(plugin.settings.classToggle);
      // Toggle the active class on the element itself
      $element.toggleClass(plugin.settings.classActive,plugin.settings.active);
      // Toggle the defined class on the target
      if(plugin.settings.target) {
        plugin.settings.target.toggleClass(plugin.settings.classToggle,!plugin.settings.active);
      }
      if(plugin.settings.targetInvert) {
        plugin.settings.targetInvert.toggleClass(plugin.settings.classToggle,plugin.settings.active);
      }
      if(plugin.settings.toggleInvert && plugin.settings.active) {
        plugin.settings.toggleInvert.not($element).trigger('toggle-trigger-off');
      }
      // If needed : toggle internal icon state
      // $('.icon-plus, .icon-minus',$element).toggleClass('icon-plus icon-minus');
      var textLabel = $('span.visually-hidden',$element);
      if(plugin.settings.active) textLabel.text(textLabel.data('togglemsg-on'));
      else textLabel.text(textLabel.data('togglemsg-off'));
    };

    // Toggle the state off the inverted target (public method)
    plugin.toggleOff = function() {
      plugin.settings.target.addClass(plugin.settings.classToggle);
      $element.removeClass(plugin.settings.classActive);
    };

    // Initialization
    plugin.init();

  };

  $.fn.toggleTrigger = function(options) {

    return this.each(function() {
      if (undefined === $(this).data('toggleTrigger')) {
        var plugin = new $.toggleTrigger(this, options);
        $(this).data('toggleTrigger', plugin);
      }
    });

  };

  $(document).ready(function() {
    $('.js-toggle-trigger').toggleTrigger();
  });

})(jQuery);
<|endoftext|>