<commit_before>import { Client } from 'discord.js'
import chalk from 'chalk'
import { config } from './config'

import { r } from './util/thinky'
import { User } from './models/user'
import { Message } from './models/message'

const {log} = console
const client = new Client()

const WELCOME_MESSAGE = `
______   ___   _______  _______  _______  ______    ______   _______  ___   _
|      | |   | |       ||       ||       ||    _ |  |      | |  _    ||   | | |
|  _    ||   | |  _____||       ||   _   ||   | ||  |  _    || | |   ||   |_| |
| | |   ||   | | |_____ |       ||  | |  ||   |_||_ | | |   || |_|   ||      _|
| |_|   ||   | |_____  ||      _||  |_|  ||    __  || |_|   ||___    ||     |_
|       ||   |  _____| ||     |_ |       ||   |  | ||       |    |   ||    _  |
|______| |___| |_______||_______||_______||___|  |_||______|     |___||___| |_|
`

client.on('ready', () => {

  log(chalk.bold.red(WELCOME_MESSAGE))

  client.guilds.map((guild) => {
    log("Connected to " + chalk.blue(guild.name) + " @ " + chalk.gray(guild.id))

    //Remove all r9k roles from all users the bot is in on connect.
    removeR9K(guild)

    setInterval(() => {
      User.filter(r.row("timeout").gt(1000))
      .run()
      .then(result => {
        log("Halving the timeout of each member (decay trigger).")

        for(let each of result) {
          each.timeout = Math.floor(each.timeout / 2)
          each.save()
        }
      })
    }, config.decay)
  })

  console.log("Ready!");
})

client.on('message', msg => {

  //THE MIGHTY R9K ALGORITHM!!11
  Message.filter({ //Check if a message exists in the db.
    channel: msg.channel.id,
    content: msg.content
  })
  .run()
  .then(result => {
    if(result[0]) { //If a result was found, delete the new message.
      msg.delete().catch(console.error)

      log("Found unoriginal message: " + chalk.magenta(msg.content) + " @ " + chalk.gray(msg.channel.id))

      //Check if the offender exists in the db.
      User.filter({
        snowflake: msg.member.id,
        channel: msg.channel.id
      })
      .run()
      .then(result => {
        let timeout = 0

        if(result[0]) {
          result[0].timeout *= config.multiplier
          result[0].save()
          timeout = result[0].timeout
        }
        else {
          User.save({
            snowflake: msg.member.id,
            channel: msg.channel.id,
            timeout: config.start
          })

          timeout = config.start
        }

        getR9K(msg.guild)
        .then(r9k => {
          msg.member.addRole(r9k)
          log("Timing out " + chalk.yellow(msg.member.displayName) + " for " + chalk.cyan(timeout+"ms"))

          setTimeout(() => {
            msg.member.removeRole(r9k)
            log("Timeout ended for " + chalk.yellow(msg.member.displayName) + " for " + chalk.cyan(timeout+"ms"))
          }, timeout)
        })

      })

    }
    else { //If not, save the message into the db.
      Message.save({
        channel: msg.channel.id,
        content: msg.content
      })
      .then(result => {
        log("Saved: " + chalk.magenta(`'${result.content}'`) + " @ " + chalk.gray(result.channel));
      })
      .error(error => {
        log(chalk.red(error));
      })
    }
  })
})

client.login(process.env.TOKEN)

// Find the R9K role in a guild.
async function getR9K(guild) {
  return new Promise((resolve, reject) => {
    guild.roles.map(role => {
      if(role.name == 'r9k') {
        log("Found role " + chalk.green(role.name) + " in " + chalk.blue(guild.name))
        resolve(role)
      }
    })
  })
}

//Remove all R9K roles in a guild.
async function removeR9K(guild) {
  await getR9K(guild)
  .then(role => {
    guild.members.map(member => {
      if(member.roles.exists("name", "r9k")) {
        member.removeRole(role)
        .then(() => {
          log("Removed r9k from " + chalk.yellow(member.displayName))
        })
        .catch(err => {
          log(chalk.blue(guild.name) + ": " +chalk.red(err))
        })
      }
    })
  })
  .catch(err => {
    log(chalk.red(err))
  })
}
<commit_msg>Update index.js<commit_after>import { Client } from 'discord.js'
import chalk from 'chalk'
import { config } from './config'

import { r } from './util/thinky'
import { User } from './models/user'
import { Message } from './models/message'

const {log} = console
const client = new Client()

const WELCOME_MESSAGE = `
______   ___   _______  _______  _______  ______    ______   _______  ___   _
|      | |   | |       ||       ||       ||    _ |  |      | |  _    ||   | | |
|  _    ||   | |  _____||       ||   _   ||   | ||  |  _    || | |   ||   |_| |
| | |   ||   | | |_____ |       ||  | |  ||   |_||_ | | |   || |_|   ||      _|
| |_|   ||   | |_____  ||      _||  |_|  ||    __  || |_|   ||___    ||     |_
|       ||   |  _____| ||     |_ |       ||   |  | ||       |    |   ||    _  |
|______| |___| |_______||_______||_______||___|  |_||______|     |___||___| |_|
`

client.on('ready', () => {

  log(chalk.bold.red(WELCOME_MESSAGE))

  client.guilds.map((guild) => {
    log("Connected to " + chalk.blue(guild.name) + " @ " + chalk.gray(guild.id))

    //Remove all r9k roles from all users the bot is in on connect.
    removeR9K(guild)

    setInterval(() => {
      User.filter(r.row("timeout").gt(1000))
      .run()
      .then(result => {
        log("Halving the timeout of each member (decay trigger).")

        for(let each of result) {
          each.timeout = Math.floor(each.timeout / 2)
          each.save()
        }
      })
    }, config.decay)
  })

  console.log("Ready!");
})

client.on('message', msg => {

  //THE MIGHTY R9K ALGORITHM!!11
  Message.filter({ //Check if a message exists in the db.
    channel: msg.channel.id,
    content: msg.content
  })
  .run()
  .then(result => {
    if(result[0]) { //If a result was found, delete the new message.
      msg.delete().catch(console.error)

      log("Found unoriginal message: " + chalk.magenta(msg.content) + " @ " + chalk.gray(msg.channel.id))

      //Check if the offender exists in the db.
      User.filter({
        snowflake: msg.member.id,
        channel: msg.channel.id
      })
      .run()
      .then(result => {
        let timeout = 0

        if(result[0]) {
          result[0].timeout *= config.multiplier
          result[0].save()
          timeout = result[0].timeout
        }
        else {
          User.save({
            snowflake: msg.member.id,
            channel: msg.channel.id,
            timeout: config.start
          })

          timeout = config.start
        }

        getR9K(msg.guild)
        .then(r9k => {
          msg.member.addRole(r9k)
          log("Timing out " + chalk.yellow(msg.member.displayName) + " for " + chalk.cyan(timeout+"ms"))

          setTimeout(() => {
            msg.member.removeRole(r9k)
            log("Timeout ended for " + chalk.yellow(msg.member.displayName) + " for " + chalk.cyan(timeout+"ms"))
          }, timeout)
        })

      })

    }
    else { //If not, save the message into the db.
      Message.save({
        channel: msg.channel.id,
        content: msg.content
      })
      .then(result => {
        log("Saved: " + chalk.magenta(`'${result.content}'`) + " @ " + chalk.gray(result.channel));
      })
      .error(error => {
        log(chalk.red(error));
      })
    }
  })
})

client.login(process.env.TOKEN)

// Find the R9K role in a guild.
async function getR9K(guild) {
  return new Promise((resolve, reject) => {
    guild.roles.map(role => {
      if(role.name === 'r9k') {
        log("Found role " + chalk.green(role.name) + " in " + chalk.blue(guild.name))
        resolve(role)
      }
    })
  })
}

//Remove all R9K roles in a guild.
async function removeR9K(guild) {
  await getR9K(guild)
  .then(role => {
    guild.members.map(member => {
      if(member.roles.exists("name", "r9k")) {
        member.removeRole(role)
        .then(() => {
          log("Removed r9k from " + chalk.yellow(member.displayName))
        })
        .catch(err => {
          log(chalk.blue(guild.name) + ": " +chalk.red(err))
        })
      }
    })
  })
  .catch(err => {
    log(chalk.red(err))
  })
}
<|endoftext|>


<commit_before>import 'babel-polyfill'
import LFSR from './lfsr'
import MSequence from './m-sequence'

export LFSR
export MSequence
<commit_msg>Fixed exports in index.js<commit_after>import 'babel-polyfill'
import LFSR from './lfsr'
import MSequence from './m-sequence'

export let lfsr = LFSR
export let m_sequence = MSequence
<|endoftext|>


<commit_before>var Key = require('./eckey')
var T = require('./transaction')

module.exports = {
  Address: require('./address'),
  base58: require('./base58'),
  base58check: require('./base58check'),
  BigInteger: require('./jsbn/jsbn'),
  convert: require('./convert'),
  crypto: require('./crypto'),
  CryptoJS: require('crypto-js'),
  ecdsa: require('./ecdsa'),
  ECKey: Key.ECKey,
  ECPointFp: require('./jsbn/ec').ECPointFp,
  ECPubKey: Key.ECPubKey,
  Message: require('./message'),
  Opcode: require('./opcode'),
  HDWallet: require('./hdwallet'),
  Script: require('./script'),
  Transaction: T.Transaction,
  TransactionIn: T.TransactionIn,
  TransactionOut: T.TransactionOut,
  network: require('./network'),
  Wallet: require('./wallet')
}
<commit_msg>CryptoJS no longer exported by default<commit_after>var Key = require('./eckey')
var T = require('./transaction')

module.exports = {
  Address: require('./address'),
  base58: require('./base58'),
  base58check: require('./base58check'),
  BigInteger: require('./jsbn/jsbn'),
  convert: require('./convert'),
  crypto: require('./crypto'),
  ecdsa: require('./ecdsa'),
  ECKey: Key.ECKey,
  ECPointFp: require('./jsbn/ec').ECPointFp,
  ECPubKey: Key.ECPubKey,
  Message: require('./message'),
  Opcode: require('./opcode'),
  HDWallet: require('./hdwallet'),
  Script: require('./script'),
  Transaction: T.Transaction,
  TransactionIn: T.TransactionIn,
  TransactionOut: T.TransactionOut,
  network: require('./network'),
  Wallet: require('./wallet')
}
<|endoftext|>


<commit_before>import ReactDOM from 'react-dom';
import React from 'react';
import { createStore, applyMiddleware, compose } from 'redux';
import { Provider } from 'react-redux';
import thunk from 'redux-thunk';

import Layout from './modules/layout/view';
import rootReducer from './reducer';
import { configureRoutes } from './routes';

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

const store = finalCreateStore(rootReducer);
configureRoutes(store);

const render = () => {
  ReactDOM.render((
    <Provider store={store}>
      <Layout />
    </Provider>
  ), document.getElementById('root'));
};

