<commit_before>'use strict'

var fs = require('fs')
var EventEmitter = require('events').EventEmitter
var util = require('util')
var async = require('async')
var uuid = require('node-uuid')
var BigNumber = require('bignumber.js')
var R = require('ramda')
var retry = require('retry')

var jsonquest = require('./jsonquest')

var _t0 = null
var sequenceNumber = 0
var pid = uuid.v4()

var Trader = function (config) {
  if (!(this instanceof Trader)) return new Trader(config)
  EventEmitter.call(this)

  this.connectionInfo = null
  this.protocol = config.protocol || 'https'
  this.rejectUnauthorized = typeof config.rejectUnauthorized === 'undefined'
  ? true
  : !!config.rejectUnauthorized

  this.config = config
  this.exchangeRate = null
  this.fiatExchangeRate = null
  this.balance = null
  this.locale = null

  this.exchange = null
  this.balanceTimer = null
  this.balanceRetries = 0
  this.balanceTriggers = null
  this.tickerExchange = null
  this.transferExchange = null
  this.pollTimer = null
  this.pollRetries = 0
  this.txLimit = null
  this.fiatTxLimit = 50  // TODO: make configurable
  this.idVerificationLimit = null
  this.idVerificationEnabled = false
  this.sessionId = null
  this.twoWayMode = false
  this.coins = []
  this.state = null
}
util.inherits(Trader, EventEmitter)

Trader.prototype.init = function init (connectionInfo) {
  var self = this

  if (this.protocol === 'https') {
    this.cert = fs.readFileSync(this.config.certs.certFile)
    this.key = fs.readFileSync(this.config.certs.keyFile)
  }
  this.connectionInfo = connectionInfo

  jsonquest.emitter.on('networkUp', function () { self.emit('networkUp') })
  jsonquest.emitter.on('networkDown', function () { self.emit('networkDown') })
}

Trader.prototype.pair = function pair (connectionInfo) {
  this.connectionInfo = connectionInfo
}

Trader.prototype._request = function _request (options, cb) {
  var protocol = this.protocol || 'https'
  var connectionInfo = this.connectionInfo
  var host = protocol === 'http' ? 'localhost' : connectionInfo.host
  var fingerprint = protocol === 'http' ? false : connectionInfo.fingerprint
  var self = this
  var sessionId = this.sessionId
  var date = new Date().toISOString()
  var headers = sessionId ? {'session-id': sessionId, date: date} : {date: date}
  if (options.body) headers['content-type'] = 'application/json'

  jsonquest({
    protocol: protocol,
    host: host,
    port: connectionInfo.port,
    cert: this.cert,
    key: this.key,
    rejectUnauthorized: this.rejectUnauthorized,
    method: options.method,
    path: options.path,
    body: options.body,
    headers: headers,
    fingerprint: fingerprint,
    repeatUntilSuccess: options.repeatUntilSuccess
  }, function (err, res, body) {
    if (sessionId && sessionId !== self.sessionId) {
      console.log('WARN: received a response from old sessionId: %s, ' +
      'current is: %s', sessionId, self.sessionId)
      return // No need to call handler
    }

    if (err) return cb(_richError(err.message, 'networkDown'))

    // Backwards compatibility
    if (res.statusCode === 404 && options.path === '/state') {
      return cb()
    }

    if (res.statusCode === 404 && options.path !== '/await_dispense') {
      self.connectionInfo = null
      return cb(_richError('Server has unpaired', 'unpair'))
    }

    // All 2xx codes are OK
    if (res.statusCode < 200 || res.statusCode >= 300) {
      var errMsg = body ? ': ' + body.err : ''
      return cb(_richError('Server returned ' + res.statusCode + errMsg))
    }

    var errRec = body.err ? {name: body.errType, message: body.err} : null
    var result = body

    if (errRec) return cb(_richError(errRec.message, errRec.name))
    cb(null, result)
  })
}

Trader.prototype.run = function run () {
  var self = this

  self.trigger()
  self.triggerInterval = setInterval(function () {
    self.trigger()
  }, this.config.settings.pollInterval)
}

Trader.prototype.stop = function stop () {
  if (this.triggerInterval) clearInterval(this.triggerInterval)
}

Trader.prototype.verifyUser = function verifyUser (idRec, cb) {
  console.log(idRec)
  this._request({
    path: '/verify_user',
    method: 'POST',
    body: idRec
  }, cb)
}

Trader.prototype.rates = function rates (cryptoCode) {
  if (this._rates) return this._rates[cryptoCode]
  if (cryptoCode !== 'BTC') throw new Error('No rates record')

  return {
    cashIn: new BigNumber(this.exchangeRate.toFixed(15)),
    cashOut: new BigNumber(this.fiatExchangeRate.toFixed(15))
  }
}

Trader.prototype.verifyTransaction = function verifyTransaction (idRec) {
  console.log(idRec)
  this._request({
    path: '/verify_transaction',
    method: 'POST',
    body: idRec
  }, function (err) {
    if (err) console.log(err)
  })
}

Trader.prototype.reportEvent = function reportEvent (eventType, note) {
  var rec = {
    eventType: eventType,
    note: note,
    deviceTime: Date.now()
  }
  this._request({
    path: '/event',
    method: 'POST',
    body: rec,
    repeatUntilSuccess: true
  }, function (err) {
    if (err) console.log(err)
  })
}

Trader.prototype.sendCoins = function sendCoins (tx, cb) {
  tx.sequenceNumber = ++sequenceNumber

  // For backwards compatibility with lamassu-server@1.0.2
  tx.txId = uuid.v4()

  this._request({
    path: '/send',
    method: 'POST',
    body: tx,
    repeatUntilSuccess: true
  }, function (err, result) {
    if (!err) {
      cb(null, result.txHash)
    } else {
      if (err.name === 'InsufficientFunds') return cb(err)
      if (err.name === 'networkDown') return cb(new Error('sendCoins timeout'))
      return cb(new Error('General server error'))
    }
  })

  sequenceNumber = 0
}

Trader.prototype.trigger = function trigger () {
  var self = this

  // Not paired yet
  if (this.connectionInfo === null) return

  var stateRec = this.state
  self._request({
    path: '/poll?state=' + stateRec.state + '&idle=' + stateRec.isIdle + '&pid=' + pid,
    method: 'GET'
  }, function (err, body) {
    self._pollHandler(err, body)
  })
}

Trader.prototype.trade = function trade (rec, cb) {
  rec.sequenceNumber = ++sequenceNumber
  this._request({
    path: '/trade',
    method: 'POST',
    body: rec,
    repeatUntilSuccess: true
  }, cb)
}

Trader.prototype.stateChange = function stateChange (state, isIdle) {
  this.state = {state: state, isIdle: isIdle}
  if (!this.connectionInfo) return  // Not connected to server yet
  var rec = {state: state, isIdle: isIdle, uuid: uuid.v4()}
  this._request({
    path: '/state',
    method: 'POST',
    body: rec
  }, function () {})
}

Trader.prototype.cashOut = function cashOut (tx, cb) {
  var config = this.config
  var result = null
  var t0 = Date.now()
  var timeOut = config.settings.sendTimeout

  var interval = config.settings.retryInterval
  var self = this

  // for backwards compatibility
  tx.satoshis = tx.cryptoAtoms

  function _cashOut (cb) {
    self._request({
      path: '/cash_out',
      method: 'POST',
      body: tx
    }, function (err, body) {
      if (!err && body) result = body.bitcoinAddress
      if (err || result === null) return setTimeout(cb, interval)
      cb()
    })
  }

  function testResponse () {
    return result !== null || Date.now() - t0 > timeOut
  }

  function handler (err) {
    if (err) return cb(err)
    if (result === null) return cb(new Error('cashOut timeout'))
    cb(null, result)
  }

  async.doUntil(_cashOut, testResponse, handler)
}

Trader.prototype.phoneCode = function phoneCode (number, cb) {
  this._request({
    path: '/phone_code',
    method: 'POST',
    body: {phone: number}
  }, function (err, res) {
    if (err) return cb(err)
    if (res.statusCode === 401) {
      var badNumberErr = new Error('Bad phone number')
      badNumberErr.name = 'BadNumberError'
      return cb(badNumberErr)
    }
    cb(null, res)
  })
}

// This is just for backwards compatibility with Raqia
// Can be taken out after Raqia is decomissioned
Trader.prototype.updatePhoneNoNotify = function updatePhoneNoNotify (tx, cb) {
  this._request({
    path: '/update_phone?notified=true',
    method: 'POST',
    body: tx
  }, function (err, res) {
    if (err) return cb(err)

    if (res.noPhone) {
      var _err = new Error('Unknown phone number')
      _err.name = 'UnknownPhoneNumberError'
      return cb(_err)
    }

    return cb()
  })
}

Trader.prototype.updatePhone = function updatePhone (tx, cb) {
  this._request({
    path: '/update_phone',
    method: 'POST',
    body: tx
  }, function (err, res) {
    if (err) return cb(err)
    return cb()
  })
}

Trader.prototype.fetchPhoneTx = function fetchPhoneTx (phone, cb) {
  this._request({
    path: '/phone_tx?phone=' + encodeURIComponent(phone),
    method: 'GET'
  }, function (err, res) {
    if (err) return cb(err)

    if (res.pending) return cb(null, {})

    if (!res.tx) {
      var _err = new Error('Unknown phone number')
      _err.name = 'UnknownPhoneNumberError'
      return cb(_err)
    }

    var tx = res.tx
    tx.cryptoAtoms = new BigNumber(tx.cryptoAtoms)

    return cb(null, {tx: tx})
  })
}

Trader.prototype.waitForDispense = function waitForDispense (status, cb) {
  var self = this

  var notSeenError = new Error('Not seen')
  var operation = retry.operation({
    factor: 1,
    minTimeout: 2000,
    retries: 60
  })

  operation.attempt(function () {
    self._request({
      path: '/await_dispense?status=' + status,
      method: 'GET',
      repeatUntilSuccess: false
    }, function (err, res) {
      if (!err && res.statusCode && res.statusCode !== 200) err = notSeenError

      if (operation.retry(err)) return
      if (err) return cb(operation.mainError())

      var tx = res.tx
      tx.cryptoAtoms = new BigNumber(tx.cryptoAtoms)
      return cb(null, tx)
    })
  })
}

Trader.prototype.registerRedeem = function registerRedeem () {
  this._request({
    path: '/register_redeem',
    method: 'POST',
    repeatUntilSuccess: true
  }, function (err) {
    if (err) return console.log(err)
  })
}

Trader.prototype.dispense = function dispense (tx, cb) {
  this._request({
    path: '/dispense',
    method: 'POST',
    body: {tx: tx}
  }, function (err) {
    if (err) return cb(err)
    return cb()
  })
}

// TODO: repeat until success
Trader.prototype.dispenseAck = function dispenseAck (tx, cartridges) {
  this._request({
    path: '/dispense_ack',
    method: 'POST',
    body: {tx: tx, cartridges: cartridges}
  }, function (err) {
    if (err) console.log(err)
  })
}