store.subscribe(render);
render();
<commit_msg>Add some comments<commit_after>import ReactDOM from 'react-dom';
import React from 'react';
import { createStore, applyMiddleware, compose } from 'redux';
import { Provider } from 'react-redux';
import thunk from 'redux-thunk';

import { configureRoutes } from './routes';
import rootReducer from './reducer';
// This is the Layout of our app, which render it based
// on the route actions
import Layout from './modules/layout/view';

// Apply middlewares and add support for dev tools
const finalCreateStore = compose(
  applyMiddleware(thunk),
  window.devToolsExtension ? window.devToolsExtension() : f => f
)(createStore);

// create the store
const store = finalCreateStore(rootReducer);

// configure routes
configureRoutes(store);

// Render the the layout
const render = () => {
  ReactDOM.render((
    <Provider store={store}>
      <Layout />
    </Provider>
  ), document.getElementById('root'));
};

store.subscribe(render);
render();
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';

import { HashRouter, Switch, Route, NavLink, Redirect } from 'react-router-dom';
import { TransitionGroup, CSSTransition } from 'react-transition-group'

require('./style.css')

import style from './styl/style.styl';
import {Window, Navbar, Menu, Toolbar} from 'butter-base-components';

import ButterSettings from 'butter-component-settings';
import List from 'butter-component-list';
import {RouterMenu} from 'butter-component-menu';
import MovieDetail from 'butter-component-movie-details';

import logo from './img/logo.png';

let imgs = [
    'https://farm1.staticflickr.com/751/22609797817_f2e2ff56eb_o_d.jpg',
    'https://farm6.staticflickr.com/5800/31223777911_7b960ddaae_k_d.jpg',
    'https://farm6.staticflickr.com/5512/31337144505_0d1b06879c_k_d.jpg'
]

let BackgroundImage = ({url, visible}) => (
    <div className={`${style.backdrop}`}
         style={{
             backgroundImage: `url(${url})`,
             opacity: visible ? 1 : 0,
             transition: `opacity 2s`
         }}>

)

class RotatingImages extends Component {
    constructor(props) {
        super(props)

        this.state = {
            idx: 0,
            show: 0,
            hide: -1 % props.imgs.length
        }
    }

    componentWillMount() {

        this.timer = setInterval(() => {
            this.setState((state, props) => ({
                hide: state.idx,
            }))

            setTimeout(() => (
                this.setState((state, props) => ({
                    idx: (state.idx + 1) % props.imgs.length
                }))
            ), this.props.switchTime*10)

            setTimeout(() => (
                this.setState((state, props) => ({
                    show: state.idx
                }))
            ), this.props.switchTime*200)
        }, this.props.switchTime*1000)
    }

    componentWillUnmount() {
        clearTimeout(this.timer)
    }

    render () {
        let {imgs, switchTime} = this.props;
        let {idx, hide, show} = this.state;
        let nextIdx = (idx + 1) % imgs.length;

        return ([
            <BackgroundImage key={idx} url={imgs[idx]} visible={idx !== hide} />,
            <BackgroundImage key={nextIdx} url={imgs[nextIdx]} visible={nextIdx === show} />
        ])
    }
}

RotatingImages.propTypes = {
    imgs: PropTypes.array.isRequired,
    switchTime: PropTypes.number.isRequired
}

RotatingImages.defaultProps = {
    switchTime: 100
}

let relativePath = (location, path) => {
    let basepath = location.pathname.split('/').slice(0, -1).join('/')
    return `${basepath}/${path}`
}

let defaultToolbar = (history) => (
    <Toolbar search={true} buttons={[
        {title: "settings", icon:"settings", action: () => (history.push('/settings'))}
    ]}/>
)

let MovieView = ({history, location, item}) => ([
    <Navbar key='main_nav'
            title="Go Back"
            goBack={() => (history.goBack())}
            right = {defaultToolbar(history)}
    />,
    <MovieDetail {...item} />
])

let debug = (e)=> {debugger}

let ListView = ({items, menu, path, history, location}) => ([
    <Navbar key='main_nav'
            left={
                <RouterMenu items={menu.map((c) => ({
                        path: relativePath(location, c),
                        title: c
                }))} location={location}/>
            }
            right = {defaultToolbar(history)}
    />,

        {menu.map((path) => (<Route path={relativePath(location, path)} key={path} render={() => (
            <List key={path} items={items[path]} action={(item) => history.push(`/movies/${path}/${item.title}`)}/>
        )} />))}
        <Route render={() => (<Redirect to={`/list/${menu[0]}`} />)} />

])

let NinjaWindow = ({settings, ...props}) => (
    <Window
        title={}>
        <Switch>
            <Route path='/settings' render={() => (
                <ButterSettings {...settings} location={props.location} navbar={
                    {goBack: () => (props.history.goBack())}
                }/>
            )} />
            <Route path={'/movies/:col/:id'} render={({match, ...routerProps}) => (
                <MovieView {...routerProps} item={
                    props.items[match.params.col]
                         .filter((i) => (i.title === match.params.id))[0]
                }/>
            )} />
            <Route path='/list' render={() => (
                <ListView menu={Object.keys(props.items)} {...props}/>
            )} />
            <Route render={() => (<Redirect to='/list' />)} />
        </Switch>
    </Window>)

let ButterNinja = (props) => (

        <RotatingImages imgs={imgs}/>
        <NinjaWindow {...props} />

)

let RoutedNinja = (props) => (
    <HashRouter>
        <Route render={(routeProps) => (
            <ButterNinja {...props} {...routeProps}/>
        )} />
    </HashRouter>
)

export default RoutedNinja;
<commit_msg>all routes should be switched<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';

import { HashRouter, Switch, Route, NavLink, Redirect } from 'react-router-dom';
import { TransitionGroup, CSSTransition } from 'react-transition-group'

require('./style.css')

import style from './styl/style.styl';
import {Window, Navbar, Menu, Toolbar} from 'butter-base-components';

import ButterSettings from 'butter-component-settings';
import List from 'butter-component-list';
import {RouterMenu} from 'butter-component-menu';
import MovieDetail from 'butter-component-movie-details';

import logo from './img/logo.png';

let imgs = [
    'https://farm1.staticflickr.com/751/22609797817_f2e2ff56eb_o_d.jpg',
    'https://farm6.staticflickr.com/5800/31223777911_7b960ddaae_k_d.jpg',
    'https://farm6.staticflickr.com/5512/31337144505_0d1b06879c_k_d.jpg'
]

let BackgroundImage = ({url, visible}) => (
    <div className={`${style.backdrop}`}
         style={{
             backgroundImage: `url(${url})`,
             opacity: visible ? 1 : 0,
             transition: `opacity 2s`
         }}>

)

class RotatingImages extends Component {
    constructor(props) {
        super(props)

        this.state = {
            idx: 0,
            show: 0,
            hide: -1 % props.imgs.length
        }
    }

    componentWillMount() {

        this.timer = setInterval(() => {
            this.setState((state, props) => ({
                hide: state.idx,
            }))

            setTimeout(() => (
                this.setState((state, props) => ({
                    idx: (state.idx + 1) % props.imgs.length
                }))
            ), this.props.switchTime*10)

            setTimeout(() => (
                this.setState((state, props) => ({
                    show: state.idx
                }))
            ), this.props.switchTime*200)
        }, this.props.switchTime*1000)
    }

    componentWillUnmount() {
        clearTimeout(this.timer)
    }

    render () {
        let {imgs, switchTime} = this.props;
        let {idx, hide, show} = this.state;
        let nextIdx = (idx + 1) % imgs.length;

        return ([
            <BackgroundImage key={idx} url={imgs[idx]} visible={idx !== hide} />,
            <BackgroundImage key={nextIdx} url={imgs[nextIdx]} visible={nextIdx === show} />
        ])
    }
}

RotatingImages.propTypes = {
    imgs: PropTypes.array.isRequired,
    switchTime: PropTypes.number.isRequired
}

RotatingImages.defaultProps = {
    switchTime: 100
}

let relativePath = (location, path) => {
    let basepath = location.pathname.split('/').slice(0, -1).join('/')
    return `${basepath}/${path}`
}

let defaultToolbar = (history) => (
    <Toolbar search={true} buttons={[
        {title: "settings", icon:"settings", action: () => (history.push('/settings'))}
    ]}/>
)

let MovieView = ({history, location, item}) => ([
    <Navbar key='main_nav'
            title="Go Back"
            goBack={() => (history.goBack())}
            right = {defaultToolbar(history)}
    />,
    <MovieDetail {...item} />
])

let debug = (e)=> {debugger}

let ListView = ({items, menu, path, history, location}) => ([
    <Navbar key='main_nav'
            left={
                <RouterMenu items={menu.map((c) => ({
                        path: relativePath(location, c),
                        title: c
                }))} location={location}/>
            }
            right = {defaultToolbar(history)}
    />,

        <Switch>
            {menu.map((path) => (<Route path={relativePath(location, path)} key={path} render={() => (
                <List key={path} items={items[path]} action={(item) => history.push(`/movies/${path}/${item.title}`)}/>
            )} />))}
            <Route render={() => (<Redirect to={`/list/${menu[0]}`} />)} />
        </Switch>

])

let NinjaWindow = ({settings, ...props}) => (
    <Window
        title={}>
        <Switch>
            <Route path='/settings' render={() => (
                <ButterSettings {...settings} location={props.location} navbar={
                    {goBack: () => (props.history.goBack())}
                }/>
            )} />
            <Route path={'/movies/:col/:id'} render={({match, ...routerProps}) => (
                <MovieView {...routerProps} item={
                    props.items[match.params.col]
                         .filter((i) => (i.title === match.params.id))[0]
                }/>
            )} />
            <Route path='/list' render={() => (
                <ListView menu={Object.keys(props.items)} {...props}/>
            )} />
            <Route render={() => (<Redirect to='/list' />)} />
        </Switch>
    </Window>)

let ButterNinja = (props) => (

        <RotatingImages imgs={imgs}/>
        <NinjaWindow {...props} />

)

let RoutedNinja = (props) => (
    <HashRouter>
        <Route render={(routeProps) => (
            <ButterNinja {...props} {...routeProps}/>
        )} />
    </HashRouter>
)

export default RoutedNinja;
<|endoftext|>


<commit_before>const browser = typeof window !== 'undefined';
const querystring = require('querystring');
const Package = require('../package');
const transport = browser ? require('./browser') : require('./node');

/**
 * Snekfetch
 * @extends Stream.Readable
 * @extends Promise
 */
class Snekfetch extends transport.Extension {
  /**
   * Options to pass to the Snekfetch constructor
   * @typedef {object} snekfetchOptions
   * @memberof Snekfetch
   * @property {object} [headers] Headers to initialize the request with
   * @property {object|string|Buffer} [data] Data to initialize the request with
   * @property {string|Object} [query] Query to intialize the request with
   * @property {boolean} [followRedirects=true] If the request should follow redirects
   * @property {object} [qs=querystring] Querystring module to use, any object providing
   * `stringify` and `parse` for querystrings
   * @property {number} [version = 1] The http version to use [1 or 2]
   * @property {external:Agent} [agent] Whether to use an http agent
   */