Trader.prototype._pollHandler = function _pollHandler (err, res) {
  if (err && err.name === 'networkDown') {
    if (_t0 === null) {
      _t0 = Date.now()
      return
    }

    if (Date.now() - _t0 > this.config.settings.pollTimeout) {
      _t0 = null
      this.emit('networkDown')
      return
    }
  }

  if (err && err.name === 'unpair') {
    this.emit('unpair')
    return
  }

  _t0 = null

  // Not a network error, so no need to keep trying
  if (err) {
    if (sequenceNumber === 0) this.emit('networkDown')

    return
  }

  this.txLimit = res.txLimit
  this.idVerificationLimit = res.idVerificationLimit
  this.idVerificationEnabled = false && res.idVerificationEnabled
  this.exchangeRate = res.rate
  this.fiatExchangeRate = res.fiatRate
  this.balance = res.fiat
  this.locale = res.locale
  if (res.cartridges) {
    this.cartridges = res.cartridges.cartridges
    this.virtualCartridges = res.cartridges.virtualCartridges.map(toInt)
    this.cartridgesUpdateId = res.cartridges.id
  }
  this.twoWayMode = res.twoWayMode
  this.fiatTxLimit = res.fiatTxLimit
  this.zeroConfLimit = res.zeroConfLimit
  this._rates = res.rates
  this.balances = res.balances
  this.coins = filterCoins(res)

  if (this.coins.length === 0) {
    console.log('No responsive coins, going to Network Down.')
    return this.emit('networkDown')
  }

  if (res.reboot) this.emit('reboot')
  this.emit('pollUpdate')
  this.emit('networkUp')
}

function filterCoins (res) {
  var coins = res.coins || ['BTC']
  return coins.filter(function (coin) {
    return !R.isNil(res.rates[coin]) && !R.isNil(res.balances[coin])
  })
}

function toInt (str) {
  return parseInt(str, 10)
}

function _richError (errMessage, name) {
  var err = new Error(errMessage)
  err.name = name
  return err
}

module.exports = Trader
<commit_msg>fix potential double dispense bug<commit_after>'use strict'

var fs = require('fs')
var EventEmitter = require('events').EventEmitter
var util = require('util')
var async = require('async')
var uuid = require('node-uuid')
var BigNumber = require('bignumber.js')
var R = require('ramda')
var retry = require('retry')

var jsonquest = require('./jsonquest')

var _t0 = null
var sequenceNumber = 0
var pid = uuid.v4()

var Trader = function (config) {
  if (!(this instanceof Trader)) return new Trader(config)
  EventEmitter.call(this)

  this.connectionInfo = null
  this.protocol = config.protocol || 'https'
  this.rejectUnauthorized = typeof config.rejectUnauthorized === 'undefined'
  ? true
  : !!config.rejectUnauthorized

  this.config = config
  this.exchangeRate = null
  this.fiatExchangeRate = null
  this.balance = null
  this.locale = null

  this.exchange = null
  this.balanceTimer = null
  this.balanceRetries = 0
  this.balanceTriggers = null
  this.tickerExchange = null
  this.transferExchange = null
  this.pollTimer = null
  this.pollRetries = 0
  this.txLimit = null
  this.fiatTxLimit = 50  // TODO: make configurable
  this.idVerificationLimit = null
  this.idVerificationEnabled = false
  this.sessionId = null
  this.twoWayMode = false
  this.coins = []
  this.state = null
}
util.inherits(Trader, EventEmitter)

Trader.prototype.init = function init (connectionInfo) {
  var self = this

  if (this.protocol === 'https') {
    this.cert = fs.readFileSync(this.config.certs.certFile)
    this.key = fs.readFileSync(this.config.certs.keyFile)
  }
  this.connectionInfo = connectionInfo

  jsonquest.emitter.on('networkUp', function () { self.emit('networkUp') })
  jsonquest.emitter.on('networkDown', function () { self.emit('networkDown') })
}

Trader.prototype.pair = function pair (connectionInfo) {
  this.connectionInfo = connectionInfo
}

Trader.prototype._request = function _request (options, cb) {
  var protocol = this.protocol || 'https'
  var connectionInfo = this.connectionInfo
  var host = protocol === 'http' ? 'localhost' : connectionInfo.host
  var fingerprint = protocol === 'http' ? false : connectionInfo.fingerprint
  var self = this
  var sessionId = this.sessionId
  var date = new Date().toISOString()
  var headers = sessionId ? {'session-id': sessionId, date: date} : {date: date}
  if (options.body) headers['content-type'] = 'application/json'

  jsonquest({
    protocol: protocol,
    host: host,
    port: connectionInfo.port,
    cert: this.cert,
    key: this.key,
    rejectUnauthorized: this.rejectUnauthorized,
    method: options.method,
    path: options.path,
    body: options.body,
    headers: headers,
    fingerprint: fingerprint,
    repeatUntilSuccess: options.repeatUntilSuccess
  }, function (err, res, body) {
    if (sessionId && sessionId !== self.sessionId) {
      console.log('WARN: received a response from old sessionId: %s, ' +
      'current is: %s', sessionId, self.sessionId)
      return // No need to call handler
    }

    if (err) return cb(_richError(err.message, 'networkDown'))

    // Backwards compatibility
    if (res.statusCode === 404 && options.path === '/state') {
      return cb()
    }

    if (res.statusCode === 404 && options.path !== '/await_dispense') {
      self.connectionInfo = null
      return cb(_richError('Server has unpaired', 'unpair'))
    }

    // All 2xx codes are OK
    if (res.statusCode < 200 || res.statusCode >= 300) {
      var errMsg = body ? ': ' + body.err : ''
      return cb(_richError('Server returned ' + res.statusCode + errMsg))
    }

    var errRec = body.err ? {name: body.errType, message: body.err} : null
    var result = body

    if (errRec) return cb(_richError(errRec.message, errRec.name))
    cb(null, result)
  })
}

Trader.prototype.run = function run () {
  var self = this

  self.trigger()
  self.triggerInterval = setInterval(function () {
    self.trigger()
  }, this.config.settings.pollInterval)
}

Trader.prototype.stop = function stop () {
  if (this.triggerInterval) clearInterval(this.triggerInterval)
}

Trader.prototype.verifyUser = function verifyUser (idRec, cb) {
  console.log(idRec)
  this._request({
    path: '/verify_user',
    method: 'POST',
    body: idRec
  }, cb)
}

Trader.prototype.rates = function rates (cryptoCode) {
  if (this._rates) return this._rates[cryptoCode]
  if (cryptoCode !== 'BTC') throw new Error('No rates record')

  return {
    cashIn: new BigNumber(this.exchangeRate.toFixed(15)),
    cashOut: new BigNumber(this.fiatExchangeRate.toFixed(15))
  }
}

Trader.prototype.verifyTransaction = function verifyTransaction (idRec) {
  console.log(idRec)
  this._request({
    path: '/verify_transaction',
    method: 'POST',
    body: idRec
  }, function (err) {
    if (err) console.log(err)
  })
}

Trader.prototype.reportEvent = function reportEvent (eventType, note) {
  var rec = {
    eventType: eventType,
    note: note,
    deviceTime: Date.now()
  }
  this._request({
    path: '/event',
    method: 'POST',
    body: rec,
    repeatUntilSuccess: true
  }, function (err) {
    if (err) console.log(err)
  })
}

Trader.prototype.sendCoins = function sendCoins (tx, cb) {
  tx.sequenceNumber = ++sequenceNumber

  // For backwards compatibility with lamassu-server@1.0.2
  tx.txId = uuid.v4()

  this._request({
    path: '/send',
    method: 'POST',
    body: tx,
    repeatUntilSuccess: true
  }, function (err, result) {
    if (!err) {
      cb(null, result.txHash)
    } else {
      if (err.name === 'InsufficientFunds') return cb(err)
      if (err.name === 'networkDown') return cb(new Error('sendCoins timeout'))
      return cb(new Error('General server error'))
    }
  })

  sequenceNumber = 0
}

Trader.prototype.trigger = function trigger () {
  var self = this

  // Not paired yet
  if (this.connectionInfo === null) return

  var stateRec = this.state
  self._request({
    path: '/poll?state=' + stateRec.state + '&idle=' + stateRec.isIdle + '&pid=' + pid,
    method: 'GET'
  }, function (err, body) {
    self._pollHandler(err, body)
  })
}

Trader.prototype.trade = function trade (rec, cb) {
  rec.sequenceNumber = ++sequenceNumber
  this._request({
    path: '/trade',
    method: 'POST',
    body: rec,
    repeatUntilSuccess: true
  }, cb)
}

Trader.prototype.stateChange = function stateChange (state, isIdle) {
  this.state = {state: state, isIdle: isIdle}
  if (!this.connectionInfo) return  // Not connected to server yet
  var rec = {state: state, isIdle: isIdle, uuid: uuid.v4()}
  this._request({
    path: '/state',
    method: 'POST',
    body: rec
  }, function () {})
}

Trader.prototype.cashOut = function cashOut (tx, cb) {
  var config = this.config
  var result = null
  var t0 = Date.now()
  var timeOut = config.settings.sendTimeout

  var interval = config.settings.retryInterval
  var self = this

  // for backwards compatibility
  tx.satoshis = tx.cryptoAtoms

  function _cashOut (cb) {
    self._request({
      path: '/cash_out',
      method: 'POST',
      body: tx
    }, function (err, body) {
      if (!err && body) result = body.bitcoinAddress
      if (err || result === null) return setTimeout(cb, interval)
      cb()
    })
  }

  function testResponse () {
    return result !== null || Date.now() - t0 > timeOut
  }

  function handler (err) {
    if (err) return cb(err)
    if (result === null) return cb(new Error('cashOut timeout'))
    cb(null, result)
  }

  async.doUntil(_cashOut, testResponse, handler)
}

Trader.prototype.phoneCode = function phoneCode (number, cb) {
  this._request({
    path: '/phone_code',
    method: 'POST',
    body: {phone: number}
  }, function (err, res) {
    if (err) return cb(err)
    if (res.statusCode === 401) {
      var badNumberErr = new Error('Bad phone number')
      badNumberErr.name = 'BadNumberError'
      return cb(badNumberErr)
    }
    cb(null, res)
  })
}

// This is just for backwards compatibility with Raqia
// Can be taken out after Raqia is decomissioned
Trader.prototype.updatePhoneNoNotify = function updatePhoneNoNotify (tx, cb) {
  this._request({
    path: '/update_phone?notified=true',
    method: 'POST',
    body: tx
  }, function (err, res) {
    if (err) return cb(err)

    if (res.noPhone) {
      var _err = new Error('Unknown phone number')
      _err.name = 'UnknownPhoneNumberError'
      return cb(_err)
    }

    return cb()
  })
}

Trader.prototype.updatePhone = function updatePhone (tx, cb) {
  this._request({
    path: '/update_phone',
    method: 'POST',
    body: tx
  }, function (err, res) {
    if (err) return cb(err)
    return cb()
  })
}

Trader.prototype.fetchPhoneTx = function fetchPhoneTx (phone, cb) {
  this._request({
    path: '/phone_tx?phone=' + encodeURIComponent(phone),
    method: 'GET'
  }, function (err, res) {
    if (err) return cb(err)

    if (res.pending) return cb(null, {})

    if (!res.tx) {
      var _err = new Error('Unknown phone number')
      _err.name = 'UnknownPhoneNumberError'
      return cb(_err)
    }

    var tx = res.tx
    tx.cryptoAtoms = new BigNumber(tx.cryptoAtoms)

    return cb(null, {tx: tx})
  })
}