  /**
   * Create a request.
   * Usually you'll want to do `Snekfetch#method(url [, options])` instead of
   * `new Snekfetch(method, url [, options])`
   * @param {string} method HTTP method
   * @param {string} url URL
   * @param {Snekfetch.snekfetchOptions} opts Options
   */
  constructor(method, url, opts = {
    version: 1,
    qs: querystring,
    followRedirects: true,
  }) {
    super();
    this.options = opts;
    this.request = transport.buildRequest.call(this, method, url, opts);
    if (opts.query) this.query(opts.query);
    if (opts.data) this.send(opts.data);
  }

  /**
   * Add a query param to the request
   * @param {string|Object} name Name of query param or object to add to query
   * @param {string} [value] If name is a string value, this will be the value of the query param
   * @returns {Snekfetch} This request
   */
  query(name, value) {
    this._checkModify();
    if (!this.request.query) this.request.query = {};
    if (name !== null && typeof name === 'object') {
      for (const [k, v] of Object.entries(name)) this.query(k, v);
    } else {
      this.request.query[name] = value;
    }
    return this;
  }

  /**
   * Add a header to the request
   * @param {string|Object} name Name of query param or object to add to headers
   * @param {string} [value] If name is a string value, this will be the value of the header
   * @returns {Snekfetch} This request
   */
  set(name, value) {
    this._checkModify();
    if (name !== null && typeof name === 'object') {
      for (const key of Object.keys(name)) this.set(key, name[key]);
    } else {
      this.request.setHeader(name, value);
    }
    return this;
  }

  /**
   * Attach a form data object
   * @param {string} name Name of the form attachment
   * @param {string|Object|Buffer} data Data for the attachment
   * @param {string} [filename] Optional filename if form attachment name needs to be overridden
   * @returns {Snekfetch} This request
   */
  attach(...args) {
    this._checkModify();
    const form = this._getFormData();
    if (typeof args[0] === 'object') {
      for (const [k, v] of Object.entries(args[0])) this.attach(k, v);
    } else {
      form.append(...args);
    }
    return this;
  }

  /**
   * Send data with the request
   * @param {string|Buffer|Object} data Data to send
   * @returns {Snekfetch} This request
   */
  send(data) {
    this._checkModify();
    if (data instanceof transport.FormData || transport.shouldSendRaw(data)) {
      this.data = data;
    } else if (data !== null && typeof data === 'object') {
      const header = this.request.getHeader('content-type');
      let serialize;
      if (header) {
        if (header.includes('json')) serialize = JSON.stringify;
        else if (header.includes('urlencoded')) serialize = this.options.qs.stringify;
      } else {
        this.set('Content-Type', 'application/json');
        serialize = JSON.stringify;
      }
      this.data = serialize(data);
    } else {
      this.data = data;
    }
    return this;
  }

  then(resolver, rejector) {
    if (this._response) return this._response.then(resolver, rejector);
    // eslint-disable-next-line no-return-assign
    return this._response = transport.finalizeRequest.call(this)
      .then(({ response, raw, redirect, headers }) => {
        if (redirect) {
          let method = this.request.method;
          if ([301, 302].includes(response.statusCode)) {
            if (method !== 'HEAD') method = 'GET';
            this.data = null;
          } else if (response.statusCode === 303) {
            method = 'GET';
          }

          const redirectHeaders = this.request.getHeaders();
          delete redirectHeaders.host;
          return new Snekfetch(method, redirect, {
            data: this.data,
            headers: redirectHeaders,
          });
        }

        const statusCode = response.statusCode || response.status;
        // forgive me :(
        const self = this; // eslint-disable-line consistent-this
        /**
         * Response from Snekfetch
         * @typedef {Object} SnekfetchResponse
         * @memberof Snekfetch
         * @prop {HTTP.Request} request
         * @prop {?string|object|Buffer} body Processed response body
         * @prop {string} text Raw response body
         * @prop {boolean} ok If the response code is >= 200 and < 300
         * @prop {number} status HTTP status code
         * @prop {string} statusText Human readable HTTP status
         */
        const res = {
          request: this.request,
          get body() {
            delete res.body;
            const type = this.headers['content-type'];
            if (type && type.includes('application/json')) {
              try {
                res.body = JSON.parse(res.text);
              } catch (err) {
                res.body = res.text;
              }
            } else if (type && type.includes('application/x-www-form-urlencoded')) {
              res.body = self.options.qs.parse(res.text);
            } else {
              res.body = raw;
            }

            return res.body;
          },
          text: raw.toString(),
          ok: statusCode >= 200 && statusCode < 400,
          headers: headers || response.headers,
          status: statusCode,
          statusText: response.statusText || transport.STATUS_CODES[response.statusCode],
        };

        if (res.ok) {
          return res;
        } else {
          const err = new Error(`${res.status} ${res.statusText}`.trim());
          Object.assign(err, res);
          return Promise.reject(err);
        }
      })
      .then(resolver, rejector);
  }

  catch(rejector) {
    return this.then(null, rejector);
  }

  /**
   * End the request
   * @param {Function} [cb] Optional callback to handle the response
   * @returns {Promise} This request
   */
  end(cb) {
    return this.then(
      (res) => cb ? cb(null, res) : res,
      (err) => cb ? cb(err, err.status ? err : null) : Promise.reject(err)
    );
  }

  _getFormData() {
    if (!(this.data instanceof transport.FormData)) {
      this.data = new transport.FormData();
    }
    return this.data;
  }

  _finalizeRequest() {
    if (!this.request) return;
    if (!this.request.getHeader('user-agent')) {
      this.set('User-Agent', `snekfetch/${Snekfetch.version} (${Package.homepage})`);
    }
    if (this.request.method !== 'HEAD') this.set('Accept-Encoding', 'gzip, deflate');
    if (this.data && this.data.getBoundary) {
      this.set('Content-Type', `multipart/form-data; boundary=${this.data.getBoundary()}`);
    }
    if (this.request.query) {
      const [path, query] = this.request.path.split('?');
      this.request.path = `${path}?${this.options.qs.stringify(this.request.query)}${query ? `&${query}` : ''}`;
    }
  }

  _checkModify() {
    if (this.response) throw new Error('Cannot modify request after it has been sent!');
  }
}

Snekfetch.version = Package.version;

/**
 * Create a ((THIS)) request
 * @dynamic this.METHODS
 * @method Snekfetch.((THIS)lowerCase)
 * @param {string} url The url to request
 * @param {Snekfetch.snekfetchOptions} [opts] Options
 * @returns {Snekfetch}
 */
Snekfetch.METHODS = transport.METHODS.concat('BREW').filter((m) => m !== 'M-SEARCH');
for (const method of Snekfetch.METHODS) {
  Snekfetch[method.toLowerCase()] = (url, opts) => new Snekfetch(method, url, opts);
}

module.exports = Snekfetch;

/**
 * @external Agent
 * @see {@link https://nodejs.org/api/http.html#http_class_http_agent}
 */
<commit_msg>fix issue with default params<commit_after>const browser = typeof window !== 'undefined';
const querystring = require('querystring');
const Package = require('../package');
const transport = browser ? require('./browser') : require('./node');

/**
 * Snekfetch
 * @extends Stream.Readable
 * @extends Promise
 */
class Snekfetch extends transport.Extension {
  /**
   * Options to pass to the Snekfetch constructor
   * @typedef {object} snekfetchOptions
   * @memberof Snekfetch
   * @property {object} [headers] Headers to initialize the request with
   * @property {object|string|Buffer} [data] Data to initialize the request with
   * @property {string|Object} [query] Query to intialize the request with
   * @property {boolean} [followRedirects=true] If the request should follow redirects
   * @property {object} [qs=querystring] Querystring module to use, any object providing
   * `stringify` and `parse` for querystrings
   * @property {number} [version = 1] The http version to use [1 or 2]
   * @property {external:Agent} [agent] Whether to use an http agent
   */

  /**
   * Create a request.
   * Usually you'll want to do `Snekfetch#method(url [, options])` instead of
   * `new Snekfetch(method, url [, options])`
   * @param {string} method HTTP method
   * @param {string} url URL
   * @param {Snekfetch.snekfetchOptions} opts Options
   */
  constructor(method, url, opts = {}) {
    super();
    this.options = Object.assign({ version: 1, qs: querystring, followRedirects: true }, opts);
    this.request = transport.buildRequest.call(this, method, url, opts);
    if (opts.query) this.query(opts.query);
    if (opts.data) this.send(opts.data);
  }

  /**
   * Add a query param to the request
   * @param {string|Object} name Name of query param or object to add to query
   * @param {string} [value] If name is a string value, this will be the value of the query param
   * @returns {Snekfetch} This request
   */
  query(name, value) {
    this._checkModify();
    if (!this.request.query) this.request.query = {};
    if (name !== null && typeof name === 'object') {
      for (const [k, v] of Object.entries(name)) this.query(k, v);
    } else {
      this.request.query[name] = value;
    }
    return this;
  }

  /**
   * Add a header to the request
   * @param {string|Object} name Name of query param or object to add to headers
   * @param {string} [value] If name is a string value, this will be the value of the header
   * @returns {Snekfetch} This request
   */
  set(name, value) {
    this._checkModify();
    if (name !== null && typeof name === 'object') {
      for (const key of Object.keys(name)) this.set(key, name[key]);
    } else {
      this.request.setHeader(name, value);
    }
    return this;
  }

  /**
   * Attach a form data object
   * @param {string} name Name of the form attachment
   * @param {string|Object|Buffer} data Data for the attachment
   * @param {string} [filename] Optional filename if form attachment name needs to be overridden
   * @returns {Snekfetch} This request
   */
  attach(...args) {
    this._checkModify();
    const form = this._getFormData();
    if (typeof args[0] === 'object') {
      for (const [k, v] of Object.entries(args[0])) this.attach(k, v);
    } else {
      form.append(...args);
    }
    return this;
  }

  /**
   * Send data with the request
   * @param {string|Buffer|Object} data Data to send
   * @returns {Snekfetch} This request
   */
  send(data) {
    this._checkModify();
    if (data instanceof transport.FormData || transport.shouldSendRaw(data)) {
      this.data = data;
    } else if (data !== null && typeof data === 'object') {
      const header = this.request.getHeader('content-type');
      let serialize;
      if (header) {
        if (header.includes('json')) serialize = JSON.stringify;
        else if (header.includes('urlencoded')) serialize = this.options.qs.stringify;
      } else {
        this.set('Content-Type', 'application/json');
        serialize = JSON.stringify;
      }
      this.data = serialize(data);
    } else {
      this.data = data;
    }
    return this;
  }