Trader.prototype.waitForDispense = function waitForDispense (status, cb) {
  var self = this

  var notSeenError = new Error('Not seen')
  var operation = retry.operation({
    factor: 1,
    minTimeout: 2000,
    retries: 60
  })

  operation.attempt(function () {
    self._request({
      path: '/await_dispense?status=' + status,
      method: 'GET',
      repeatUntilSuccess: false
    }, function (err, res) {
      if (!err && res.statusCode && res.statusCode !== 200) err = notSeenError

      if (operation.retry(err)) return
      if (err) return cb(operation.mainError())

      var tx = res.tx
      tx.cryptoAtoms = new BigNumber(tx.cryptoAtoms)
      return cb(null, tx)
    })
  })
}

Trader.prototype.registerRedeem = function registerRedeem () {
  this._request({
    path: '/register_redeem',
    method: 'POST',
    repeatUntilSuccess: true
  }, function (err) {
    if (err) return console.log(err)
  })
}

Trader.prototype.dispense = function dispense (tx, cb) {
  this._request({
    path: '/dispense',
    method: 'POST',
    body: {tx: tx}
  }, function (err, res) {
    if (err) return cb(err)
    if (!res.dispense) return cb(new Error('Could not dispense: ' + res.reason))
    return cb()
  })
}

// TODO: repeat until success
Trader.prototype.dispenseAck = function dispenseAck (tx, cartridges) {
  this._request({
    path: '/dispense_ack',
    method: 'POST',
    body: {tx: tx, cartridges: cartridges}
  }, function (err) {
    if (err) console.log(err)
  })
}

Trader.prototype._pollHandler = function _pollHandler (err, res) {
  if (err && err.name === 'networkDown') {
    if (_t0 === null) {
      _t0 = Date.now()
      return
    }

    if (Date.now() - _t0 > this.config.settings.pollTimeout) {
      _t0 = null
      this.emit('networkDown')
      return
    }
  }

  if (err && err.name === 'unpair') {
    this.emit('unpair')
    return
  }

  _t0 = null

  // Not a network error, so no need to keep trying
  if (err) {
    if (sequenceNumber === 0) this.emit('networkDown')

    return
  }

  this.txLimit = res.txLimit
  this.idVerificationLimit = res.idVerificationLimit
  this.idVerificationEnabled = false && res.idVerificationEnabled
  this.exchangeRate = res.rate
  this.fiatExchangeRate = res.fiatRate
  this.balance = res.fiat
  this.locale = res.locale
  if (res.cartridges) {
    this.cartridges = res.cartridges.cartridges
    this.virtualCartridges = res.cartridges.virtualCartridges.map(toInt)
    this.cartridgesUpdateId = res.cartridges.id
  }
  this.twoWayMode = res.twoWayMode
  this.fiatTxLimit = res.fiatTxLimit
  this.zeroConfLimit = res.zeroConfLimit
  this._rates = res.rates
  this.balances = res.balances
  this.coins = filterCoins(res)

  if (this.coins.length === 0) {
    console.log('No responsive coins, going to Network Down.')
    return this.emit('networkDown')
  }

  if (res.reboot) this.emit('reboot')
  this.emit('pollUpdate')
  this.emit('networkUp')
}

function filterCoins (res) {
  var coins = res.coins || ['BTC']
  return coins.filter(function (coin) {
    return !R.isNil(res.rates[coin]) && !R.isNil(res.balances[coin])
  })
}

function toInt (str) {
  return parseInt(str, 10)
}

function _richError (errMessage, name) {
  var err = new Error(errMessage)
  err.name = name
  return err
}

module.exports = Trader
<|endoftext|>


<commit_before>import React from 'react';
const ReactDOM = require('react-dom');
let id = 0;

class Radio extends React.PureComponent {
  constructor(props) {
    super(props);
    this.onChange = this.onChange.bind(this);
    this.id = id++;
  }

  onChange(e) {
    this.props.updateProps({ value: e.target.value });
  }

  render() {
    return (

        {this.props.options.map((d) => {
          if (typeof d === 'string') {
            return <input type="radio" checked={d === this.props.value} onChange={this.onChange} value={d} name={this.id} />{d};
          }
          return <input type="radio" checked={d.value === this.props.value} onChange={this.onChange} value={d.value} name={this.id} />{d.label || d.value};
        })}

    );
  }
}

Radio.defaultProps = {
  options: []
};

Radio._idyll = {
  name: "Radio",
  tagType: "closed",
  props: [{
    name: "value",
    type: "string",
    example: "x"
  }, {
    name: "options",
    type: "array",
    example: '`["option1", "option2"]`'
  }]
}

export default Radio;
<commit_msg>fix radio component warning #423<commit_after>import React from 'react';
const ReactDOM = require('react-dom');
let id = 0;

class Radio extends React.PureComponent {
  constructor(props) {
    super(props);
    this.onChange = this.onChange.bind(this);
    this.id = id++;
  }

  onChange(e) {
    this.props.updateProps({ value: e.target.value });
  }

  render() {
    const { idyll, hasError, updateProps, options, value, ...props } = this.props;

    return (

        {options.map((d) => {
          if (typeof d === 'string') {
            return <input type="radio" checked={d === value} onChange={this.onChange} value={d} name={this.id} />{d};
          }
          return <input type="radio" checked={d.value === value} onChange={this.onChange} value={d.value} name={this.id} />{d.label || d.value};
        })}

    );
  }
}

Radio.defaultProps = {
  options: []
};

Radio._idyll = {
  name: "Radio",
  tagType: "closed",
  props: [{
    name: "value",
    type: "string",
    example: "x"
  }, {
    name: "options",
    type: "array",
    example: '`["option1", "option2"]`'
  }]
}

export default Radio;
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////////////////////////
// Grunt config customisations
function gruntAliases(options) {
	const aliases = {
		lint: {
			description: 'Lint files in the project.',
			tasks: [
				'eslint'
			]
		}
	};

	if (options.nodeServer) {
		aliases.serve = {
			description: 'Start server and watch for file changes',
			tasks: [
				'express',
				'watch'
			]
		};

		aliases['build:server'] = {
			description: 'Build task for server files',
			tasks: [
				'eslint:server',
				'uglify:server',
				'sync:server'
			]
		};

		if (options.polymerApp) {
			aliases['build:bower'] = {
				description: 'Build task for bower components',
				tasks: [
					'minifyPolymer:bower',
					'minifyPolymerCSS:bower',
					'uglify:bower'
				]
			}
		}
	}

	return aliases;
}

function gruntEslint(options) {
	const eslint = {
		options: {
			format: 'node_modules/eslint-formatter-pretty'
		},
		project: {
			files: [
				{
					expand: true,
					src: [
						'gruntfile.js',
						'grunt/*.js'
					]
				}
			]
		}
	};

	if (options.nodeServer) {
		eslint.server = {
			files: 'server/**/*.js'
		};
	}

	return eslint;
}

function gruntExpress(options) {
	const express = {};

	if (options.nodeServer) {
		express.all = {
			options: {
				script: 'build/server/start.js'
			}
		};
	}

	return express;
}

function gruntSync(options) {
	const sync = {};

	if (options.nodeServer) {
		sync.server = {
			files: {
				'build/.env': '.env'
			}
		};
	}

	return sync;
}

function gruntUglify(options) {
	const uglify = {};

	if (options.nodeServer) {
		uglify.server = {
			files: [
				{
					expand: true,
					cwd: 'server/',
					src: ['**/*.js'],
					dest: 'build/server/'
				}
			]
		};

		if (options.polymerApp) {
			uglify.bower = {
				files: [
					{
						expand: true,
						cwd: 'public/bower_components/',
						src: [
							'**/*.js',
							'!**/*.min.js',
							'!**/{grunt,gulp}file.js',
							'!**/{demo,demos,docs,explainer,node_modules,test,tests}/**/*'
						],
						dest: 'build/public/bower_components/'
					}
				]
			}
		}
	}

	return uglify;
}

function gruntWatch(options) {
	const watch = {};

	if (options.nodeServer) {
		watch.options = {
			spawn: false,
			interrupt: true
		};

		watch.server = {
			options: {
				reload: true
			},
			files: [
				'gruntfile.js',
				'grunt/*.js',
				'server/**/*.js'
			],
			tasks: [
				'express:stop',
				'eslint:server',
				'build:server',
				'express'
			]
		};

		if (options.polymerApp) {
			watch.bower = {
				files: ['bower.json'],
				tasks: ['build:bower']
			}
		}
	}

	return watch;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// Initialisation and preparation for writing
function prepareConfigs(options) {
	const grunt = {};

	// App
	grunt.aliases = gruntAliases(options);
	grunt.eslint = gruntEslint(options);

	// Node Server
	grunt.express = gruntExpress(options);
	grunt.sync = gruntSync(options);
	grunt.uglify = gruntUglify(options);
	grunt.watch = gruntWatch(options);

	return grunt;
}

function stringifyConfigs(configs) {
	const stringifiedConfigs = [];
	const keys = Object.keys(configs);

	keys.map((key) => {
		if (Object.keys(configs[key]).length !== 0) {
			stringifiedConfigs.push({
				file: `grunt/${key}.js`,
				content: `module.exports = ${JSON.stringify(configs[key], null, '\t')};`
			});
		}
	});

	return stringifiedConfigs;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// Exports
exports.prepareConfigs = prepareConfigs;
exports.stringifyConfigs = stringifyConfigs;
<commit_msg>Template minifyPolymer tasks.<commit_after>///////////////////////////////////////////////////////////////////////////////////////////////////
// Grunt config customisations
function gruntAliases(options) {
	const aliases = {
		lint: {
			description: 'Lint files in the project.',
			tasks: [
				'eslint'
			]
		}
	};

	if (options.nodeServer) {
		aliases.serve = {
			description: 'Start server and watch for file changes',
			tasks: [
				'express',
				'watch'
			]
		};

		aliases['build:server'] = {
			description: 'Build task for server files',
			tasks: [
				'eslint:server',
				'uglify:server',
				'sync:server'
			]
		};

		if (options.polymerApp) {
			aliases['build:bower'] = {
				description: 'Build task for bower components',
				tasks: [
					'minifyPolymer:bower',
					'minifyPolymerCSS:bower',
					'uglify:bower'
				]
			}
		}
	}

	return aliases;
}

function gruntEslint(options) {
	const eslint = {
		options: {
			format: 'node_modules/eslint-formatter-pretty'
		},
		project: {
			files: [
				{
					expand: true,
					src: [
						'gruntfile.js',
						'grunt/*.js'
					]
				}
			]
		}
	};

	if (options.nodeServer) {
		eslint.server = {
			files: 'server/**/*.js'
		};
	}

	return eslint;
}

function gruntExpress(options) {
	const express = {};

	if (options.nodeServer) {
		express.all = {
			options: {
				script: 'build/server/start.js'
			}
		};
	}

	return express;
}

function gruntSync(options) {
	const sync = {};

	if (options.nodeServer) {
		sync.server = {
			files: {
				'build/.env': '.env'
			}
		};
	}

	return sync;
}

function gruntUglify(options) {
	const uglify = {};

	if (options.nodeServer) {
		uglify.server = {
			files: [
				{
					expand: true,
					cwd: 'server/',
					src: ['**/*.js'],
					dest: 'build/server/'
				}
			]
		};

		if (options.polymerApp) {
			uglify.bower = {
				files: [
					{
						expand: true,
						cwd: 'public/bower_components/',
						src: [
							'**/*.js',
							'!**/*.min.js',
							'!**/{grunt,gulp}file.js',
							'!**/{demo,demos,docs,explainer,node_modules,test,tests}/**/*'
						],
						dest: 'build/public/bower_components/'
					}
				]
			}
		}
	}

	return uglify;
}

function gruntWatch(options) {
	const watch = {};

	if (options.nodeServer) {
		watch.options = {
			spawn: false,
			interrupt: true
		};

		watch.server = {
			options: {
				reload: true
			},
			files: [
				'gruntfile.js',
				'grunt/*.js',
				'server/**/*.js'
			],
			tasks: [
				'express:stop',
				'eslint:server',
				'build:server',
				'express'
			]
		};

		if (options.polymerApp) {
			watch.bower = {
				files: ['bower.json'],
				tasks: ['build:bower']
			}
		}
	}

	return watch;
}

function gruntMinifyPolymer(options) {
	const minifyPolymer = {};

	if (options.polymerApp) {
		minifyPolymer.bower = {
			files: [
				{
					expand: true,
					cwd: 'public/bower_components/',
					src: [
						'**/*.html',
						'!**/{index,demo}.html',
						'!**/{demo,demos,docs,explainer,node_modules,test,tests}/**/*'
					],
					dest: 'build/public/bower_components/'
				}
			]
		};
	}

	return minifyPolymer;
}

function gruntMinifyPolymerCss(options) {
	const minifyPolymerCss = {};

	if (options.polymerApp) {
		minifyPolymerCss.bower = {
			files: [
				{
					expand: true,
					cwd: 'public/bower_components/',
					src: [
						'**/*.css',
						'!**/{index,demo}.css',
						'!**/{demo,demos,docs,explainer,node_modules,test,tests}/**/*'
					],
					dest: 'build/public/bower_components/'
				}
			]
		};
	}

	return minifyPolymer;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Initialisation and preparation for writing
function prepareConfigs(options) {
	const grunt = {};

	// App
	grunt.aliases = gruntAliases(options);
	grunt.eslint = gruntEslint(options);

	// Node Server
	grunt.express = gruntExpress(options);
	grunt.sync = gruntSync(options);
	grunt.uglify = gruntUglify(options);
	grunt.watch = gruntWatch(options);

	// Polymer App
	grunt.minifyPolymer = gruntMinifyPolymer(options);
	grunt.minifyPolymerCss = gruntMinifyPolymerCss(options);

	return grunt;
}

function stringifyConfigs(configs) {
	const stringifiedConfigs = [];
	const keys = Object.keys(configs);

	keys.map((key) => {
		if (Object.keys(configs[key]).length !== 0) {
			stringifiedConfigs.push({
				file: `grunt/${key}.js`,
				content: `module.exports = ${JSON.stringify(configs[key], null, '\t')};`
			});
		}
	});

	return stringifiedConfigs;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// Exports
exports.prepareConfigs = prepareConfigs;
exports.stringifyConfigs = stringifyConfigs;
<|endoftext|>


<commit_before>/// <binding />
"use strict";
const webpack = require("webpack");
const path = require("path");
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

module.exports = {
    mode: 'development',
    entry: {
        OpenSEE: "./Scripts/TSX/OpenSEE/openSEE.tsx",
        PQDashboard: "./Scripts/TSX/PQDashboard/PQDashboard.tsx",

    },
    output: {
        path: path.resolve(__dirname, 'Scripts'),
        filename: "[name].js"
    },
    // Enable sourcemaps for debugging webpack's output.
    devtool: "source-map",

    resolve: {
        // Add '.ts' and '.tsx' as resolvable extensions.
        extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js", ".css"]
    },
    module: {
        rules: [
            // All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'.
            { test: /\.tsx?$/, loader: "ts-loader" },
            {
                test: /\.css$/,
                loaders: ['style-loader', 'css-loader'],
            },
            {
                test: /\.js$/,
                enforce: "pre",
                loader: "source-map-loader"
            },
            { test: /\.(woff|woff2|ttf|eot|svg|png|gif)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=100000" }
        ]
    },
    plugins: [
        new webpack.ProvidePlugin({
            $: 'jquery',
            jQuery: 'jquery',
            'window.jQuery':'jquery',
            Map: 'core-js/es6/map',
            Set: 'core-js/es6/set',
            requestAnimationFrame: 'raf',
            cancelAnimationFrame: ['raf', 'cancel'],
        }),
        new webpack.DefinePlugin({
            'process.env.NODE_ENV': JSON.stringify('production')
        }),
    ]
};<commit_msg>Moved developement webpack code to regular config file, since we only tend to use one.<commit_after>/// <binding ProjectOpened='Watch - Development' />
"use strict";
const webpack = require("webpack");
const path = require("path");

module.exports = {
    mode: 'development',
    context: path.resolve(__dirname, 'Scripts'),
    cache: true,
    entry: {
        OpenSEE: "./TSX/OpenSEE/openSEE.tsx",
        PQDashboard: "./TSX/PQDashboard/PQDashboard.tsx",

    },
    output: {
        path: path.resolve(__dirname, 'Scripts'),
        filename: "[name].js"
    },
    // Enable sourcemaps for debugging webpack's output.
    devtool: "inline-source-map",

    resolve: {
        // Add '.ts' and '.tsx' as resolvable extensions.
        extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js", ".css"]
    },
    module: {
        rules: [
            // All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'.
            { test: /\.tsx?$/, loader: "ts-loader" },
            {
                test: /\.css$/,
                loaders: ['style-loader', 'css-loader'],
            },
            {
                test: /\.js$/,
                enforce: "pre",
                loader: "source-map-loader"
            },
            { test: /\.(woff|woff2|ttf|eot|svg|png|gif)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=100000" }
        ]
    },
    externals: {
        jquery: 'jQuery',
        react: 'React',
        'react-dom': 'ReactDOM',
        moment: 'moment'

    },
    plugins: [
        new webpack.ProvidePlugin({
            //$: 'jquery',
            //jQuery: 'jquery',
            //'window.jQuery':'jquery',
            //Map: 'core-js/es/map',
            //Set: 'core-js/es/set',
            //requestAnimationFrame: 'raf',
            //cancelAnimationFrame: ['raf', 'cancel'],
        }),
    ]
};<|endoftext|>


<commit_before>/*
==================================================================================================
  Core - JavaScript Foundation
  Copyright 2012-2013 Sebastian Werner
==================================================================================================
*/

"use strict";

(function(global, slice)
{
  var bind = function(func, context)
  {
    // Inspired by: http://webreflection.blogspot.de/2012/11/my-name-is-bound-method-bound.html

    if (jasy.Env.isSet("debug"))
    {
      core.Assert.isType(func, "Function");
      core.Assert.isType(context, "Object");
    }

    // Using name which is not common to store these references in their objects
    // Storing it on the object has the benefit that when the object is
    // garbage collected its bound methods are gone as well.
    var boundName = "bound:" + core.util.Id.get(func);

    return context[boundName] || (
      context[boundName] = func.bind(context)
    );
  };

  var createDelayed = function(nativeMethod)
  {
    return function(callback, context, delay)
    {
      if (jasy.Env.isSet("debug"))
      {
        core.Assert.isType(callback, "Function");
        if (context) {
          core.Assert.isType(context, "Object");
        }
        core.Assert.isType(delay, "Integer");
      }

      if (arguments.length > 3)
      {
        if (!context) {
          context = global;
        }

        var callbackArgs = slice.call(arguments, 3);

        return nativeMethod(function() {
          callback.apply(context, callbackArgs);
        }, delay);
      }
      else
      {
        if (context) {
          callback = bind(callback, context);
        }

        return nativeMethod(callback, delay);
      }
    };
  };

  var immediate;

  // Keep in mind IE10 bugs:
  // http://codeforhire.com/2013/09/21/setimmediate-and-messagechannel-broken-on-internet-explorer-10/

  // Try NodeJS style nextTick() API
  // http://howtonode.org/understanding-process-next-tick
  if (global.process && process.nextTick)
  {
    immediate = process.nextTick;
  }
  else
  {
    // Try experimental setImmediate() API
    // https://developer.mozilla.org/en-US/docs/DOM/window.setImmediate
    immediate = core.util.Experimental.get(global, "setImmediate");

    if (immediate)
    {
      immediate = global[immediate];
    }
    else
    {
      // Last fallback: Timeout
      immediate = function(func) {
        return setTimeout(func, 0);
      };
    }
  }

  /**
   * A collection of utility methods for native JavaScript functions.
   */
  core.Module("core.Function",
  {
    /**
     * {Function} Binds the given function @func {Function} to the given @object {Object} and returns
     * the resulting function.
     *
     * - Only one connection is made to allow proper disconnecting without access to the bound function.
     * - Uses ES5 bind() to connect functions to objects internally.
     *
     * Because bound functions are cached on the objects this approach is only useful for longer
     * living methods like class or module methods and not a recommended approach for binding
     * short living or temporary methods like the ones declared inside closures. Otherwise
     * the cache would increase in size during application runtime.
     */
    bind : bind,

    /**
     * {Number} Executes the given @callback {Function} in the given @context {Object?global}
     * after a timeout of @delay {Number} milliseconds. Supports optional
     * @args {arguments...} which are passed to the @callback.
     */
    timeout : createDelayed(setTimeout),

    /**
     * {Number} Executes the given @callback {Function} in the given @context {Object?global}
     * every interval of @delay {Number} milliseconds. Supports optional
     * @args {arguments...} which are passed to the @callback.
     */
    interval : createDelayed(setInterval),

    /**
     * {Function} Debounces the given method.
     *
     * Debouncing ensures that exactly one signal is sent for an event that may be happening
     * several times — or even several hundreds of times over an extended period. As long as
     * the events are occurring fast enough to happen at least once in every detection
     * period, the signal will not be sent!
     *
     * - @threshold {Integer?100} Number of milliseconds of distance required before reacting/resetting.
     * - @execAsap {Boolean?false} Whether the execution should happen at begin.
     */
    debounce : function(func, threshold, execAsap)
    {
      if (jasy.Env.isSet("debug"))
      {
        core.Assert.isType(func, "Function");

        if (threshold != null) {
          core.Assert.isType(threshold, "Integer");
        }

        if (execAsap != null) {
          core.Assert.isType(execAsap, "Boolean");
        }
      }

      // Via: http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
      var timeout;

      return function()
      {
        var obj = this, args = arguments;
        function delayed()
        {
          if (!execAsap) {
            func.apply(obj, args);
          }

          timeout = null;
        }

        if (timeout){
          clearTimeout(timeout);
        } else if (execAsap) {
          func.apply(obj, args);
        }

        timeout = setTimeout(delayed, threshold || 100);
      };
    },

    /**
     * {Function} Returns a new function that when called multiple times will only call the
     * original function after the specificed @time {Integer} in milliseconds has elapsed.
     */
    throttle : function(func, time)
    {
      if (jasy.Env.isSet("debug"))
      {
        core.Assert.isType(func, "Function");
        core.Assert.isType(time, "Integer");
      }

      var lastEventTimestamp = null;
      var limit = time;

      return function()
      {
        var self = this;
        var args = arguments;
        var now = Date.now();

        if (!lastEventTimestamp || now - lastEventTimestamp >= limit)
        {
          lastEventTimestamp = now;
          func.apply(self, args);
        }
      };
    },

    /**
     * Executes the given @func {Function} immediately, but not in the current
     * thread (non-blocking). Optionally is able to call the method in the given
     * @context {Object?}.
     */
    immediate : function(func, context)
    {
      if (jasy.Env.isSet("debug"))
      {
        core.Assert.isType(func, "Function");

        if (context != null) {
          core.Assert.isType(context, "Object");
        }
      }

      if (context) {
        func = bind(func, context);
      }

      immediate(func);
    },

    /**
     * {Function} Returns a new function that curries all given arguments to the given @func {Function}.
     */
    curry : function(func)
    {
      if (jasy.Env.isSet("debug"))
      {
        core.Assert.isType(func, "Function");
      }

      var args = core.Array.fromArguments(arguments);
      args.splice(0, 1);
      return function() {
        return func.apply(this, args.concat(core.Array.fromArguments(arguments)));
      };
    }
  });
})(core.Main.getGlobal(), Array.prototype.slice);
<commit_msg>Add infinite apply helper<commit_after>/*
==================================================================================================
  Core - JavaScript Foundation
  Copyright 2012-2013 Sebastian Werner
==================================================================================================
*/

"use strict";

(function(global, slice)
{
  var bind = function(func, context)
  {
    // Inspired by: http://webreflection.blogspot.de/2012/11/my-name-is-bound-method-bound.html

    if (jasy.Env.isSet("debug"))
    {
      core.Assert.isType(func, "Function");
      core.Assert.isType(context, "Object");
    }

    // Using name which is not common to store these references in their objects
    // Storing it on the object has the benefit that when the object is
    // garbage collected its bound methods are gone as well.
    var boundName = "bound:" + core.util.Id.get(func);

    return context[boundName] || (
      context[boundName] = func.bind(context)
    );
  };

  var createDelayed = function(nativeMethod)
  {
    return function(callback, context, delay)
    {
      if (jasy.Env.isSet("debug"))
      {
        core.Assert.isType(callback, "Function");
        if (context) {
          core.Assert.isType(context, "Object");
        }
        core.Assert.isType(delay, "Integer");
      }

      if (arguments.length > 3)
      {
        if (!context) {
          context = global;
        }

        var callbackArgs = slice.call(arguments, 3);

        return nativeMethod(function() {
          callback.apply(context, callbackArgs);
        }, delay);
      }
      else
      {
        if (context) {
          callback = bind(callback, context);
        }

        return nativeMethod(callback, delay);
      }
    };
  };

  var immediate;

  // Keep in mind IE10 bugs:
  // http://codeforhire.com/2013/09/21/setimmediate-and-messagechannel-broken-on-internet-explorer-10/

  // Try NodeJS style nextTick() API
  // http://howtonode.org/understanding-process-next-tick
  if (global.process && process.nextTick)
  {
    immediate = process.nextTick;
  }
  else
  {
    // Try experimental setImmediate() API
    // https://developer.mozilla.org/en-US/docs/DOM/window.setImmediate
    immediate = core.util.Experimental.get(global, "setImmediate");

    if (immediate)
    {
      immediate = global[immediate];
    }
    else
    {
      // Last fallback: Timeout
      immediate = function(func) {
        return setTimeout(func, 0);
      };
    }
  }

  /**
   * {Integer} Maximum arguments that could be given to Function.apply
   * 2048 is a safe value for all browsers.
   */

  var APPLY_LIMIT = 2048;

  /**
   * A collection of utility methods for native JavaScript functions.
   */
  core.Module("core.Function",
  {
    /**
     * {Function} Binds the given function @func {Function} to the given @object {Object} and returns
     * the resulting function.
     *
     * - Only one connection is made to allow proper disconnecting without access to the bound function.
     * - Uses ES5 bind() to connect functions to objects internally.
     *
     * Because bound functions are cached on the objects this approach is only useful for longer
     * living methods like class or module methods and not a recommended approach for binding
     * short living or temporary methods like the ones declared inside closures. Otherwise
     * the cache would increase in size during application runtime.
     */
    bind : bind,

    /**
     * {Number} Executes the given @callback {Function} in the given @context {Object?global}
     * after a timeout of @delay {Number} milliseconds. Supports optional
     * @args {arguments...} which are passed to the @callback.
     */
    timeout : createDelayed(setTimeout),

    /**
     * {Number} Executes the given @callback {Function} in the given @context {Object?global}
     * every interval of @delay {Number} milliseconds. Supports optional
     * @args {arguments...} which are passed to the @callback.
     */
    interval : createDelayed(setInterval),

    /**
     * {Function} Debounces the given method.
     *
     * Debouncing ensures that exactly one signal is sent for an event that may be happening
     * several times — or even several hundreds of times over an extended period. As long as
     * the events are occurring fast enough to happen at least once in every detection
     * period, the signal will not be sent!
     *
     * - @threshold {Integer?100} Number of milliseconds of distance required before reacting/resetting.
     * - @execAsap {Boolean?false} Whether the execution should happen at begin.
     */
    debounce : function(func, threshold, execAsap)
    {
      if (jasy.Env.isSet("debug"))
      {
        core.Assert.isType(func, "Function");

        if (threshold != null) {
          core.Assert.isType(threshold, "Integer");
        }

        if (execAsap != null) {
          core.Assert.isType(execAsap, "Boolean");
        }
      }

      // Via: http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
      var timeout;

      return function()
      {
        var obj = this, args = arguments;
        function delayed()
        {
          if (!execAsap) {
            func.apply(obj, args);
          }

          timeout = null;
        }

        if (timeout){
          clearTimeout(timeout);
        } else if (execAsap) {
          func.apply(obj, args);
        }

        timeout = setTimeout(delayed, threshold || 100);
      };
    },

    /**
     * {Function} Returns a new function that when called multiple times will only call the
     * original function after the specificed @time {Integer} in milliseconds has elapsed.
     */
    throttle : function(func, time)
    {
      if (jasy.Env.isSet("debug"))
      {
        core.Assert.isType(func, "Function");
        core.Assert.isType(time, "Integer");
      }

      var lastEventTimestamp = null;
      var limit = time;

      return function()
      {
        var self = this;
        var args = arguments;
        var now = Date.now();

        if (!lastEventTimestamp || now - lastEventTimestamp >= limit)
        {
          lastEventTimestamp = now;
          func.apply(self, args);
        }
      };
    },

    /**
     * Executes the given @func {Function} immediately, but not in the current
     * thread (non-blocking). Optionally is able to call the method in the given
     * @context {Object?}.
     */
    immediate : function(func, context)
    {
      if (jasy.Env.isSet("debug"))
      {
        core.Assert.isType(func, "Function");

        if (context != null) {
          core.Assert.isType(context, "Object");
        }
      }

      if (context) {
        func = bind(func, context);
      }

      immediate(func);
    },

    /**
     * {Function} Returns a new function that curries all given arguments to the given @func {Function}.
     */
    curry : function(func)
    {
      if (jasy.Env.isSet("debug"))
      {
        core.Assert.isType(func, "Function");
      }

      var args = core.Array.fromArguments(arguments);
      args.splice(0, 1);
      return function() {
        return func.apply(this, args.concat(core.Array.fromArguments(arguments)));
      };
    },

    /**
     * Applies the given @args {Array} via func.apply to the given @func {Function}
     * in @context {Object}.
     * infiniteApply devides the arguments list to a reasonable size and applies each
     * chunk to the fiven function. After that @joinFunc {Function} is called with the
     * result as array. This function should join all results to the appropriate result
     * and return it.
     */
    infiniteApply : function(func, args, joinFunc, context)
    {
      if (jasy.Env.isSet("debug")) {
        core.Assert.isType(func, "Function");
        core.Assert.isType(args, "Array");
        core.Assert.isType(joinFunc, "Function");
      }

      var argsLength = args.length;
      if (argsLength <= APPLY_LIMIT) {
        return func.apply(context, args);
      }

      var turns = Math.ceil(argsLength / APPLY_LIMIT)
      var result = new Array(turns);
      for (var i=0; i<turns; i++) {
        var start = i * APPLY_LIMIT;
        result[i] = func.apply(context, args.slice(start, start + APPLY_LIMIT));
      }
      return joinFunc(result);
    }
  });
})(core.Main.getGlobal(), Array.prototype.slice);
<|endoftext|>


<commit_before>var request = require('superagent');

var liveUrl = 'https://core.trexle.com/api/v1';
var testUrl = 'https://core.trexle.com/api/v1';

var Trexle = function(options) {

  var generateRequest = function(req, fields, callback) {
    var field, field2;
    req.auth(options.key, '')
    for(field in fields) {
        if(typeof fields[field] === 'object') {
          for(field2 in fields[field]) {
            req.field(field+'['+field2+']', ''+fields[field][field2])
          }
        } else {
          req.field(field, ''+fields[field])
        }
      }

    req.end(function(err,res){
      if(res && !res.ok){
        err = new Error(res.body.error_description);
      };
      callback.call(this, err, res);
    });
  };

  this.createCard = function (fields, callback) {
    var req = request.post(options.url + '/tokens');
    generateRequest(req, fields, callback);
  };

  this.createCustomer = function (fields, callback) {
    var req = request.post(options.url + '/customers');
    generateRequest(req, fields, callback);
  };

  this.retrieveCustomer = function (token, callback) {
    var req = request.get(options.url + '/customers/' + token);
    generateRequest(req, {}, callback);
  };

  this.refundCharge = function (chargeId, fields, callback) {

    var req = request.post(options.url + '/charges/' + chargeId + '/refunds');
    generateRequest(req, fields, callback);
  };

  this.retrieveCharge = function (chargeId, callback) {

    var req = request.get(options.url + '/charges/' + chargeId);
    generateRequest(req, {}, callback);
  };

  this.createCharge = function (fields, callback) {
    var req = request.post(options.url + '/charges');
    generateRequest(req, fields, callback);
  };

  this.captureCharge = function (nonCapturedToken, callback) {
    var url = options.url + '/charges/' + nonCapturedToken + "/capture";
    console.log(url);
    var req = request.put(url);
    generateRequest(req, {}, callback);
  };

};

var setup = function (options) {
  options.url = liveUrl;
  if(!options.production) {
    options.url = testUrl;
  }
  var trexle = new Trexle(options);
  return trexle;
};

exports.setup = setup;
<commit_msg>fix response<commit_after>var request = require('superagent');

var liveUrl = 'https://core.trexle.com/api/v1';
var testUrl = 'https://core.trexle.com/api/v1';

var Trexle = function(options) {

  var generateRequest = function(req, fields, callback) {
    var field, field2;
    req.auth(options.key, '')
    for(field in fields) {
        if(typeof fields[field] === 'object') {
          for(field2 in fields[field]) {
            req.field(field+'['+field2+']', ''+fields[field][field2])
          }
        } else {
          req.field(field, ''+fields[field])
        }
      }

    req.end(function(err,res){
      if(err && !res.ok){
        err = new Error(res.body.error_description);
      };
      callback.call(this, err, res.body.response);
    });
  };

  this.createCard = function (fields, callback) {
    var req = request.post(options.url + '/tokens');
    generateRequest(req, fields, callback);
  };

  this.createCustomer = function (fields, callback) {
    var req = request.post(options.url + '/customers');
    generateRequest(req, fields, callback);
  };

  this.retrieveCustomer = function (token, callback) {
    var req = request.get(options.url + '/customers/' + token);
    generateRequest(req, {}, callback);
  };

  this.refundCharge = function (chargeId, fields, callback) {

    var req = request.post(options.url + '/charges/' + chargeId + '/refunds');
    generateRequest(req, fields, callback);
  };

  this.retrieveCharge = function (chargeId, callback) {

    var req = request.get(options.url + '/charges/' + chargeId);
    generateRequest(req, {}, callback);
  };

  this.createCharge = function (fields, callback) {
    var req = request.post(options.url + '/charges');
    generateRequest(req, fields, callback);
  };

  this.captureCharge = function (nonCapturedToken, callback) {
    var url = options.url + '/charges/' + nonCapturedToken + "/capture";
    console.log(url);
    var req = request.put(url);
    generateRequest(req, {}, callback);
  };

};

var setup = function (options) {
  options.url = liveUrl;
  if(!options.production) {
    options.url = testUrl;
  }
  var trexle = new Trexle(options);
  return trexle;
};

exports.setup = setup;
<|endoftext|>


<commit_before>var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/mydb');

//schema//
var locationSchema = mongoose.Schema({
        city : String
    })

var db = mongoose.connection;
db.on('error',console.error.bind(console,'connection error'));
db.once('open',function(callback){
    console.log('Mongodb is connected');
});

module.exports.create = function(city){
    //Model//
    var Locations = mongoose.model('location',locationSchema)

    var cityLocation = new Locations({city:'milano'})
    console.log(cityLocation.city)
}<commit_msg>add db<commit_after>var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/mydb');

//schema//
var locationSchema = mongoose.Schema({
        city : String
    })
//Model//
var Locations = mongoose.model('location',locationSchema)

var db = mongoose.connection;
db.on('error',console.error.bind(console,'connection error'));
db.once('open',function(callback){
    console.log('Mongodb is connected');
});

module.exports.create = function(city){
    var cityLocation = new Locations({city:'milano'})
    console.log(cityLocation.city)
}<|endoftext|>


<commit_before>/*
 * markdown.js
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * The Initial Developer of the Original Code is
 * Ajax.org B.V.
 * Portions created by the Initial Developer are Copyright (C) 2010
 * the Initial Developer. All Rights Reserved.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

define("mode/rmarkdown", function(require, exports, module) {

var oop = require("ace/lib/oop");
var MarkdownMode = require("mode/markdown").Mode;
var Tokenizer = require("ace/tokenizer").Tokenizer;
var RMarkdownHighlightRules = require("mode/rmarkdown_highlight_rules").RMarkdownHighlightRules;
var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent;
var RMatchingBraceOutdent = require("mode/r_matching_brace_outdent").RMatchingBraceOutdent;
var SweaveBackgroundHighlighter = require("mode/sweave_background_highlighter").SweaveBackgroundHighlighter;
var RCodeModel = require("mode/r_code_model").RCodeModel;
var MarkdownFoldMode = require("ace/mode/folding/markdown").FoldMode;
var Utils = require("mode/utils");

var Mode = function(suppressHighlighting, session) {
   var that = this;

   this.$session = session;
   this.$tokenizer = new Tokenizer(new RMarkdownHighlightRules().getRules());

   this.$outdent = new MatchingBraceOutdent();
   this.$r_outdent = {};
   oop.implement(this.$r_outdent, RMatchingBraceOutdent);

   this.codeModel = new RCodeModel(session, this.$tokenizer, /^r-/,
                                   /^(?:[ ]{4})?`{3,}\s*\{r(.*)\}\s*$/);

   var markdownFoldingRules = new MarkdownFoldMode();

   this.foldingRules = {

      getFoldWidget: function(session, foldStyle, row) {
         if (that.getLanguageMode({row: row, column: 0}) == "Markdown")
            return markdownFoldingRules.getFoldWidget(session, foldStyle, row);
         else
            return that.codeModel.getFoldWidget(session, foldStyle, row);
      },

      getFoldWidgetRange: function(session, foldStyle, row) {
         if (that.getLanguageMode({row: row, column: 0}) == "Markdown")
            return markdownFoldingRules.getFoldWidgetRange(session, foldStyle, row);
         else
            return that.codeModel.getFoldWidgetRange(session, foldStyle, row);
      }

   };

   this.$sweaveBackgroundHighlighter = new SweaveBackgroundHighlighter(
         session,
         /^(?:[ ]{4})?`{3,}\s*\{r(?:.*)\}\s*$/,
         /^(?:[ ]{4})?`{3,}\s*$/,
         true);
};
oop.inherits(Mode, MarkdownMode);

(function() {

   this.insertChunkInfo = {
      value: "```{r}\n\n```\n",
      position: {row: 0, column: 5}
   };

   this.getLanguageMode = function(position)
   {
      var state = Utils.getPrimaryState(this.$session, position.row);

      if (state.match(/^r-cpp-(?!r-)/))
         return 'C_CPP';
      else
         return state.match(/^r-/) ? 'R' : 'Markdown';
   };

   this.inCppLanguageMode = function(state)
   {
      return state.match(/^r-cpp-(?!r-)/);
   };

   this.inMarkdownLanguageMode = function(state)
   {
      return !state.match(/^r-/);
   };

   this.getNextLineIndent = function(state, line, tab)
   {
      state = Utils.primaryState(state);
      if (!this.inCppLanguageMode(state))
         return this.codeModel.getNextLineIndent(state, line, tab);
      else {
         // from c_cpp getNextLineIndent
         var indent = this.$getIndent(line);

         var tokenizedLine = this.$tokenizer.getLineTokens(line, state);
         var tokens = tokenizedLine.tokens;
         var endState = tokenizedLine.state;

         if (tokens.length && tokens[tokens.length-1].type == "comment") {
            return indent;
         }

         if (state == "r-cpp-start") {
            var match = line.match(/^.*[\{\(\[]\s*$/);
            if (match) {
                indent += tab;
            }
         } else if (state == "r-cpp-doc-start") {
            if (endState == "start") {
                return "";
            }
            var match = line.match(/^\s*(\/?)\*/);
            if (match) {
                if (match[1]) {
                    indent += " ";
                }
                indent += "* ";
            }
        }

        return indent;
      }
   };

    this.checkOutdent = function(state, line, input) {
        state = Utils.primaryState(state);
        if (this.inCppLanguageMode(state))
            return this.$outdent.checkOutdent(line, input);
        else
            return this.$r_outdent.checkOutdent(state, line, input);
    };

    this.autoOutdent = function(state, doc, row) {
        state = Utils.primaryState(state);
        if (this.inCppLanguageMode(state))
            return this.$outdent.autoOutdent(doc, row);
        else
            return this.$r_outdent.autoOutdent(state, doc, row, this.codeModel);
    };

    this.transformAction = function(state, action, editor, session, text) {
        state = Utils.primaryState(state);
        // from c_cpp.js
        if (action === 'insertion') {
            if ((text === "\n") && this.inCppLanguageMode(state)) {
                // If newline in a doxygen comment, continue the comment
                var pos = editor.getSelectionRange().start;
                var match = /^((\s*\/\/+')\s*)/.exec(session.doc.getLine(pos.row));
                if (match && editor.getSelectionRange().start.column >= match[2].length) {
                    return {text: "\n" + match[1]};
                }
            }

            else if ((text === "R") && this.inCppLanguageMode(state)) {
                // If newline to start and embedded R chunk complete the chunk
                var pos = editor.getSelectionRange().start;
                var match = /^(\s*\/\*{3,}\s*)/.exec(session.doc.getLine(pos.row));
                if (match && editor.getSelectionRange().start.column >= match[1].length) {
                    return {text: "R\n\n*/\n",
                            selection: [1,0,1,0]};
                }
            }
        }
        return false;
    };

}).call(Mode.prototype);

exports.Mode = Mode;
});
<commit_msg>use R mode token boundaries in R markdown<commit_after>/*
 * markdown.js
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * The Initial Developer of the Original Code is
 * Ajax.org B.V.
 * Portions created by the Initial Developer are Copyright (C) 2010
 * the Initial Developer. All Rights Reserved.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

define("mode/rmarkdown", function(require, exports, module) {

var oop = require("ace/lib/oop");
var MarkdownMode = require("mode/markdown").Mode;
var Tokenizer = require("ace/tokenizer").Tokenizer;
var RMarkdownHighlightRules = require("mode/rmarkdown_highlight_rules").RMarkdownHighlightRules;
var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent;
var RMatchingBraceOutdent = require("mode/r_matching_brace_outdent").RMatchingBraceOutdent;
var SweaveBackgroundHighlighter = require("mode/sweave_background_highlighter").SweaveBackgroundHighlighter;
var RCodeModel = require("mode/r_code_model").RCodeModel;
var MarkdownFoldMode = require("ace/mode/folding/markdown").FoldMode;
var Utils = require("mode/utils");
var unicode = require("ace/unicode");

var Mode = function(suppressHighlighting, session) {
   var that = this;

   this.$session = session;
   this.$tokenizer = new Tokenizer(new RMarkdownHighlightRules().getRules());

   this.$outdent = new MatchingBraceOutdent();
   this.$r_outdent = {};
   oop.implement(this.$r_outdent, RMatchingBraceOutdent);

   this.codeModel = new RCodeModel(session, this.$tokenizer, /^r-/,
                                   /^(?:[ ]{4})?`{3,}\s*\{r(.*)\}\s*$/);

   var markdownFoldingRules = new MarkdownFoldMode();

   this.foldingRules = {

      getFoldWidget: function(session, foldStyle, row) {
         if (that.getLanguageMode({row: row, column: 0}) == "Markdown")
            return markdownFoldingRules.getFoldWidget(session, foldStyle, row);
         else
            return that.codeModel.getFoldWidget(session, foldStyle, row);
      },

      getFoldWidgetRange: function(session, foldStyle, row) {
         if (that.getLanguageMode({row: row, column: 0}) == "Markdown")
            return markdownFoldingRules.getFoldWidgetRange(session, foldStyle, row);
         else
            return that.codeModel.getFoldWidgetRange(session, foldStyle, row);
      }

   };

   this.$sweaveBackgroundHighlighter = new SweaveBackgroundHighlighter(
         session,
         /^(?:[ ]{4})?`{3,}\s*\{r(?:.*)\}\s*$/,
         /^(?:[ ]{4})?`{3,}\s*$/,
         true);
};
oop.inherits(Mode, MarkdownMode);

(function() {

   this.insertChunkInfo = {
      value: "```{r}\n\n```\n",
      position: {row: 0, column: 5}
   };

   this.getLanguageMode = function(position)
   {
      var state = Utils.getPrimaryState(this.$session, position.row);

      if (state.match(/^r-cpp-(?!r-)/))
         return 'C_CPP';
      else
         return state.match(/^r-/) ? 'R' : 'Markdown';
   };

   this.inCppLanguageMode = function(state)
   {
      return state.match(/^r-cpp-(?!r-)/);
   };

   this.inMarkdownLanguageMode = function(state)
   {
      return !state.match(/^r-/);
   };

   this.getNextLineIndent = function(state, line, tab)
   {
      state = Utils.primaryState(state);
      if (!this.inCppLanguageMode(state))
         return this.codeModel.getNextLineIndent(state, line, tab);
      else {
         // from c_cpp getNextLineIndent
         var indent = this.$getIndent(line);

         var tokenizedLine = this.$tokenizer.getLineTokens(line, state);
         var tokens = tokenizedLine.tokens;
         var endState = tokenizedLine.state;

         if (tokens.length && tokens[tokens.length-1].type == "comment") {
            return indent;
         }

         if (state == "r-cpp-start") {
            var match = line.match(/^.*[\{\(\[]\s*$/);
            if (match) {
                indent += tab;
            }
         } else if (state == "r-cpp-doc-start") {
            if (endState == "start") {
                return "";
            }
            var match = line.match(/^\s*(\/?)\*/);
            if (match) {
                if (match[1]) {
                    indent += " ";
                }
                indent += "* ";
            }
        }

        return indent;
      }
   };

    this.checkOutdent = function(state, line, input) {
        state = Utils.primaryState(state);
        if (this.inCppLanguageMode(state))
            return this.$outdent.checkOutdent(line, input);
        else
            return this.$r_outdent.checkOutdent(state, line, input);
    };

    this.autoOutdent = function(state, doc, row) {
        state = Utils.primaryState(state);
        if (this.inCppLanguageMode(state))
            return this.$outdent.autoOutdent(doc, row);
        else
            return this.$r_outdent.autoOutdent(state, doc, row, this.codeModel);
    };

    this.transformAction = function(state, action, editor, session, text) {
        state = Utils.primaryState(state);
        // from c_cpp.js
        if (action === 'insertion') {
            if ((text === "\n") && this.inCppLanguageMode(state)) {
                // If newline in a doxygen comment, continue the comment
                var pos = editor.getSelectionRange().start;
                var match = /^((\s*\/\/+')\s*)/.exec(session.doc.getLine(pos.row));
                if (match && editor.getSelectionRange().start.column >= match[2].length) {
                    return {text: "\n" + match[1]};
                }
            }

            else if ((text === "R") && this.inCppLanguageMode(state)) {
                // If newline to start and embedded R chunk complete the chunk
                var pos = editor.getSelectionRange().start;
                var match = /^(\s*\/\*{3,}\s*)/.exec(session.doc.getLine(pos.row));
                if (match && editor.getSelectionRange().start.column >= match[1].length) {
                    return {text: "R\n\n*/\n",
                            selection: [1,0,1,0]};
                }
            }
        }
        return false;
    };

    this.tokenRe = new RegExp("^["
        + unicode.packages.L
        + unicode.packages.Mn + unicode.packages.Mc
        + unicode.packages.Nd
        + unicode.packages.Pc + "._]+", "g"
    );

    this.nonTokenRe = new RegExp("^(?:[^"
        + unicode.packages.L
        + unicode.packages.Mn + unicode.packages.Mc
        + unicode.packages.Nd
        + unicode.packages.Pc + "._]|\s])+", "g"
    );

}).call(Mode.prototype);