  then(resolver, rejector) {
    if (this._response) return this._response.then(resolver, rejector);
    // eslint-disable-next-line no-return-assign
    return this._response = transport.finalizeRequest.call(this)
      .then(({ response, raw, redirect, headers }) => {
        if (redirect) {
          let method = this.request.method;
          if ([301, 302].includes(response.statusCode)) {
            if (method !== 'HEAD') method = 'GET';
            this.data = null;
          } else if (response.statusCode === 303) {
            method = 'GET';
          }

          const redirectHeaders = this.request.getHeaders();
          delete redirectHeaders.host;
          return new Snekfetch(method, redirect, {
            data: this.data,
            headers: redirectHeaders,
          });
        }

        const statusCode = response.statusCode || response.status;
        // forgive me :(
        const self = this; // eslint-disable-line consistent-this
        /**
         * Response from Snekfetch
         * @typedef {Object} SnekfetchResponse
         * @memberof Snekfetch
         * @prop {HTTP.Request} request
         * @prop {?string|object|Buffer} body Processed response body
         * @prop {string} text Raw response body
         * @prop {boolean} ok If the response code is >= 200 and < 300
         * @prop {number} status HTTP status code
         * @prop {string} statusText Human readable HTTP status
         */
        const res = {
          request: this.request,
          get body() {
            delete res.body;
            const type = this.headers['content-type'];
            if (type && type.includes('application/json')) {
              try {
                res.body = JSON.parse(res.text);
              } catch (err) {
                res.body = res.text;
              }
            } else if (type && type.includes('application/x-www-form-urlencoded')) {
              res.body = self.options.qs.parse(res.text);
            } else {
              res.body = raw;
            }

            return res.body;
          },
          text: raw.toString(),
          ok: statusCode >= 200 && statusCode < 400,
          headers: headers || response.headers,
          status: statusCode,
          statusText: response.statusText || transport.STATUS_CODES[response.statusCode],
        };

        if (res.ok) {
          return res;
        } else {
          const err = new Error(`${res.status} ${res.statusText}`.trim());
          Object.assign(err, res);
          return Promise.reject(err);
        }
      })
      .then(resolver, rejector);
  }

  catch(rejector) {
    return this.then(null, rejector);
  }

  /**
   * End the request
   * @param {Function} [cb] Optional callback to handle the response
   * @returns {Promise} This request
   */
  end(cb) {
    return this.then(
      (res) => cb ? cb(null, res) : res,
      (err) => cb ? cb(err, err.status ? err : null) : Promise.reject(err)
    );
  }

  _getFormData() {
    if (!(this.data instanceof transport.FormData)) {
      this.data = new transport.FormData();
    }
    return this.data;
  }

  _finalizeRequest() {
    if (!this.request) return;
    if (!this.request.getHeader('user-agent')) {
      this.set('User-Agent', `snekfetch/${Snekfetch.version} (${Package.homepage})`);
    }
    if (this.request.method !== 'HEAD') this.set('Accept-Encoding', 'gzip, deflate');
    if (this.data && this.data.getBoundary) {
      this.set('Content-Type', `multipart/form-data; boundary=${this.data.getBoundary()}`);
    }
    if (this.request.query) {
      const [path, query] = this.request.path.split('?');
      this.request.path = `${path}?${this.options.qs.stringify(this.request.query)}${query ? `&${query}` : ''}`;
    }
  }

  _checkModify() {
    if (this.response) throw new Error('Cannot modify request after it has been sent!');
  }
}

Snekfetch.version = Package.version;

/**
 * Create a ((THIS)) request
 * @dynamic this.METHODS
 * @method Snekfetch.((THIS)lowerCase)
 * @param {string} url The url to request
 * @param {Snekfetch.snekfetchOptions} [opts] Options
 * @returns {Snekfetch}
 */
Snekfetch.METHODS = transport.METHODS.concat('BREW').filter((m) => m !== 'M-SEARCH');
for (const method of Snekfetch.METHODS) {
  Snekfetch[method.toLowerCase()] = (url, opts) => new Snekfetch(method, url, opts);
}

module.exports = Snekfetch;

/**
 * @external Agent
 * @see {@link https://nodejs.org/api/http.html#http_class_http_agent}
 */
<|endoftext|>


<commit_before>import MascotBot from './bots/mascot-bot.js';
import RandomChannel from './behaviors/random-channel/random-channel.js';
import DaysUntil from './behaviors/days-until/days-until.js';

const name = process.env.NAME || 'Beatz Bot',
  beatzBot = new MascotBot({
    name,
    behaviors: [
      {
        behavior: DaysUntil,
        settings: {
          conDate: '10/19/2016',
          sayInChannel: '#drop-the-beatz',
          isPubic: false
        }
      }/*,
      {
        behavior: RandomChannel,
        settings: {
          sayInChannel: '#drop-the-beatz'
        }
      }*/
    ]
  });

beatzBot.launch();
<commit_msg>Update Beatz Bot behaviors<commit_after>import MascotBot from './bots/mascot-bot.js';
import RandomChannel from './behaviors/random-channel/random-channel.js';
import DaysUntil from './behaviors/days-until/days-until.js';
import Introductions from './behaviors/introductions/introductions.js';

const name = process.env.NAME || 'Beatz Bot',
  beatzBot = new MascotBot({
    name,
    behaviors: [
      Introductions,
      {
        behavior: DaysUntil,
        settings: {
          conDate: '08/11/2017',
          sayInChannel: '#drop-the-beatz',
          isPubic: false
        }
      },
      {
        behavior: RandomChannel,
        settings: {
          sayInChannel: '#drop-the-beatz'
        }
      }
    ]
  });

beatzBot.launch();
<|endoftext|>


<commit_before>var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;

var SUPPORT_TOUCH = ('ontouchstart' in window);
var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined;
var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);

var INPUT_TYPE_TOUCH = 'touch';
var INPUT_TYPE_PEN = 'pen';
var INPUT_TYPE_MOUSE = 'mouse';
var INPUT_TYPE_KINECT = 'kinect';

var COMPUTE_INTERVAL = 25;

var INPUT_START = 1;
var INPUT_MOVE = 2;
var INPUT_END = 4;
var INPUT_CANCEL = 8;

var DIRECTION_NONE = 1;
var DIRECTION_LEFT = 2;
var DIRECTION_RIGHT = 4;
var DIRECTION_UP = 8;
var DIRECTION_DOWN = 16;

var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT;
var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN;
var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;

var PROPS_XY = ['x', 'y'];
var PROPS_CLIENT_XY = ['clientX', 'clientY'];

/**
 * create new input type manager
 * @param {Manager} manager
 * @param {Function} callback
 * @returns {Input}
 * @constructor
 */
function Input(manager, callback) {
    var self = this;
    this.manager = manager;
    this.callback = callback;
    this.element = manager.element;
    this.target = manager.options.inputTarget;

    // smaller wrapper around the handler, for the scope and the enabled state of the manager,
    // so when disabled the input events are completely bypassed.
    this.domHandler = function(ev) {
        if (boolOrFn(manager.options.enable, [manager])) {
            self.handler(ev);
        }
    };

    this.init();

}

Input.prototype = {
    /**
     * should handle the inputEvent data and trigger the callback
     * @virtual
     */
    handler: function() { },

    /**
     * bind the events
     */
    init: function() {
        this.evEl && addEventListeners(this.element, this.evEl, this.domHandler);
        this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler);
        this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
    },

    /**
     * unbind the events
     */
    destroy: function() {
        this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler);
        this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler);
        this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
    }
};

/**
 * create new input type manager
 * called by the Manager constructor
 * @param {Hammer} manager
 * @returns {Input}
 */
function createInputInstance(manager) {
    var Type;
    var inputClass = manager.options.inputClass;

    if(inputClass) {
        Type = inputClass;
    } else if (SUPPORT_POINTER_EVENTS) {
        Type = PointerEventInput;
    } else if (SUPPORT_ONLY_TOUCH) {
        Type = TouchInput;
    } else if (!SUPPORT_TOUCH) {
        Type = MouseInput;
    } else {
        Type = TouchMouseInput;
    }
    return new (Type)(manager, inputHandler);
}

/**
 * handle input events
 * @param {Manager} manager
 * @param {String} eventType
 * @param {Object} input
 */
function inputHandler(manager, eventType, input) {
    var pointersLen = input.pointers.length;
    var changedPointersLen = input.changedPointers.length;
    var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0));
    var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0));

    input.isFirst = !!isFirst;
    input.isFinal = !!isFinal;

    if (isFirst) {
        manager.session = {};
    }

    // source event is the normalized value of the domEvents
    // like 'touchstart, mouseup, pointerdown'
    input.eventType = eventType;

    // compute scale, rotation etc
    computeInputData(manager, input);

    // emit secret event
    manager.emit('hammer.input', input);

    manager.recognize(input);
    manager.session.prevInput = input;
}

/**
 * extend the data with some usable properties like scale, rotate, velocity etc
 * @param {Object} manager
 * @param {Object} input
 */
function computeInputData(manager, input) {
    var session = manager.session;
    var pointers = input.pointers;
    var pointersLength = pointers.length;

    // store the first input to calculate the distance and direction
    if (!session.firstInput) {
        session.firstInput = simpleCloneInputData(input);
    }

    // to compute scale and rotation we need to store the multiple touches
    if (pointersLength > 1 && !session.firstMultiple) {
        session.firstMultiple = simpleCloneInputData(input);
    } else if (pointersLength === 1) {
        session.firstMultiple = false;
    }

    var firstInput = session.firstInput;
    var firstMultiple = session.firstMultiple;
    var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center;

    var center = input.center = getCenter(pointers);
    input.timeStamp = now();
    input.deltaTime = input.timeStamp - firstInput.timeStamp;

    input.angle = getAngle(offsetCenter, center);
    input.distance = getDistance(offsetCenter, center);

    computeDeltaXY(session, input);
    input.offsetDirection = getDirection(input.deltaX, input.deltaY);

    input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1;
    input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0;

    computeIntervalInputData(session, input);

    // find the correct target
    var target = manager.element;
    if (hasParent(input.srcEvent.target, target)) {
        target = input.srcEvent.target;
    }
    input.target = target;
}

function computeDeltaXY(session, input) {
    var center = input.center;
    var offset = session.offsetDelta || {};
    var prevDelta = session.prevDelta || {};
    var prevInput = session.prevInput || {};

    if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) {
        prevDelta = session.prevDelta = {
            x: prevInput.deltaX || 0,
            y: prevInput.deltaY || 0
        };

        offset = session.offsetDelta = {
            x: center.x,
            y: center.y
        };
    }

    input.deltaX = prevDelta.x + (center.x - offset.x);
    input.deltaY = prevDelta.y + (center.y - offset.y);
}

/**
 * velocity is calculated every x ms
 * @param {Object} session
 * @param {Object} input
 */