exports.Mode = Mode;
});
<|endoftext|>


<commit_before>var AutoComplete = Selectioner.Dialog.AutoComplete = function() {};

AutoComplete.prototype = new Selectioner.Base.Dialog();

// Render an the equivilant control that represents an
// <option /> element for the underlying <select /> element.
AutoComplete.prototype.render = function()
{
	this.textElement = this.select
		.data('selectioner')
		.display
		.element
		.find('input[type="text"]');

	if (this.textElement.length === 0)
	{
		throw new Error('AutoComplete expects the Display to contain an <input type="text" /> element');
	}

	this.element = $('<ul />');
	this.update();

	var dialog = this;
	var select = this.select;
	var children = this.select.find('option');

	this.textElement.on
		(
			'keyup',
			function(event)
			{
				dialog.update();
				if (!dialog.popup.isShown())
				{
					dialog.popup.show();
				}
				else
				{
					dialog.popup.reposition();
				}
			}
		);

	this.update();
};

AutoComplete.prototype.update = function()
{
	var buildOption = function(option)
	{
		var selectAnchor = $('<a />')
			.attr('href', 'javascript:;')
			.text(option.text())
			.on
				(
					'click',
					function(event)
					{
						option[0].selected = true;
						dialog.popup.hide();
						select.trigger('change');
					}
				);

		return $('<li />').append(selectAnchor);
	};

	var filterText = this.textElement.val().toLowerCase();

	var children = this.select.find('option');
	var filteredOptions = $();

	for (var i = 0, length = children.length; i < length; i++)
	{
		var option = $(children[i]);
		var text = option.text().toLowerCase();

		if (text !== '' && text.indexOf(filterText) === 0)
		{
			filteredOptions = filteredOptions.add(buildOption(option));

			if (filteredOptions.length > Selectioner.Settings.maxAutoCompleteItems)
			{
				break;
			}
		}
	}

	this.element
		.empty()
		.append(filteredOptions);

	/*
	var children = this.element.find('li');

	var visibleChildren = children
		.filter
		(
			function()
			{
				var text = $(this).text().toLowerCase();
				return text !== '' && text.indexOf(filterText) === 0;
			}
		)
		.filter
		(
			function(index)
			{
				return index < Selectioner.Settings.maxAutoCompleteItems;
			}
		);

	children.not(visibleChildren).css('display', 'none');
	visibleChildren.css('display', '');
	*/
};<commit_msg>Auto-complete now renders a lot faster.<commit_after>var AutoComplete = Selectioner.Dialog.AutoComplete = function() {};