function computeIntervalInputData(session, input) {
    var last = session.lastInterval || input,
        deltaTime = input.timeStamp - last.timeStamp,
        velocity, velocityX, velocityY, direction;

    if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) {
        var deltaX = last.deltaX - input.deltaX;
        var deltaY = last.deltaY - input.deltaY;

        var v = getVelocity(deltaTime, deltaX, deltaY);
        velocityX = v.x;
        velocityY = v.y;
        velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y;
        direction = getDirection(deltaX, deltaY);

        session.lastInterval = input;
    } else {
        // use latest velocity info if it doesn't overtake a minimum period
        velocity = last.velocity;
        velocityX = last.velocityX;
        velocityY = last.velocityY;
        direction = last.direction;
    }

    input.velocity = velocity;
    input.velocityX = velocityX;
    input.velocityY = velocityY;
    input.direction = direction;
}

/**
 * create a simple clone from the input used for storage of firstInput and firstMultiple
 * @param {Object} input
 * @returns {Object} clonedInputData
 */
function simpleCloneInputData(input) {
    // make a simple copy of the pointers because we will get a reference if we don't
    // we only need clientXY for the calculations
    var pointers = [];
    for (var i = 0; i < input.pointers.length; i++) {
        pointers[i] = {
            clientX: round(input.pointers[i].clientX),
            clientY: round(input.pointers[i].clientY)
        };
    }

    return {
        timeStamp: now(),
        pointers: pointers,
        center: getCenter(pointers),
        deltaX: input.deltaX,
        deltaY: input.deltaY
    };
}

/**
 * get the center of all the pointers
 * @param {Array} pointers
 * @return {Object} center contains `x` and `y` properties
 */
function getCenter(pointers) {
    var pointersLength = pointers.length;

    // no need to loop when only one touch
    if (pointersLength === 1) {
        return {
            x: round(pointers[0].clientX),
            y: round(pointers[0].clientY)
        };
    }

    var x = 0, y = 0;
    for (var i = 0; i < pointersLength; i++) {
        x += pointers[i].clientX;
        y += pointers[i].clientY;
    }

    return {
        x: round(x / pointersLength),
        y: round(y / pointersLength)
    };
}

/**
 * calculate the velocity between two points. unit is in px per ms.
 * @param {Number} deltaTime
 * @param {Number} x
 * @param {Number} y
 * @return {Object} velocity `x` and `y`
 */
function getVelocity(deltaTime, x, y) {
    return {
        x: x / deltaTime || 0,
        y: y / deltaTime || 0
    };
}

/**
 * get the direction between two points
 * @param {Number} x
 * @param {Number} y
 * @return {Number} direction
 */
function getDirection(x, y) {
    if (x === y) {
        return DIRECTION_NONE;
    }

    if (abs(x) >= abs(y)) {
        return x > 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
    }
    return y > 0 ? DIRECTION_UP : DIRECTION_DOWN;
}

/**
 * calculate the absolute distance between two points
 * @param {Object} p1 {x, y}
 * @param {Object} p2 {x, y}
 * @param {Array} [props] containing x and y keys
 * @return {Number} distance
 */
function getDistance(p1, p2, props) {
    if (!props) {
        props = PROPS_XY;
    }
    var x = p2[props[0]] - p1[props[0]],
        y = p2[props[1]] - p1[props[1]];

    return Math.sqrt((x * x) + (y * y));
}

/**
 * calculate the angle between two coordinates
 * @param {Object} p1
 * @param {Object} p2
 * @param {Array} [props] containing x and y keys
 * @return {Number} angle
 */
function getAngle(p1, p2, props) {
    if (!props) {
        props = PROPS_XY;
    }
    var x = p2[props[0]] - p1[props[0]],
        y = p2[props[1]] - p1[props[1]];
    return Math.atan2(y, x) * 180 / Math.PI;
}

/**
 * calculate the rotation degrees between two pointersets
 * @param {Array} start array of pointers
 * @param {Array} end array of pointers
 * @return {Number} rotation
 */
function getRotation(start, end) {
    return getAngle(end[1], end[0], PROPS_CLIENT_XY) - getAngle(start[1], start[0], PROPS_CLIENT_XY);
}

/**
 * calculate the scale factor between two pointersets
 * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
 * @param {Array} start array of pointers
 * @param {Array} end array of pointers
 * @return {Number} scale
 */
function getScale(start, end) {
    return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY);
}
<commit_msg>codestyle<commit_after>var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;

var SUPPORT_TOUCH = ('ontouchstart' in window);
var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined;
var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);

var INPUT_TYPE_TOUCH = 'touch';
var INPUT_TYPE_PEN = 'pen';
var INPUT_TYPE_MOUSE = 'mouse';
var INPUT_TYPE_KINECT = 'kinect';

var COMPUTE_INTERVAL = 25;

var INPUT_START = 1;
var INPUT_MOVE = 2;
var INPUT_END = 4;
var INPUT_CANCEL = 8;

var DIRECTION_NONE = 1;
var DIRECTION_LEFT = 2;
var DIRECTION_RIGHT = 4;
var DIRECTION_UP = 8;
var DIRECTION_DOWN = 16;

var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT;
var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN;
var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;

var PROPS_XY = ['x', 'y'];
var PROPS_CLIENT_XY = ['clientX', 'clientY'];

/**
 * create new input type manager
 * @param {Manager} manager
 * @param {Function} callback
 * @returns {Input}
 * @constructor
 */
function Input(manager, callback) {
    var self = this;
    this.manager = manager;
    this.callback = callback;
    this.element = manager.element;
    this.target = manager.options.inputTarget;

    // smaller wrapper around the handler, for the scope and the enabled state of the manager,
    // so when disabled the input events are completely bypassed.
    this.domHandler = function(ev) {
        if (boolOrFn(manager.options.enable, [manager])) {
            self.handler(ev);
        }
    };

    this.init();

}

Input.prototype = {
    /**
     * should handle the inputEvent data and trigger the callback
     * @virtual
     */
    handler: function() { },

    /**
     * bind the events
     */
    init: function() {
        this.evEl && addEventListeners(this.element, this.evEl, this.domHandler);
        this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler);
        this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
    },

    /**
     * unbind the events
     */
    destroy: function() {
        this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler);
        this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler);
        this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
    }
};

/**
 * create new input type manager
 * called by the Manager constructor
 * @param {Hammer} manager
 * @returns {Input}
 */
function createInputInstance(manager) {
    var Type;
    var inputClass = manager.options.inputClass;

    if (inputClass) {
        Type = inputClass;
    } else if (SUPPORT_POINTER_EVENTS) {
        Type = PointerEventInput;
    } else if (SUPPORT_ONLY_TOUCH) {
        Type = TouchInput;
    } else if (!SUPPORT_TOUCH) {
        Type = MouseInput;
    } else {
        Type = TouchMouseInput;
    }
    return new (Type)(manager, inputHandler);
}

/**
 * handle input events
 * @param {Manager} manager
 * @param {String} eventType
 * @param {Object} input
 */
function inputHandler(manager, eventType, input) {
    var pointersLen = input.pointers.length;
    var changedPointersLen = input.changedPointers.length;
    var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0));
    var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0));

    input.isFirst = !!isFirst;
    input.isFinal = !!isFinal;

    if (isFirst) {
        manager.session = {};
    }

    // source event is the normalized value of the domEvents
    // like 'touchstart, mouseup, pointerdown'
    input.eventType = eventType;

    // compute scale, rotation etc
    computeInputData(manager, input);

    // emit secret event
    manager.emit('hammer.input', input);

    manager.recognize(input);
    manager.session.prevInput = input;
}

/**
 * extend the data with some usable properties like scale, rotate, velocity etc
 * @param {Object} manager
 * @param {Object} input
 */
function computeInputData(manager, input) {
    var session = manager.session;
    var pointers = input.pointers;
    var pointersLength = pointers.length;

    // store the first input to calculate the distance and direction
    if (!session.firstInput) {
        session.firstInput = simpleCloneInputData(input);
    }

    // to compute scale and rotation we need to store the multiple touches
    if (pointersLength > 1 && !session.firstMultiple) {
        session.firstMultiple = simpleCloneInputData(input);
    } else if (pointersLength === 1) {
        session.firstMultiple = false;
    }

    var firstInput = session.firstInput;
    var firstMultiple = session.firstMultiple;
    var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center;

    var center = input.center = getCenter(pointers);
    input.timeStamp = now();
    input.deltaTime = input.timeStamp - firstInput.timeStamp;

    input.angle = getAngle(offsetCenter, center);
    input.distance = getDistance(offsetCenter, center);

    computeDeltaXY(session, input);
    input.offsetDirection = getDirection(input.deltaX, input.deltaY);

    input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1;
    input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0;

    computeIntervalInputData(session, input);

    // find the correct target
    var target = manager.element;
    if (hasParent(input.srcEvent.target, target)) {
        target = input.srcEvent.target;
    }
    input.target = target;
}

function computeDeltaXY(session, input) {
    var center = input.center;
    var offset = session.offsetDelta || {};
    var prevDelta = session.prevDelta || {};
    var prevInput = session.prevInput || {};

    if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) {
        prevDelta = session.prevDelta = {
            x: prevInput.deltaX || 0,
            y: prevInput.deltaY || 0
        };

        offset = session.offsetDelta = {
            x: center.x,
            y: center.y
        };
    }

    input.deltaX = prevDelta.x + (center.x - offset.x);
    input.deltaY = prevDelta.y + (center.y - offset.y);
}

/**
 * velocity is calculated every x ms
 * @param {Object} session
 * @param {Object} input
 */
function computeIntervalInputData(session, input) {
    var last = session.lastInterval || input,
        deltaTime = input.timeStamp - last.timeStamp,
        velocity, velocityX, velocityY, direction;

    if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) {
        var deltaX = last.deltaX - input.deltaX;
        var deltaY = last.deltaY - input.deltaY;

        var v = getVelocity(deltaTime, deltaX, deltaY);
        velocityX = v.x;
        velocityY = v.y;
        velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y;
        direction = getDirection(deltaX, deltaY);

        session.lastInterval = input;
    } else {
        // use latest velocity info if it doesn't overtake a minimum period
        velocity = last.velocity;
        velocityX = last.velocityX;
        velocityY = last.velocityY;
        direction = last.direction;
    }

    input.velocity = velocity;
    input.velocityX = velocityX;
    input.velocityY = velocityY;
    input.direction = direction;
}

/**
 * create a simple clone from the input used for storage of firstInput and firstMultiple
 * @param {Object} input
 * @returns {Object} clonedInputData
 */
function simpleCloneInputData(input) {
    // make a simple copy of the pointers because we will get a reference if we don't
    // we only need clientXY for the calculations
    var pointers = [];
    for (var i = 0; i < input.pointers.length; i++) {
        pointers[i] = {
            clientX: round(input.pointers[i].clientX),
            clientY: round(input.pointers[i].clientY)
        };
    }

    return {
        timeStamp: now(),
        pointers: pointers,
        center: getCenter(pointers),
        deltaX: input.deltaX,
        deltaY: input.deltaY
    };
}