AutoComplete.prototype = new Selectioner.Base.Dialog();

// Render an the equivilant control that represents an
// <option /> element for the underlying <select /> element.
AutoComplete.prototype.render = function()
{
	this.textElement = this.select
		.data('selectioner')
		.display
		.element
		.find('input[type="text"]');

	if (this.textElement.length === 0)
	{
		throw new Error('AutoComplete expects the Display to contain an <input type="text" /> element');
	}

	this.element = $('<ul />');
	this.update();

	var dialog = this;
	var select = this.select;
	var children = this.select.find('option');

	this.textElement.on
		(
			'keyup',
			function(event)
			{
				dialog.update();
				if (!dialog.popup.isShown())
				{
					dialog.popup.show();
				}
				else
				{
					dialog.popup.reposition();
				}
			}
		);

	this.update();
};

AutoComplete.prototype.update = function()
{
	var buildOption = function(option)
	{
		var selectAnchor = $('<a />')
			.attr('href', 'javascript:;')
			.text(option.text())
			.on
				(
					'click',
					function(event)
					{
						option[0].selected = true;
						dialog.popup.hide();
						select.trigger('change');
					}
				);

		return $('<li />').append(selectAnchor);
	};

	var filterText = this.textElement.val().toLowerCase();

	var children = this.select.find('option');
	var filteredOptions = $();

	for (var i = 0, length = children.length; i < length; i++)
	{
		var option = $(children[i]);
		var text = option.text().toLowerCase();

		if (text !== '' && text.indexOf(filterText) === 0)
		{
			filteredOptions = filteredOptions.add(buildOption(option));

			if (filteredOptions.length > Selectioner.Settings.maxAutoCompleteItems)
			{
				break;
			}
		}
	}

	this.element
		.empty()
		.append(filteredOptions);
};<|endoftext|>