/**
 * get the center of all the pointers
 * @param {Array} pointers
 * @return {Object} center contains `x` and `y` properties
 */
function getCenter(pointers) {
    var pointersLength = pointers.length;

    // no need to loop when only one touch
    if (pointersLength === 1) {
        return {
            x: round(pointers[0].clientX),
            y: round(pointers[0].clientY)
        };
    }

    var x = 0, y = 0;
    for (var i = 0; i < pointersLength; i++) {
        x += pointers[i].clientX;
        y += pointers[i].clientY;
    }

    return {
        x: round(x / pointersLength),
        y: round(y / pointersLength)
    };
}

/**
 * calculate the velocity between two points. unit is in px per ms.
 * @param {Number} deltaTime
 * @param {Number} x
 * @param {Number} y
 * @return {Object} velocity `x` and `y`
 */
function getVelocity(deltaTime, x, y) {
    return {
        x: x / deltaTime || 0,
        y: y / deltaTime || 0
    };
}

/**
 * get the direction between two points
 * @param {Number} x
 * @param {Number} y
 * @return {Number} direction
 */
function getDirection(x, y) {
    if (x === y) {
        return DIRECTION_NONE;
    }

    if (abs(x) >= abs(y)) {
        return x > 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
    }
    return y > 0 ? DIRECTION_UP : DIRECTION_DOWN;
}

/**
 * calculate the absolute distance between two points
 * @param {Object} p1 {x, y}
 * @param {Object} p2 {x, y}
 * @param {Array} [props] containing x and y keys
 * @return {Number} distance
 */
function getDistance(p1, p2, props) {
    if (!props) {
        props = PROPS_XY;
    }
    var x = p2[props[0]] - p1[props[0]],
        y = p2[props[1]] - p1[props[1]];

    return Math.sqrt((x * x) + (y * y));
}

/**
 * calculate the angle between two coordinates
 * @param {Object} p1
 * @param {Object} p2
 * @param {Array} [props] containing x and y keys
 * @return {Number} angle
 */
function getAngle(p1, p2, props) {
    if (!props) {
        props = PROPS_XY;
    }
    var x = p2[props[0]] - p1[props[0]],
        y = p2[props[1]] - p1[props[1]];
    return Math.atan2(y, x) * 180 / Math.PI;
}

/**
 * calculate the rotation degrees between two pointersets
 * @param {Array} start array of pointers
 * @param {Array} end array of pointers
 * @return {Number} rotation
 */
function getRotation(start, end) {
    return getAngle(end[1], end[0], PROPS_CLIENT_XY) - getAngle(start[1], start[0], PROPS_CLIENT_XY);
}

/**
 * calculate the scale factor between two pointersets
 * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
 * @param {Array} start array of pointers
 * @param {Array} end array of pointers
 * @return {Number} scale
 */
function getScale(start, end) {
    return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY);
}
<|endoftext|>


<commit_before>/* global Utils,Region */