<commit_before>'use strict';

var googleapis = require('googleapis');
var async = require('async');

var config = require('../config/configuration.js');
var retrieveThreads = require('./helpers/retrieve.js');

module.exports = function updateAccount(serviceData, cursor, queues, cb) {
  // Retrieve all mails since last call
  async.waterfall([
    function refreshTokens(cb) {
      var oauth2Client = new googleapis.auth.OAuth2(config.googleId, config.googleSecret, serviceData.callbackUrl);
      oauth2Client.refreshToken_(serviceData.tokens.refresh_token, function(err, tokens) {
        if(err) {
          return cb(err);
        }

        if(typeof tokens !== 'object' || !tokens.access_token) {
          return cb(new Error("Can't refresh tokens"));
        }

        tokens.refresh_token = serviceData.tokens.refresh_token;
        serviceData.tokens = tokens;
        cb(err);
      });
    },
    function getThreads(cb) {
      var options = {
        maxResults: 1000,
        userId: serviceData.accountName
      };

      if(!cursor) {
        cursor = {
          date: new Date(1970),
          id: 0
        };
      }

      var oauth2Client = new googleapis.auth.OAuth2(config.googleId, config.googleSecret, serviceData.callbackUrl);
      oauth2Client.credentials = serviceData.tokens;
      options.auth = oauth2Client;

      retrieveThreads(options, cursor, [], {}, cb);
    },
    function addThreadsToQueue(newCursor, threads, cb) {
      threads.forEach(function(thread) {
        thread.identifier = "https://mail.google.com/mail/b/" + serviceData.accountName + "/?cm#all/" + thread.id;
        thread.title = thread.identifier;
        queues.addition.push(thread);
      });
      cb(null, newCursor, serviceData);
    }
  ], cb);
};
<commit_msg>Send TokenError when we need a refresh<commit_after>'use strict';

var googleapis = require('googleapis');
var async = require('async');
var TokenError = require('anyfetch-provider').TokenError;

var config = require('../config/configuration.js');
var retrieveThreads = require('./helpers/retrieve.js');

module.exports = function updateAccount(serviceData, cursor, queues, cb) {
  // Retrieve all mails since last call
  async.waterfall([
    function refreshTokens(cb) {
      var oauth2Client = new googleapis.auth.OAuth2(config.googleId, config.googleSecret, serviceData.callbackUrl);
      oauth2Client.refreshToken_(serviceData.tokens.refresh_token, function(err, tokens) {
        if(err) {
          if(err.toString().match(/token/i)) {
            return cb(new TokenError());
          }
          return cb(err);
        }

        if(typeof tokens !== 'object' || !tokens.access_token) {
          return cb(new TokenError());
        }

        tokens.refresh_token = serviceData.tokens.refresh_token;
        serviceData.tokens = tokens;
        cb(err);
      });
    },
    function getThreads(cb) {
      var options = {
        maxResults: 1000,
        userId: serviceData.accountName
      };

      if(!cursor) {
        cursor = {
          date: new Date(1970),
          id: 0
        };
      }

      var oauth2Client = new googleapis.auth.OAuth2(config.googleId, config.googleSecret, serviceData.callbackUrl);
      oauth2Client.credentials = serviceData.tokens;
      options.auth = oauth2Client;

      retrieveThreads(options, cursor, [], {}, cb);
    },
    function addThreadsToQueue(newCursor, threads, cb) {
      threads.forEach(function(thread) {
        thread.identifier = "https://mail.google.com/mail/b/" + serviceData.accountName + "/?cm#all/" + thread.id;
        thread.title = thread.identifier;
        queues.addition.push(thread);
      });
      cb(null, newCursor, serviceData);
    }
  ], cb);
};
<|endoftext|>


<commit_before>/**
 * @fileOverview Defines client side API in which files can be uploaded.
 */

Slingshot = {};

/**
 *
 * @param {string} directive - Name of server-directive to use.
 * @param {object} [metaData] - Data to be sent to directive.
 * @constructor
 */

Slingshot.Upload = function (directive, metaData) {

  if (!window.File || !window.FormData) {
    throw new Error("Browser does not support HTML5 uploads");
  }

  var self = this,
      loaded = new ReactiveVar(),
      total = new ReactiveVar(),
      status = new ReactiveVar("idle");

  function buildFormData() {
    var formData = new window.FormData();

    _.each(self.instructions.postData, function (field) {
      formData.append(field.name, field.value);
    });

    formData.append("file", self.file);

    return formData;
  }

  _.extend(self, {

    /**
     * @returns {string}
     */

    status: function () {
      return status.get();
    },

    /**
     * @returns {number}
     */

    progress: function () {
      return self.uploaded() / total.get();
    },

    /**
     * @returns {number}
     */

    uploaded: function () {
      return loaded.get();
    },

    /**
     * @param {File} file
     * @param {Function} [callback]
     * @returns {Slingshot.Upload}
     */

    send: function (file, callback) {
      check(file, window.File);

      self.file = file;

      self.request(file, function (error, instructions) {
        if (error) {
          return callback(error);
        }

        self.instructions = instructions;

        self.transfer(file, callback);
      });

      return self;
    },

    /**
     * @param {Function} [callback]
     * @returns {Slingshot.Upload}
     */

    request: function (callback) {
      status.set("authorizing");
      Meteor.call("slingshot/uploadRequest", directive, metaData,
        _.pick(self.file, "name", "size", "type"), function (error,
                                                             instructions) {
          status.set(error ? "failed" : "authorized");

          callback(error, instructions);
        });

      return self;
    },

    /**
     * @param {Function} [callback]
     *
     * @returns {Slingshot.Upload}
     */

    transfer: function (callback) {
      if (status.curValue !== "authorized") {
        throw new Error("Cannot transfer file at upload status: " +
          status.curValue);
      }

      status.set("transferring");
      loaded.set(0);

      var xhr = new XMLHttpRequest();

      xhr.upload.addEventListener("progress", function (event) {
        if (event.lengthComputable) {
          loaded.set(event.loaded);
          total.set(event.total);
        }
      }, false);

      xhr.addEventListener("load", function () {
        status.set("done");
        loaded.set(total.get());
        callback(null, self.instructions.download);
      });

      xhr.addEventListener("error", function () {
        status.set("failed");
        callback(new Error("Upload failed - see console logs"));
      });

      xhr.addEventListener("abort", function () {
        status.set("aborted");
        callback(new Error("The upload has been cancelled"));
      });

      xhr.open("POST", self.instructions.upload, true);
      xhr.send(buildFormData());

      return self;
    },

    /**
     * Latency compensated url of the file to be uploaded.
     *
     * @returns {string}
     */

    url: function () {
      var status = self.status();

      if (self.instructions && status === "done") {
        return self.instructions.download;
      }

      if (self.file && status !== "failed" && status !== "aborted" &&
        window.FileReader) {
          var reader = new window.FileReader();
          return reader.readAsDataURL(self.file);
      }
    }
  });
};
<commit_msg>Fixed latency compensation for url reading.<commit_after>/**
 * @fileOverview Defines client side API in which files can be uploaded.
 */

Slingshot = {};

/**
 *
 * @param {string} directive - Name of server-directive to use.
 * @param {object} [metaData] - Data to be sent to directive.
 * @constructor
 */

Slingshot.Upload = function (directive, metaData) {

  if (!window.File || !window.FormData) {
    throw new Error("Browser does not support HTML5 uploads");
  }

  var self = this,
      loaded = new ReactiveVar(),
      total = new ReactiveVar(),
      status = new ReactiveVar("idle"),
      dataUri = new ReactiveVar();

  function buildFormData() {
    var formData = new window.FormData();

    _.each(self.instructions.postData, function (field) {
      formData.append(field.name, field.value);
    });

    formData.append("file", self.file);

    return formData;
  }

  _.extend(self, {

    /**
     * @returns {string}
     */

    status: function () {
      return status.get();
    },

    /**
     * @returns {number}
     */

    progress: function () {
      return self.uploaded() / total.get();
    },

    /**
     * @returns {number}
     */

    uploaded: function () {
      return loaded.get();
    },

    /**
     * @param {File} file
     * @param {Function} [callback]
     * @returns {Slingshot.Upload}
     */

    send: function (file, callback) {
      check(file, window.File);

      self.file = file;

      self.request(file, function (error, instructions) {
        if (error) {
          return callback(error);
        }

        self.instructions = instructions;

        self.transfer(file, callback);
      });

      return self;
    },

    /**
     * @param {Function} [callback]
     * @returns {Slingshot.Upload}
     */

    request: function (callback) {
      status.set("authorizing");
      Meteor.call("slingshot/uploadRequest", directive, metaData,
        _.pick(self.file, "name", "size", "type"), function (error,
                                                             instructions) {
          status.set(error ? "failed" : "authorized");

          callback(error, instructions);
        });

      return self;
    },

    /**
     * @param {Function} [callback]
     *
     * @returns {Slingshot.Upload}
     */

    transfer: function (callback) {
      if (status.curValue !== "authorized") {
        throw new Error("Cannot transfer file at upload status: " +
          status.curValue);
      }

      status.set("transferring");
      loaded.set(0);

      var xhr = new XMLHttpRequest();

      xhr.upload.addEventListener("progress", function (event) {
        if (event.lengthComputable) {
          loaded.set(event.loaded);
          total.set(event.total);
        }
      }, false);

      xhr.addEventListener("load", function () {
        status.set("done");
        loaded.set(total.get());
        callback(null, self.instructions.download);
      });

      xhr.addEventListener("error", function () {
        status.set("failed");
        callback(new Error("Upload failed - see console logs"));
      });

      xhr.addEventListener("abort", function () {
        status.set("aborted");
        callback(new Error("The upload has been cancelled"));
      });

      xhr.open("POST", self.instructions.upload, true);
      xhr.send(buildFormData());

      return self;
    },

    /**
     * Latency compensated url of the file to be uploaded.
     *
     * @returns {string}
     */

    url: function () {
      var status = self.status();

      if (self.instructions && status === "done") {
        return self.instructions.download;
      }

      var url = dataUri.get();

      if (url)
        return url;

      if (Tracker.active && self.file && status !== "failed" &&
        status !== "aborted" && window.FileReader) {
          var reader = new window.FileReader();

          reader.onloadend = function () {
            dataUri.set(reader.result);
          };

          reader.readAsDataURL(self.file);
      }
    }
  });
};
<|endoftext|>


<commit_before>var _ = require('underscore');
var Buffer = require('buffer').Buffer;

function VerifyWithParse(Parse){
	var AccountData = Parse.Object.extend("AccountData");
	this.verify = function(){
		return function(req, token1, token2, profile, done) {
			var provider = this.name;
			var columnName = provider+"AuthData";
			var user;
			var accountData;
			var accountDataQuery = new Parse.Query(AccountData)
			.equalTo("provider", provider)
			.equalTo("userId", profile.id.toString())
			.first()
			.then(function(result){
				if(!(accountData = result)){
					var acl = new Parse.ACL();
					acl.setPublicReadAccess(false);
					acl.setPublicWriteAccess(false);
					accountData = new AccountData({
						userId: profile.id.toString()
						, provider: provider
					})
					.setACL(acl);
				};
				accountData.set({
					token1: token1
					, token2: token2
					, profile: profile
				});
				return accountData;
			})
			.then(function(accountData){
				if(req.user){
					return req.user;
				}
				if(!accountData.get("owner")){
					var username = new Buffer(24);
					var password = new Buffer(24);
					_.times(24, function(i) {
						username.set(i, _.random(0, 255));
						password.set(i, _.random(0, 255));
					});
					return new Parse.User()
					.set("username", username.toString('base64'))
					.set("password", password.toString('base64'))
					.signUp();
				}
				return new Parse.Query(Parse.User).get(accountData.get("owner").id);
			})
			.then(function(result){
				user = result;
				return accountData.save("owner", user);
			})
			.then(function(accountData){
				user.relation("accounts").add(accountData);
				return user.save(null, {useMasterKey: true});
			})
			.then(
				function(user){
					return done(null, user);
				}
				, function(error){
					return done(new Error(error.message), null);
				}
			);
		};
	};
	this.serializeUser = function(user, done){
		done(null, user._sessionToken)
	};
	this.deserializeUser = function(sessionToken, done){
		new Parse.Query(Parse.User)
		.equalTo("sessionToken", sessionToken)
		.first()
		.then(function(user){
			done(null, user);
		}, function(error){
			done(error);
		});
	};
	return this;
}
module.exports = VerifyWithParse;<commit_msg>improved comments<commit_after>// Module dependencies
var _ = require('underscore');
var Buffer = require('buffer').Buffer;

// VerifyWithParse class
function VerifyWithParse(Parse){
	// Create AccountData Parse Class
	// Generalist class for account information (tokens, profile, provider) for all passport strategies
	var AccountData = Parse.Object.extend("AccountData");
	// Verify callback to be used in PassportJS
	this.verify = function(){
		return function(req, token1, token2, profile, done) {
			// Strategy provider name
			var provider = this.name;
			// Callback level definitions of user and accountData
			var user;
			var accountData;
			// Query parse for an AccountData matching the provider and profile.id from the strategy
			var accountDataQuery = new Parse.Query(AccountData)
			.equalTo("provider", provider)
			.equalTo("userId", profile.id.toString())
			.first()
			.then(function(result){
				// if no result is found, create a new AccountData
				if(!(accountData = result)){
					// set ACL only accesible with Master Key
					var acl = new Parse.ACL();
					acl.setPublicReadAccess(false);
					acl.setPublicWriteAccess(false);
					accountData = new AccountData({
						userId: profile.id.toString()
						, provider: provider
					})
					.setACL(acl);
				};
				// save updated tokens and profile
				accountData.set({
					token1: token1
					, token2: token2
					, profile: profile
				});
				return accountData;
			})
			.then(function(accountData){
				// if a user is on the session we are going to link the accounts instead of creating a new one
				if(req.user){
					return req.user;
				};
				// if there's no owner for the accountdata we'll create a new user and sign it up,
				// we'll use random username and password
				if(!accountData.get("owner")){
					var username = new Buffer(24);
					var password = new Buffer(24);
					_.times(24, function(i) {
						username.set(i, _.random(0, 255));
						password.set(i, _.random(0, 255));
					});
					return new Parse.User()
					.set("username", username.toString('base64'))
					.set("password", password.toString('base64'))
					.signUp();
				}
				return new Parse.Query(Parse.User).get(accountData.get("owner").id);
			})
			.then(function(result){
				user = result;
				// save user as account data owner
				return accountData.save("owner", user);
			})
			.then(function(accountData){
				// create a relation btw user and accountdata on "accounts" user field
				user.relation("accounts").add(accountData);
				return user.save(null, {useMasterKey: true});
			})
			.then(
				function(user){
					return done(null, user);
				}
				, function(error){
					return done(new Error(error.message), null);
				}
			);
		};
	};
	// serialize user's session token
	this.serializeUser = function(user, done){
		done(null, user._sessionToken)
	};
	// find user based on session token
	this.deserializeUser = function(sessionToken, done){
		new Parse.Query(Parse.User)
		.equalTo("sessionToken", sessionToken)
		.first()
		.then(function(user){
			done(null, user);
		}, function(error){
			done(error);
		});
	};
	return this;
}
module.exports = VerifyWithParse;<|endoftext|>


<commit_before>angular.module('percentage', [])
    .filter('percentage', function ($window) {
        return function (input, decimals, suffix) {
            decimals = angular.isNumber(decimals)? decimals :  3;
            suffix = suffix || '%';
            if ($window.isNaN(input)) {
                return '';
            }
            return Math.round(input * Math.pow(10, decimals + 2))/Math.pow(10, decimals) + suffix
        };
    });
<commit_msg>fix minimize build<commit_after>angular.module('percentage', [])
    .filter('percentage', ['$window', function ($window) {
        return function (input, decimals, suffix) {
            decimals = angular.isNumber(decimals)? decimals :  3;
            suffix = suffix || '%';
            if ($window.isNaN(input)) {
                return '';
            }
            return Math.round(input * Math.pow(10, decimals + 2))/Math.pow(10, decimals) + suffix
        };
    }]);
<|endoftext|>