var UI = (function () {
    "use strict";

    var hiddenColumns = [];
    var dataTable;

    /******************************************************************/
    /*                P R I V A T E   F U N C T I O N S               */
    /******************************************************************/

    function initDataTable () {

        var columns = [
            {'title': 'ID'},
            {'title': 'Name'},
            {'title': 'Ram'},
            {'title': 'VCPUs'},
            {'title': 'Disk'},
            {'title': 'Swap'},
            {'title': 'Region'},
            {'title': 'Actions'}
        ];

        dataTable = $('#flavors_table').dataTable({
            'columns': columns,
            "columnDefs": [
                {
                    "targets": hiddenColumns,
                    "visible": false
                }
            ],
            'dom': 't<"navbar navbar-default navbar-fixed-bottom"p>',
            'binfo': false,
            'pagingType': 'full_numbers',
            'info': false,
            "language": {
                "paginate": {
                    "first": '',
                    "last": '',
                    "next": '',
                    "previous": ''
                }
            }
        });
    }

    function createSearchField (nextElement) {

        var search = $('
').addClass('input-group search-container').insertBefore(nextElement);
        var searchButton = $('<button>').addClass('btn btn-default').html('');
        $('').addClass('input-group-btn').append(searchButton).appendTo(search);
        var searchInput = $('<input>').attr('type', 'text').attr('placeholder', 'Search for...').addClass('search form-control').appendTo(search);
        var focusState = false;

        searchButton.on('click', function () {
            focusState = !focusState;

            searchInput.toggleClass('slideRight');
            searchButton.parent()
                .css('z-index', 20);

            if (focusState) {
                searchInput.focus();
            }
            else {
                searchInput.blur();
            }
        });

        searchInput.on( 'keyup', function () {
            dataTable.api().search(this.value).draw();
        });
    }

    function createModalButton (nextElement) {

        $('<button>')
            .html('')
            .addClass('btn btn-success action-button pull-left')
            .attr('data-toggle', 'modal')
            .attr('data-target', '#uploadFlavorModal')
            .insertBefore(nextElement);
    }

    function createRefreshButton (nextElement, refreshCallback) {

        $('<button>')
            .html('')
            .addClass('btn btn-default action-button pull-left')
            .click(refreshCallback.bind(null, false))
            .insertBefore(nextElement);
    }

    function createRegionsButton (nextElement) {
        $('<button>')
            .html('')
            .addClass('btn btn-primary action-button pull-left')
            .click(toggleRegionSelector)
            .insertBefore(nextElement);
    }

    function createRegionSelector () {
        var regions = Region.getAvailableRegions();
        var regionSelector = $('
')
                .attr('id', 'region-selector')
                .addClass('region-selector')
                .css('max-height', window.innerHeight - 50)
                .appendTo($('body'));

        $(window).resize(function () {
            regionSelector.css('max-height', window.innerHeight - 50);
        });

        regions.forEach(function(region) {

            var checked = false;

            $('
')
                .html('<input type="checkbox" name="region" value="' + region + '" /> ' + region)
                .addClass('region-container')
                .click(function (e) {
                    var input = $('input', this);
                    checked = !checked;

                    input.toggleClass('selected');
                    input.prop('checked', checked);

                    Region.setCurrentRegions(regionSelector);
                })
                .appendTo(regionSelector);
        });

        $("div>input[type=checkbox][value=Spain2]").prop("checked", true);
    }

    function toggleRegionSelector () {
        $('#region-selector').toggleClass('slideRight');
    }

    function buildTableBody (flavorList, updateCallback, deleteCallback) {

        var row, flavor, displayableRam, displayableDisk, displayableSwap;

        // Launch button
        var wrapper = $('
');
        getEditButtonHTML(wrapper);
        getDeleteButtonHTML(wrapper);

        // Clear previous elements
        dataTable.api().clear();

        flavorList.forEach(function (flavor) {

            displayableRam = Utils.getDisplayableValue(flavor.ram, "MiB");
            displayableDisk = Utils.getDisplayableValue(flavor.disk, "GiB");
            displayableSwap = Utils.getDisplayableValue(flavor.swap, "MiB");

            row = dataTable.api().row.add([
                flavor.id,
                flavor.name,
                displayableRam,
                flavor.vcpus,
                displayableDisk,
                displayableSwap,
                flavor.region,
                wrapper.html()
            ])
            .draw()
            .nodes()
            .to$();

            if (UI.selectedRowId && flavor.id === UI.selectedRowId) {
                row.addClass('selected');
            }

            setEditEvents(flavor, updateCallback);

        });
    }

    function setEditEvents (flavor, callback) {

        $('button[name=edit-button]').on('click', function () {
            var row = $(this).parent().parent();

            fillEditForm(flavor);
        });

    }

    function setDeleteButtonEvent (callback) {

        $('button[name=delete-button]').on('click', function () {
            var row = $(this).parent().parent();
            var data = dataTable.api().row(row).data();
            callback(data[0], data[data.length - 2]);
        });

    }

    function setSelectFlavorEvents () {

        // Remove previous row click events
        $('#flavors_table tbody').off('click', '**');

        // Row events
        $('#flavors_table tbody').on('click', 'tr', function () {
            var data = dataTable.api().row(this).data();
            var id = data[0];
            var region = data[data.length - 1];
            UI.selectedRowId = id;

            dataTable.api().row('.selected')
                .nodes()
                .to$()
                .removeClass('selected');
            $(this).addClass('selected');
        });
    }

    function initFixedHeader () {

        UI.fixedHeader = new $.fn.dataTable.FixedHeader(dataTable);

        $(window).resize(function () {
            UI.fixedHeader._fnUpdateClones(true); // force redraw
            UI.fixedHeader._fnUpdatePositions();
        });

    }

    function createFormRegionSelector () {

        var availableRegions = Region.getAvailableRegions();
        var currentRegions = Region.getCurrentRegions();
        var regionFormSelector = $('#region');

        availableRegions.forEach(function (region) {
            $('<option>')
                .val(region)
                .text(region)
                .appendTo(regionFormSelector);
        });

        if (currentRegions.length === 1) {
            $('option[value=' + currentRegions[0] + ']').prop('selected', true);
        }

    }

    function getEditButtonHTML (parent) {

        $('<button>')
            .addClass('btn btn-primary')
            .attr('name', 'edit-button')
            .html('')
            .attr('data-toggle', 'modal')
            .attr('data-target', '#updateFlavorModal')
            .appendTo(parent);

    }

    function getDeleteButtonHTML (parent) {

        $('<button>')
            .addClass('btn btn-danger')
            .attr('name', 'delete-button')
            .html('')
            .appendTo(parent);

    }

    function fillEditForm (flavor) {

        $('#update-name').val(flavor.name);
        $('#update-ram').val(flavor.ram);
        $('#update-vcpus').val(flavor.vcpus);
        $('#update-disk').val(flavor.disk);
        $('#update-form-region').val(flavor.region);

    }

    /******************************************************************/
    /*                 P U B L I C   F U N C T I O N S                */
    /******************************************************************/

    function createTable (callbacks) {

        initDataTable();

        // Extra padding to adjust to bottom fixed navbar
        $('#flavors_table_wrapper').attr('style', 'padding-bottom: 40px;');

        // Pagination style
        $('#flavors_table_paginate').addClass('pagination pull-right');

        createRegionSelector();
        createFormRegionSelector();
        createRegionsButton($('#flavors_table_paginate'));
        createModalButton($('#flavors_table_paginate'));
        createSearchField($('#flavors_table_paginate'));
        createRefreshButton($('#flavors_table_paginate'), callbacks.refresh);

        // Set modal create flavor button click
        $('#create-flavor').on('click', callbacks.create);
        $('#update-flavor').on('click', function (e) {
            var form = $('#update_flavor_form')[0];
            var flavor = {};
            flavor.name = form['update-name'].value;
            flavor.ram = form['update-ram'].value;
            flavor.vcpus = form['update-vcpus'].value;
            flavor.disk = form['update-disk'].value;
            flavor.region = form['update-form-region'].value;
            callbacks.update(flavor);
            e.preventDefault();
            $('#updateFlavorModal').modal('hide');
        });

        initFixedHeader();

    }

    function updateHiddenColumns () {

        var display;
        var preferenceList = [
            'id',
            'name',
            'ram',
            'vcpus',
            'disk',
            'swap'
        ];

        hiddenColumns = [];

        preferenceList.forEach(function (preference, index) {

            display = MashupPlatform.prefs.get(preference);

            if (!display) {
                hiddenColumns.push(index);
            }

            if (dataTable) {
                dataTable.api().column(index).visible(display, false);
            }

        });

        // Recalculate all columns size at once
        if (dataTable) {
            dataTable.api().columns.adjust();
        }

    }

    function drawFlavors (callbacks, autoRefresh, flavorList) {

        // Save previous scroll and page
        var scroll = $(window).scrollTop();
        var page = dataTable.api().page();

        buildTableBody(flavorList, callbacks.update);
        setDeleteButtonEvent(callbacks.destroy);
        setSelectFlavorEvents();

        // Restore previous scroll and page
        $(window).scrollTop(scroll);
        dataTable.api().page(page).draw(false);

        if (autoRefresh) {
            setTimeout(function () {
                callbacks.refresh(true);
            }, 4000);
        }
    }

    function startLoadingAnimation (element, icon) {

        var bodyWidth = $('body').width();
        var bodyHeight = $('body').height();

        // Reference size is the smaller between height and width
        var referenceSize = (bodyWidth < bodyHeight) ? bodyWidth : bodyHeight;
        var font_size = referenceSize / 4;

        icon.css('font-size', font_size);
        element.removeClass('hide');

    }

    function stopLoadingAnimation (element) {

        element.addClass('hide');

    }

    return {
        createTable: createTable,
        updateHiddenColumns: updateHiddenColumns,
        drawFlavors: drawFlavors,
        startLoadingAnimation: startLoadingAnimation,
        stopLoadingAnimation: stopLoadingAnimation
    };
})();<commit_msg>Columns headers are now aligned with its content. This closes #12<commit_after>/* global Utils,Region */

var UI = (function () {
    "use strict";

    var hiddenColumns = [];
    var dataTable;

    /******************************************************************/
    /*                P R I V A T E   F U N C T I O N S               */
    /******************************************************************/

    function initDataTable () {

        var columns = [
            {'title': 'ID'},
            {'title': 'Name'},
            {'title': 'Ram'},
            {'title': 'VCPUs'},
            {'title': 'Disk'},
            {'title': 'Swap'},
            {'title': 'Region'},
            {'title': 'Actions'}
        ];

        dataTable = $('#flavors_table').dataTable({
            'columns': columns,
            "columnDefs": [
                {
                    "targets": hiddenColumns,
                    "visible": false
                }
            ],
            'dom': 't<"navbar navbar-default navbar-fixed-bottom"p>',
            'binfo': false,
            'pagingType': 'full_numbers',
            'info': false,
            "language": {
                "paginate": {
                    "first": '',
                    "last": '',
                    "next": '',
                    "previous": ''
                }
            }
        });
    }

    function createSearchField (nextElement) {

        var search = $('
').addClass('input-group search-container').insertBefore(nextElement);
        var searchButton = $('<button>').addClass('btn btn-default').html('');
        $('').addClass('input-group-btn').append(searchButton).appendTo(search);
        var searchInput = $('<input>').attr('type', 'text').attr('placeholder', 'Search for...').addClass('search form-control').appendTo(search);
        var focusState = false;

        searchButton.on('click', function () {
            focusState = !focusState;

            searchInput.toggleClass('slideRight');
            searchButton.parent()
                .css('z-index', 20);

            if (focusState) {
                searchInput.focus();
            }
            else {
                searchInput.blur();
            }
        });

        searchInput.on( 'keyup', function () {
            dataTable.api().search(this.value).draw();
        });
    }

    function createModalButton (nextElement) {

        $('<button>')
            .html('')
            .addClass('btn btn-success action-button pull-left')
            .attr('data-toggle', 'modal')
            .attr('data-target', '#uploadFlavorModal')
            .insertBefore(nextElement);
    }

    function createRefreshButton (nextElement, refreshCallback) {

        $('<button>')
            .html('')
            .addClass('btn btn-default action-button pull-left')
            .click(refreshCallback.bind(null, false))
            .insertBefore(nextElement);
    }

    function createRegionsButton (nextElement) {
        $('<button>')
            .html('')
            .addClass('btn btn-primary action-button pull-left')
            .click(toggleRegionSelector)
            .insertBefore(nextElement);
    }

    function createRegionSelector () {
        var regions = Region.getAvailableRegions();
        var regionSelector = $('
')
                .attr('id', 'region-selector')
                .addClass('region-selector')
                .css('max-height', window.innerHeight - 50)
                .appendTo($('body'));

        $(window).resize(function () {
            regionSelector.css('max-height', window.innerHeight - 50);
        });

        regions.forEach(function(region) {

            var checked = false;

            $('
')
                .html('<input type="checkbox" name="region" value="' + region + '" /> ' + region)
                .addClass('region-container')
                .click(function (e) {
                    var input = $('input', this);
                    checked = !checked;

                    input.toggleClass('selected');
                    input.prop('checked', checked);

                    Region.setCurrentRegions(regionSelector);
                })
                .appendTo(regionSelector);
        });

        $("div>input[type=checkbox][value=Spain2]").prop("checked", true);
    }

    function toggleRegionSelector () {
        $('#region-selector').toggleClass('slideRight');
    }

    function buildTableBody (flavorList, updateCallback, deleteCallback) {

        var row, flavor, displayableRam, displayableDisk, displayableSwap;

        // Launch button
        var wrapper = $('
');
        getEditButtonHTML(wrapper);
        getDeleteButtonHTML(wrapper);

        // Clear previous elements
        dataTable.api().clear();

        flavorList.forEach(function (flavor) {

            displayableRam = Utils.getDisplayableValue(flavor.ram, "MiB");
            displayableDisk = Utils.getDisplayableValue(flavor.disk, "GiB");
            displayableSwap = Utils.getDisplayableValue(flavor.swap, "MiB");

            row = dataTable.api().row.add([
                flavor.id,
                flavor.name,
                displayableRam,
                flavor.vcpus,
                displayableDisk,
                displayableSwap,
                flavor.region,
                wrapper.html()
            ])
            .draw()
            .nodes()
            .to$();

            if (UI.selectedRowId && flavor.id === UI.selectedRowId) {
                row.addClass('selected');
            }

            setEditEvents(flavor, updateCallback);

        });
    }

    function setEditEvents (flavor, callback) {

        $('button[name=edit-button]').on('click', function () {
            var row = $(this).parent().parent();

            fillEditForm(flavor);
        });

    }

    function setDeleteButtonEvent (callback) {

        $('button[name=delete-button]').on('click', function () {
            var row = $(this).parent().parent();
            var data = dataTable.api().row(row).data();
            callback(data[0], data[data.length - 2]);
        });

    }

    function setSelectFlavorEvents () {

        // Remove previous row click events
        $('#flavors_table tbody').off('click', '**');

        // Row events
        $('#flavors_table tbody').on('click', 'tr', function () {
            var data = dataTable.api().row(this).data();
            var id = data[0];
            var region = data[data.length - 1];
            UI.selectedRowId = id;

            dataTable.api().row('.selected')
                .nodes()
                .to$()
                .removeClass('selected');
            $(this).addClass('selected');
        });
    }

    function initFixedHeader () {
        UI.fixedHeader = new $.fn.dataTable.FixedHeader(dataTable);
        $(window).resize(redrawFixedHeaders);
    }

    function redrawFixedHeaders () {
        UI.fixedHeader._fnUpdateClones(true); // force redraw
        UI.fixedHeader._fnUpdatePositions();
    }

    function createFormRegionSelector () {

        var availableRegions = Region.getAvailableRegions();
        var currentRegions = Region.getCurrentRegions();
        var regionFormSelector = $('#region');

        availableRegions.forEach(function (region) {
            $('<option>')
                .val(region)
                .text(region)
                .appendTo(regionFormSelector);
        });

        if (currentRegions.length === 1) {
            $('option[value=' + currentRegions[0] + ']').prop('selected', true);
        }

    }

    function getEditButtonHTML (parent) {

        $('<button>')
            .addClass('btn btn-primary')
            .attr('name', 'edit-button')
            .html('')
            .attr('data-toggle', 'modal')
            .attr('data-target', '#updateFlavorModal')
            .appendTo(parent);

    }

    function getDeleteButtonHTML (parent) {

        $('<button>')
            .addClass('btn btn-danger')
            .attr('name', 'delete-button')
            .html('')
            .appendTo(parent);

    }

    function fillEditForm (flavor) {

        $('#update-name').val(flavor.name);
        $('#update-ram').val(flavor.ram);
        $('#update-vcpus').val(flavor.vcpus);
        $('#update-disk').val(flavor.disk);
        $('#update-form-region').val(flavor.region);

    }

    /******************************************************************/
    /*                 P U B L I C   F U N C T I O N S                */
    /******************************************************************/

    function createTable (callbacks) {

        initDataTable();

        // Extra padding to adjust to bottom fixed navbar
        $('#flavors_table_wrapper').attr('style', 'padding-bottom: 40px;');

        // Pagination style
        $('#flavors_table_paginate').addClass('pagination pull-right');

        createRegionSelector();
        createFormRegionSelector();
        createRegionsButton($('#flavors_table_paginate'));
        createModalButton($('#flavors_table_paginate'));
        createSearchField($('#flavors_table_paginate'));
        createRefreshButton($('#flavors_table_paginate'), callbacks.refresh);

        // Set modal create flavor button click
        $('#create-flavor').on('click', callbacks.create);
        $('#update-flavor').on('click', function (e) {
            var form = $('#update_flavor_form')[0];
            var flavor = {};
            flavor.name = form['update-name'].value;
            flavor.ram = form['update-ram'].value;
            flavor.vcpus = form['update-vcpus'].value;
            flavor.disk = form['update-disk'].value;
            flavor.region = form['update-form-region'].value;
            callbacks.update(flavor);
            e.preventDefault();
            $('#updateFlavorModal').modal('hide');
        });

        initFixedHeader();

    }

    function updateHiddenColumns () {

        var display;
        var preferenceList = [
            'id',
            'name',
            'ram',
            'vcpus',
            'disk',
            'swap'
        ];

        hiddenColumns = [];

        preferenceList.forEach(function (preference, index) {

            display = MashupPlatform.prefs.get(preference);

            if (!display) {
                hiddenColumns.push(index);
            }

            if (dataTable) {
                dataTable.api().column(index).visible(display, false);
            }

        });

        // Recalculate all columns size at once
        if (dataTable) {
            dataTable.api().columns.adjust();
        }

    }

    function drawFlavors (callbacks, autoRefresh, flavorList) {

        // Save previous scroll and page
        var scroll = $(window).scrollTop();
        var page = dataTable.api().page();

        buildTableBody(flavorList, callbacks.update);
        setDeleteButtonEvent(callbacks.destroy);
        setSelectFlavorEvents();

        // Restore previous scroll and page
        $(window).scrollTop(scroll);
        dataTable.api().page(page).draw(false);

        // Adjust columns and headers
        dataTable.api().columns.adjust();
        redrawFixedHeaders();

        if (autoRefresh) {
            setTimeout(function () {
                callbacks.refresh(true);
            }, 4000);
        }
    }

    function startLoadingAnimation (element, icon) {

        var bodyWidth = $('body').width();
        var bodyHeight = $('body').height();

        // Reference size is the smaller between height and width
        var referenceSize = (bodyWidth < bodyHeight) ? bodyWidth : bodyHeight;
        var font_size = referenceSize / 4;

        icon.css('font-size', font_size);
        element.removeClass('hide');

    }

    function stopLoadingAnimation (element) {

        element.addClass('hide');

    }

    return {
        createTable: createTable,
        updateHiddenColumns: updateHiddenColumns,
        drawFlavors: drawFlavors,
        startLoadingAnimation: startLoadingAnimation,
        stopLoadingAnimation: stopLoadingAnimation
    };
})();<|endoftext|>


<commit_before>/**
 * @author Wang, Hui (huiwang@qlike.com)
 * @repo https://github.com/hui-w/interactive-canvas
 * @licence MIT
 *
 * Label
 */

'use strict';

(function() {
  var prototype = {
    onTextChange: null,
    textObject: null,

    init: function(left, top, width, height, text, id) {
      this._super(left, top, width, height, id);

      // When text is changed
      this.onTextChange = new EventHandler();

      // The text boundary with relative position
      this.textObject = null;

      // Extend properties
      var newProperties = {
        fontSize: 12,
        fontFace: 'Arial, Helvetica, sans-serif',
        fontColor: '#000000',
        text: text,
        horizontalAlign: 'left',
        verticalAlign: 'top',
        alignMode: 'boundary' // 'basePoint' | 'boundary'
      };
      this.properties = Object.assign({}, this.properties, newProperties);

      // Register the internal events
      this.onSizeChange.add(function(width, height) {
        this.updateTextObject();
      }.bind(this));
    },

    setProp: function(key, value) {
      this._super(key, value);

      switch (key) {
        case 'horizontalAlign':
          if (this.updatePropValue('horizontalAlign', value)) {
            this.updateTextObject();
            this.requestPaint();
          }
          break;
        case 'verticalAlign':
          if (this.updatePropValue('verticalAlign', value)) {
            this.updateTextObject();
            this.requestPaint();
          }
          break;
        case 'text':
          if (this.updatePropValue('text', value)) {
            this.updateTextObject();
            this.requestPaint();
            this.onTextChange.trigger();
          }
          break;
        case 'fontColor':
          if (this.updatePropValue('fontColor', value)) {
            this.requestPaint();
          }
          break;
        case 'fontSize':
          if (this.updatePropValue('fontSize', value)) {
            this.updateTextObject();
            this.requestPaint();
          }
      }
    },

    getTextObject: function() {
      if (this.textObject == null) {
        this.updateTextObject();
      }

      return this.textObject;
    },

    // To calculate the text boundary
    updateTextObject: function(context) {
      if (!context) {
        // This method may be called ouside of paint without context
        context = this.getContext();

        if (!context) {
          // Still no context as the canvas may not renderred
          return;
        }
      }

      // Parsing lines
      var lines = this.getProp('text').split(/\\n/);
      // console.log(lines);

      context.save();

      // Set the font temporary for mesuring the size
      context.font = this.getProp('fontSize') + 'px ' + this.getProp('fontFace');

      // Calculate size of the boundary
      var textWidth = parseInt(context.measureText(this.getProp('text')).width);
      var textHeight = this.getProp('fontSize');

      // Calculate position of the boundary
      var textLeft = 0,
        textTop = 0;
      if (this.getProp('horizontalAlign') == 'center') {
        textLeft = parseInt(this.width / 2 - textWidth / 2);
      } else if (this.getProp('horizontalAlign') == 'right') {
        textLeft = this.width - textWidth;
      }

      if (this.getProp('verticalAlign') == 'middle') {
        textTop = parseInt(this.height / 2 - textHeight / 2);
      } else if (this.getProp('verticalAlign') == 'bottom') {
        textTop = this.height - textHeight;
      }

      this.textObject = {
        left: textLeft,
        top: textTop,
        width: textWidth,
        height: textHeight
      }

      context.restore();
    },

    paint: function(context) {
      // Prepare to paint
      this.saveContext(context);

      // Base Paint()
      this._super(context, true);

      // Set the font and render the text
      context.font = this.getProp('fontSize') + 'px ' + this.getProp('fontFace');
      context.fillStyle = this.getProp('fontColor');
      context.textBaseline = 'top';
      var b = this.getTextObject();
      context.fillText(this.getProp('text'), b.left, b.top);

      /*
      function wrapText(context, text, x, y, maxWidth, lineHeight) {
        var words = text.split(' ');
        var line = '';

        for(var n = 0; n < words.length; n++) {
          var testLine = line + words[n] + ' ';
          var metrics = context.measureText(testLine);
          var testWidth = metrics.width;
          if (testWidth > maxWidth && n > 0) {
            context.fillText(line, x, y);
            line = words[n] + ' ';
            y += lineHeight;
          }
          else {
            line = testLine;
          }
        }
        context.fillText(line, x, y);
      }
      */

      // Paint completed
      this.restoreContext(context);
    }
  };

  window.Label = Panel.extend(prototype);
})();
<commit_msg>Handle the line breaking in Label<commit_after>/**
 * @author Wang, Hui (huiwang@qlike.com)
 * @repo https://github.com/hui-w/interactive-canvas
 * @licence MIT
 *
 * Label
 */

'use strict';

(function() {
  var prototype = {
    onTextChange: null,
    textObject: null,

    init: function(left, top, width, height, text, id) {
      this._super(left, top, width, height, id);

      // When text is changed
      this.onTextChange = new EventHandler();

      // The text boundary with relative position
      this.textObject = null;

      // Extend properties
      var newProperties = {
        fontSize: 12,
        fontFace: 'Arial, Helvetica, sans-serif',
        fontColor: '#000000',
        text: text,
        horizontalAlign: 'left',
        verticalAlign: 'top',
        alignMode: 'boundary' // 'basePoint' | 'boundary'
      };
      this.properties = Object.assign({}, this.properties, newProperties);

      // Register the internal events
      this.onSizeChange.add(function(width, height) {
        this.updateTextObject();
      }.bind(this));
    },

    setProp: function(key, value) {
      this._super(key, value);

      switch (key) {
        case 'horizontalAlign':
          if (this.updatePropValue('horizontalAlign', value)) {
            this.updateTextObject();
            this.requestPaint();
          }
          break;
        case 'verticalAlign':
          if (this.updatePropValue('verticalAlign', value)) {
            this.updateTextObject();
            this.requestPaint();
          }
          break;
        case 'text':
          if (this.updatePropValue('text', value)) {
            this.updateTextObject();
            this.requestPaint();
            this.onTextChange.trigger();
          }
          break;
        case 'fontColor':
          if (this.updatePropValue('fontColor', value)) {
            this.requestPaint();
          }
          break;
        case 'fontSize':
          if (this.updatePropValue('fontSize', value)) {
            this.updateTextObject();
            this.requestPaint();
          }
      }
    },

    getTextObject: function() {
      if (this.textObject == null) {
        this.updateTextObject();
      }

      return this.textObject;
    },

    // To calculate the text boundary
    updateTextObject: function(context) {
      if (!context) {
        // This method may be called ouside of paint without context
        context = this.getContext();

        if (!context) {
          // Still no context as the canvas may not renderred
          return;
        }
      }

      context.save();

      // Set the font temporary for mesuring the size
      context.font = this.getProp('fontSize') + 'px ' + this.getProp('fontFace');

      // Parsing lines
      var lines = [];
      this.getProp('text').split(/\n/).forEach(function(content) {
        lines.push({
          width: context.measureText(content).width,
          height: this.getProp('fontSize'),
          content: content
        });
      }.bind(this));

      // Calculate size of the boundary
      var textWidth = parseInt(context.measureText(this.getProp('text')).width);
      var textHeight = this.getProp('fontSize');

      // Calculate position of the boundary
      var textLeft = 0,
        textTop = 0;
      if (this.getProp('horizontalAlign') == 'center') {
        textLeft = parseInt(this.width / 2 - textWidth / 2);
      } else if (this.getProp('horizontalAlign') == 'right') {
        textLeft = this.width - textWidth;
      }

      if (this.getProp('verticalAlign') == 'middle') {
        textTop = parseInt(this.height / 2 - textHeight / 2);
      } else if (this.getProp('verticalAlign') == 'bottom') {
        textTop = this.height - textHeight;
      }

      this.textObject = {
        left: textLeft,
        top: textTop,
        width: textWidth,
        height: textHeight,
        lines: lines
      }

      context.restore();
    },

    paint: function(context) {
      // Prepare to paint
      this.saveContext(context);

      // Base Paint()
      this._super(context, true);

      // Set the font and render the text
      context.font = this.getProp('fontSize') + 'px ' + this.getProp('fontFace');
      context.fillStyle = this.getProp('fontColor');
      context.textBaseline = 'top';
      var b = this.getTextObject();
      context.fillText(this.getProp('text'), b.left, b.top);

      /*
      function wrapText(context, text, x, y, maxWidth, lineHeight) {
        var words = text.split(' ');
        var line = '';

        for(var n = 0; n < words.length; n++) {
          var testLine = line + words[n] + ' ';
          var metrics = context.measureText(testLine);
          var testWidth = metrics.width;
          if (testWidth > maxWidth && n > 0) {
            context.fillText(line, x, y);
            line = words[n] + ' ';
            y += lineHeight;
          }
          else {
            line = testLine;
          }
        }
        context.fillText(line, x, y);
      }
      */

      // Paint completed
      this.restoreContext(context);
    }
  };

  window.Label = Panel.extend(prototype);
})();
<|endoftext|>


<commit_before>import DateTime from './datetime';
import Duration from './duration';
import Interval from './interval';
import Info from './info';
import Zone from './zone';
import Settings from './settings';

export { DateTime, Duration, Interval, Info, Zone, Settings };
<commit_msg>Added exposes for specific zones. (#227)<commit_after>import DateTime from './datetime';
import Duration from './duration';
import Interval from './interval';
import Info from './info';
import Zone from './zone';
import FixedOffsetZone from './zones/fixedOffsetZone';
import IANAZone from './zones/IANAZone';
import LocalZone from './zones/localZone';
import Settings from './settings';

export { DateTime, Duration, Interval, Info, Zone, FixedOffsetZone, IANAZone, LocalZone, Settings };
<|endoftext|>