<commit_before>'use strict'

var os = require('os')
var EventEmitter = require('events').EventEmitter
var stringifySafe = require('fast-safe-stringify')
var serializers = require('pino-std-serializers')
var fs = require('fs')
var pump = require('pump')
var flatstr = require('flatstr')
var pretty = require('./pretty')
var events = require('./lib/events')
var levels = require('./lib/levels')
var tools = require('./lib/tools')
var time = require('./lib/time')
var needsMetadata = Symbol.for('needsMetadata')
var isStandardLevelVal = levels.isStandardLevelVal
var isStandardLevel = levels.isStandardLevel
var applyOptions = tools.applyOptions

var LOG_VERSION = 1

var defaultOptions = {
  safe: true,
  name: undefined,
  serializers: {},
  timestamp: time.epochTime,
  slowtime: false,
  extreme: false,
  level: 'info',
  levelVal: undefined,
  prettyPrint: false,
  onTerminated: function (eventName, err) {
    if (err) return process.exit(1)
    process.exit(0)
  },
  base: {
    pid: process.pid,
    hostname: os.hostname()
  },
  enabled: true,
  messageKey: 'msg'
}

var pinoPrototype = Object.create(EventEmitter.prototype, {
  silent: {
    value: tools.noop,
    enumerable: true
  },
  stream: {
    value: process.stdout,
    writable: true
  },
  pino: {
    value: require('./package.json').version,
    enumerable: true
  }
})

var levelMethods = ['fatal', 'error', 'warn', 'info', 'debug', 'trace']
levelMethods.forEach(function (m) {
  Object.defineProperty(pinoPrototype, m, {
    value: tools.genLog(levels.levels[m]),
    enumerable: true,
    writable: true
  })
})

function getLevelVal () {
  return this._levelVal
}
function setLevelVal (num) {
  if (typeof num === 'string') { return this._setLevel(num) }

  if (this.emit) {
    this.emit('level-change', this.levels.labels[num], num, this.levels.labels[this._levelVal], this._levelVal)
  }

  this._levelVal = num

  for (var key in this.levels.values) {
    if (num > this.levels.values[key]) {
      this[key] = tools.noop
      continue
    }
    this[key] = isStandardLevel(key) ? pinoPrototype[key] : tools.genLog(this.levels.values[key])
  }
}
Object.defineProperty(pinoPrototype, 'levelVal', {
  get: getLevelVal,
  set: setLevelVal
})

function _setLevel (level) {
  if (typeof level === 'number') {
    if (!isFinite(level)) {
      throw Error('unknown level ' + level)
    }
    level = this.levels.labels[level]
  }

  if (!this.levels.values[level]) {
    throw Error('unknown level ' + level)
  }
  this.levelVal = this.levels.values[level]
}
Object.defineProperty(pinoPrototype, '_setLevel', {
  value: _setLevel
})

Object.defineProperty(pinoPrototype, '_getLevel', {
  value: function _getLevel (level) {
    return this.levels.labels[this.levelVal]
  }
})

Object.defineProperty(pinoPrototype, 'level', {
  get: pinoPrototype._getLevel,
  set: pinoPrototype._setLevel
})

Object.defineProperty(pinoPrototype, '_lscache', {
  value: tools.copy({}, levels.lscache)
})

Object.defineProperty(
  pinoPrototype,
  'LOG_VERSION',
  {value: LOG_VERSION}
)

function asJson (obj, msg, num) {
  // to catch both null and undefined
  var hasObj = obj !== undefined && obj !== null
  var objError = hasObj && obj instanceof Error
  msg = !msg && objError ? obj.message : msg || undefined
  var data = this._lscache[num] + this.time()
  if (msg !== undefined) {
    // JSON.stringify is safe here
    data += this.messageKeyString + JSON.stringify('' + msg)
  }
  // we need the child bindings added to the output first so that logged
  // objects can take precedence when JSON.parse-ing the resulting log line
  data = data + this.chindings
  var value
  if (hasObj) {
    var notHasOwnProperty = obj.hasOwnProperty === undefined
    if (objError) {
      data += ',"type":"Error","stack":' + this.stringify(obj.stack)
    }
    // if global serializer is set, call it first
    if (this.serializers[Symbol.for('pino.*')]) {
      obj = this.serializers[Symbol.for('pino.*')](obj)
    }
    for (var key in obj) {
      value = obj[key]
      if ((notHasOwnProperty || obj.hasOwnProperty(key)) && value !== undefined) {
        value = this.stringify(this.serializers[key] ? this.serializers[key](value) : value)
        if (value !== undefined) {
          data += ',"' + key + '":' + value
        }
      }
    }
  }
  return data + this.end
}
Object.defineProperty(pinoPrototype, 'asJson', {
  enumerable: true,
  value: asJson
})

function asChindings (that, bindings) {
  if (!bindings) {
    throw Error('missing bindings for child Pino')
  }
  var key
  var value
  var data = that.chindings
  if (that.serializers[Symbol.for('pino.*')]) {
    bindings = that.serializers[Symbol.for('pino.*')](bindings)
  }
  for (key in bindings) {
    value = bindings[key]
    if (key !== 'level' && key !== 'serializers' && bindings.hasOwnProperty(key) && value !== undefined) {
      value = that.serializers[key] ? that.serializers[key](value) : value
      data += ',"' + key + '":' + that.stringify(value)
    }
  }
  return data
}

function child (bindings) {
  var opts = {
    chindings: asChindings(this, bindings),
    level: bindings.level || this.level,
    levelVal: isStandardLevelVal(this.levelVal) ? undefined : this.levelVal,
    serializers: bindings.hasOwnProperty('serializers') ? Object.assign({}, this.serializers, bindings.serializers) : this.serializers
  }

  var _child = Object.create(this)
  _child.stream = this.stream
  applyOptions(_child, opts)
  return _child
}
Object.defineProperty(pinoPrototype, 'child', {
  enumerable: true,
  value: child
})

function pinoWrite (obj, msg, num) {
  var s = this.asJson(obj, msg, num)
  var stream = this.stream
  if (this.cache === null) {
    if (stream[needsMetadata]) {
      stream.lastLevel = num
      stream.lastMsg = msg
      stream.lastObj = obj
      stream.lastLogger = this // for child loggers
    }
    stream.write(flatstr(s))
    return
  }

  this.cache.buf += s
  if (this.cache.buf.length > this.cache.size) {
    stream.write(flatstr(this.cache.buf))
    this.cache.buf = ''
  }
}
Object.defineProperty(pinoPrototype, 'write', {
  value: pinoWrite
})

function flush () {
  if (!this.cache) {
    return
  }

  this.stream.write(flatstr(this.cache.buf))
  this.cache.buf = ''
}
Object.defineProperty(pinoPrototype, 'flush', {
  enumerable: true,
  value: flush
})

function addLevel (name, lvl) {
  if (this.levels.values.hasOwnProperty(name)) return false
  if (this.levels.labels.hasOwnProperty(lvl)) return false
  this.levels.values[name] = lvl
  this.levels.labels[lvl] = name
  this._lscache[lvl] = flatstr('{"level":' + Number(lvl))
  Object.defineProperty(this, name, {
    value: lvl < this._levelVal ? tools.noop : tools.genLog(lvl),
    enumerable: true,
    writable: true
  })

  return true
}
Object.defineProperty(pinoPrototype, 'addLevel', {
  enumerable: true,
  value: addLevel
})

function isLevelEnabled (logLevel) {
  var logLevelVal = this.levels.values[logLevel]
  return logLevelVal && (logLevelVal >= this._levelVal)
}
Object.defineProperty(pinoPrototype, 'isLevelEnabled', {
  enumerable: true,
  value: isLevelEnabled
})

function pino (opts, stream) {
  var iopts = opts
  var istream = stream
  if (iopts && (iopts.writable || iopts._writableState)) {
    istream = iopts
    iopts = defaultOptions
  }
  iopts = Object.assign({}, defaultOptions, iopts)
  if (iopts.extreme && iopts.prettyPrint) throw Error('cannot enable pretty print in extreme mode')
  istream = istream || process.stdout
  var isStdout = istream === process.stdout
  if (!isStdout && iopts.prettyPrint) throw Error('cannot enable pretty print when stream is not process.stdout')
  if (iopts.prettyPrint) {
    var prettyOpts = Object.assign({ messageKey: iopts.messageKey }, iopts.prettyPrint)
    var pstream = pretty(prettyOpts)
    pump(pstream, process.stdout, function (err) {
      if (err) instance.emit('error', err)
    })
    istream = pstream
  }

  // internal options
  iopts.stringify = iopts.safe ? stringifySafe : JSON.stringify
  iopts.formatOpts = {lowres: true}
  iopts.messageKeyString = `,"${iopts.messageKey}":`
  iopts.end = ',"v":' + LOG_VERSION + '}' + (iopts.crlf ? '\r\n' : '\n')
  iopts.cache = !iopts.extreme ? null : {
    size: 4096,
    buf: ''
  }
  iopts.chindings = ''

  if (iopts.enabled === false) {
    iopts.level = 'silent'
  }

  var instance = Object.create(pinoPrototype)
  instance.stream = istream
  tools.defineLevelsProperty(instance)

  instance.stringify = iopts.stringify
  instance.end = iopts.end
  instance.name = iopts.name
  instance.timestamp = iopts.timestamp
  instance.slowtime = iopts.slowtime
  instance.cache = iopts.cache
  instance.formatiopts = iopts.formatiopts
  instance.onTerminated = iopts.onTerminated
  instance.messageKey = iopts.messageKey
  instance.messageKeyString = iopts.messageKeyString

  applyOptions(instance, iopts)

  if (iopts.slowtime) {
    instance.time = time.slowTime
    process.emitWarning('use `timestamp: pino.stdTimeFunctions.slowTime`', '(pino) `slowtime` is deprecated')
  } else if (iopts.timestamp && Function.prototype.isPrototypeOf(iopts.timestamp)) {
    instance.time = iopts.timestamp
  } else if (iopts.timestamp) {
    instance.time = time.epochTime
  } else {
    instance.time = time.nullTime
  }

  if (iopts.cache) setTimeout(waitForFDSettle, 100)

  var settleTries = 0
  function waitForFDSettle () {
    var isBlockable = tools.streamIsBlockable(istream)
    if (isBlockable === false && settleTries > 10) {
      return instance.emit('error', Error('stream must have a file descriptor in extreme mode'))
    } else if (isBlockable === true) {
      return events(instance, extremeModeExitHandler)
    }
    settleTries += 1
    setTimeout(waitForFDSettle, 100)
  }

  function extremeModeExitHandler () {
    var buf = iopts.cache.buf
    if (buf) {
      // We need to block the process exit long enough to flush the buffer
      // to the destination stream. We do that by forcing a synchronous
      // write directly to the stream's file descriptor.
      var fd = (istream.fd) ? istream.fd : istream._handle.fd
      fs.writeSync(fd, buf)
    }
  }

  var base = (typeof iopts.base === 'object') ? iopts.base : defaultOptions.base

  if (iopts.name !== undefined) {
    base = Object.assign({}, base, {
      name: iopts.name
    })
  }

  if (base !== null) {
    instance = instance.child(base)
  }

  return instance
}

tools.defineLevelsProperty(pino)

module.exports = pino
module.exports.stdSerializers = {
  req: serializers.req,
  res: serializers.res,
  err: serializers.err,
  wrapRequestSerializer: serializers.wrapRequestSerializer,
  wrapRespnonseSerializer: serializers.wrapResponseSerializer
}
module.exports.stdTimeFunctions = Object.assign({}, time)
module.exports.pretty = pretty
Object.defineProperty(
  module.exports,
  'LOG_VERSION',
  {value: LOG_VERSION, enumerable: true}
)
<commit_msg>std serializers api typo<commit_after>'use strict'

var os = require('os')
var EventEmitter = require('events').EventEmitter
var stringifySafe = require('fast-safe-stringify')
var serializers = require('pino-std-serializers')
var fs = require('fs')
var pump = require('pump')
var flatstr = require('flatstr')
var pretty = require('./pretty')
var events = require('./lib/events')
var levels = require('./lib/levels')
var tools = require('./lib/tools')
var time = require('./lib/time')
var needsMetadata = Symbol.for('needsMetadata')
var isStandardLevelVal = levels.isStandardLevelVal
var isStandardLevel = levels.isStandardLevel
var applyOptions = tools.applyOptions

var LOG_VERSION = 1

var defaultOptions = {
  safe: true,
  name: undefined,
  serializers: {},
  timestamp: time.epochTime,
  slowtime: false,
  extreme: false,
  level: 'info',
  levelVal: undefined,
  prettyPrint: false,
  onTerminated: function (eventName, err) {
    if (err) return process.exit(1)
    process.exit(0)
  },
  base: {
    pid: process.pid,
    hostname: os.hostname()
  },
  enabled: true,
  messageKey: 'msg'
}

var pinoPrototype = Object.create(EventEmitter.prototype, {
  silent: {
    value: tools.noop,
    enumerable: true
  },
  stream: {
    value: process.stdout,
    writable: true
  },
  pino: {
    value: require('./package.json').version,
    enumerable: true
  }
})

var levelMethods = ['fatal', 'error', 'warn', 'info', 'debug', 'trace']
levelMethods.forEach(function (m) {
  Object.defineProperty(pinoPrototype, m, {
    value: tools.genLog(levels.levels[m]),
    enumerable: true,
    writable: true
  })
})

function getLevelVal () {
  return this._levelVal
}
function setLevelVal (num) {
  if (typeof num === 'string') { return this._setLevel(num) }

  if (this.emit) {
    this.emit('level-change', this.levels.labels[num], num, this.levels.labels[this._levelVal], this._levelVal)
  }

  this._levelVal = num

  for (var key in this.levels.values) {
    if (num > this.levels.values[key]) {
      this[key] = tools.noop
      continue
    }
    this[key] = isStandardLevel(key) ? pinoPrototype[key] : tools.genLog(this.levels.values[key])
  }
}
Object.defineProperty(pinoPrototype, 'levelVal', {
  get: getLevelVal,
  set: setLevelVal
})

function _setLevel (level) {
  if (typeof level === 'number') {
    if (!isFinite(level)) {
      throw Error('unknown level ' + level)
    }
    level = this.levels.labels[level]
  }

  if (!this.levels.values[level]) {
    throw Error('unknown level ' + level)
  }
  this.levelVal = this.levels.values[level]
}
Object.defineProperty(pinoPrototype, '_setLevel', {
  value: _setLevel
})

Object.defineProperty(pinoPrototype, '_getLevel', {
  value: function _getLevel (level) {
    return this.levels.labels[this.levelVal]
  }
})

Object.defineProperty(pinoPrototype, 'level', {
  get: pinoPrototype._getLevel,
  set: pinoPrototype._setLevel
})

Object.defineProperty(pinoPrototype, '_lscache', {
  value: tools.copy({}, levels.lscache)
})

Object.defineProperty(
  pinoPrototype,
  'LOG_VERSION',
  {value: LOG_VERSION}
)

function asJson (obj, msg, num) {
  // to catch both null and undefined
  var hasObj = obj !== undefined && obj !== null
  var objError = hasObj && obj instanceof Error
  msg = !msg && objError ? obj.message : msg || undefined
  var data = this._lscache[num] + this.time()
  if (msg !== undefined) {
    // JSON.stringify is safe here
    data += this.messageKeyString + JSON.stringify('' + msg)
  }
  // we need the child bindings added to the output first so that logged
  // objects can take precedence when JSON.parse-ing the resulting log line
  data = data + this.chindings
  var value
  if (hasObj) {
    var notHasOwnProperty = obj.hasOwnProperty === undefined
    if (objError) {
      data += ',"type":"Error","stack":' + this.stringify(obj.stack)
    }
    // if global serializer is set, call it first
    if (this.serializers[Symbol.for('pino.*')]) {
      obj = this.serializers[Symbol.for('pino.*')](obj)
    }
    for (var key in obj) {
      value = obj[key]
      if ((notHasOwnProperty || obj.hasOwnProperty(key)) && value !== undefined) {
        value = this.stringify(this.serializers[key] ? this.serializers[key](value) : value)
        if (value !== undefined) {
          data += ',"' + key + '":' + value
        }
      }
    }
  }
  return data + this.end
}
Object.defineProperty(pinoPrototype, 'asJson', {
  enumerable: true,
  value: asJson
})

function asChindings (that, bindings) {
  if (!bindings) {
    throw Error('missing bindings for child Pino')
  }
  var key
  var value
  var data = that.chindings
  if (that.serializers[Symbol.for('pino.*')]) {
    bindings = that.serializers[Symbol.for('pino.*')](bindings)
  }
  for (key in bindings) {
    value = bindings[key]
    if (key !== 'level' && key !== 'serializers' && bindings.hasOwnProperty(key) && value !== undefined) {
      value = that.serializers[key] ? that.serializers[key](value) : value
      data += ',"' + key + '":' + that.stringify(value)
    }
  }
  return data
}

function child (bindings) {
  var opts = {
    chindings: asChindings(this, bindings),
    level: bindings.level || this.level,
    levelVal: isStandardLevelVal(this.levelVal) ? undefined : this.levelVal,
    serializers: bindings.hasOwnProperty('serializers') ? Object.assign({}, this.serializers, bindings.serializers) : this.serializers
  }

  var _child = Object.create(this)
  _child.stream = this.stream
  applyOptions(_child, opts)
  return _child
}
Object.defineProperty(pinoPrototype, 'child', {
  enumerable: true,
  value: child
})

function pinoWrite (obj, msg, num) {
  var s = this.asJson(obj, msg, num)
  var stream = this.stream
  if (this.cache === null) {
    if (stream[needsMetadata]) {
      stream.lastLevel = num
      stream.lastMsg = msg
      stream.lastObj = obj
      stream.lastLogger = this // for child loggers
    }
    stream.write(flatstr(s))
    return
  }

  this.cache.buf += s
  if (this.cache.buf.length > this.cache.size) {
    stream.write(flatstr(this.cache.buf))
    this.cache.buf = ''
  }
}
Object.defineProperty(pinoPrototype, 'write', {
  value: pinoWrite
})

function flush () {
  if (!this.cache) {
    return
  }

  this.stream.write(flatstr(this.cache.buf))
  this.cache.buf = ''
}
Object.defineProperty(pinoPrototype, 'flush', {
  enumerable: true,
  value: flush
})

function addLevel (name, lvl) {
  if (this.levels.values.hasOwnProperty(name)) return false
  if (this.levels.labels.hasOwnProperty(lvl)) return false
  this.levels.values[name] = lvl
  this.levels.labels[lvl] = name
  this._lscache[lvl] = flatstr('{"level":' + Number(lvl))
  Object.defineProperty(this, name, {
    value: lvl < this._levelVal ? tools.noop : tools.genLog(lvl),
    enumerable: true,
    writable: true
  })

  return true
}
Object.defineProperty(pinoPrototype, 'addLevel', {
  enumerable: true,
  value: addLevel
})

function isLevelEnabled (logLevel) {
  var logLevelVal = this.levels.values[logLevel]
  return logLevelVal && (logLevelVal >= this._levelVal)
}
Object.defineProperty(pinoPrototype, 'isLevelEnabled', {
  enumerable: true,
  value: isLevelEnabled
})

function pino (opts, stream) {
  var iopts = opts
  var istream = stream
  if (iopts && (iopts.writable || iopts._writableState)) {
    istream = iopts
    iopts = defaultOptions
  }
  iopts = Object.assign({}, defaultOptions, iopts)
  if (iopts.extreme && iopts.prettyPrint) throw Error('cannot enable pretty print in extreme mode')
  istream = istream || process.stdout
  var isStdout = istream === process.stdout
  if (!isStdout && iopts.prettyPrint) throw Error('cannot enable pretty print when stream is not process.stdout')
  if (iopts.prettyPrint) {
    var prettyOpts = Object.assign({ messageKey: iopts.messageKey }, iopts.prettyPrint)
    var pstream = pretty(prettyOpts)
    pump(pstream, process.stdout, function (err) {
      if (err) instance.emit('error', err)
    })
    istream = pstream
  }

  // internal options
  iopts.stringify = iopts.safe ? stringifySafe : JSON.stringify
  iopts.formatOpts = {lowres: true}
  iopts.messageKeyString = `,"${iopts.messageKey}":`
  iopts.end = ',"v":' + LOG_VERSION + '}' + (iopts.crlf ? '\r\n' : '\n')
  iopts.cache = !iopts.extreme ? null : {
    size: 4096,
    buf: ''
  }
  iopts.chindings = ''

  if (iopts.enabled === false) {
    iopts.level = 'silent'
  }

  var instance = Object.create(pinoPrototype)
  instance.stream = istream
  tools.defineLevelsProperty(instance)

  instance.stringify = iopts.stringify
  instance.end = iopts.end
  instance.name = iopts.name
  instance.timestamp = iopts.timestamp
  instance.slowtime = iopts.slowtime
  instance.cache = iopts.cache
  instance.formatiopts = iopts.formatiopts
  instance.onTerminated = iopts.onTerminated
  instance.messageKey = iopts.messageKey
  instance.messageKeyString = iopts.messageKeyString

  applyOptions(instance, iopts)

  if (iopts.slowtime) {
    instance.time = time.slowTime
    process.emitWarning('use `timestamp: pino.stdTimeFunctions.slowTime`', '(pino) `slowtime` is deprecated')
  } else if (iopts.timestamp && Function.prototype.isPrototypeOf(iopts.timestamp)) {
    instance.time = iopts.timestamp
  } else if (iopts.timestamp) {
    instance.time = time.epochTime
  } else {
    instance.time = time.nullTime
  }

  if (iopts.cache) setTimeout(waitForFDSettle, 100)

  var settleTries = 0
  function waitForFDSettle () {
    var isBlockable = tools.streamIsBlockable(istream)
    if (isBlockable === false && settleTries > 10) {
      return instance.emit('error', Error('stream must have a file descriptor in extreme mode'))
    } else if (isBlockable === true) {
      return events(instance, extremeModeExitHandler)
    }
    settleTries += 1
    setTimeout(waitForFDSettle, 100)
  }

  function extremeModeExitHandler () {
    var buf = iopts.cache.buf
    if (buf) {
      // We need to block the process exit long enough to flush the buffer
      // to the destination stream. We do that by forcing a synchronous
      // write directly to the stream's file descriptor.
      var fd = (istream.fd) ? istream.fd : istream._handle.fd
      fs.writeSync(fd, buf)
    }
  }

  var base = (typeof iopts.base === 'object') ? iopts.base : defaultOptions.base

  if (iopts.name !== undefined) {
    base = Object.assign({}, base, {
      name: iopts.name
    })
  }

  if (base !== null) {
    instance = instance.child(base)
  }

  return instance
}

tools.defineLevelsProperty(pino)

module.exports = pino
module.exports.stdSerializers = {
  req: serializers.req,
  res: serializers.res,
  err: serializers.err,
  wrapRequestSerializer: serializers.wrapRequestSerializer,
  wrapResponseSerializer: serializers.wrapResponseSerializer
}
module.exports.stdTimeFunctions = Object.assign({}, time)
module.exports.pretty = pretty
Object.defineProperty(
  module.exports,
  'LOG_VERSION',
  {value: LOG_VERSION, enumerable: true}
)
<|endoftext|>


<commit_before>const list = `
polonox
poloneix
biitrex
biittrex
bitter
bitterx
bittex
bittrax
bittre
bittrec
bittres
bittrex.com
bittrexe
bittrexx
bittrez
bittrix
bittrx
bitttrex
bitrex
bitrexx
bitrix
bitrrex
bttrex
btrex
bttrex
ittrex
bittrex-deposit
poloiex
poloinex
polomiex
polon
poloneex
poloneix
polonex
poloni
poloniax
polonie
poloniec
poloniee
polonieex
poloniek
polonieks
polonies
poloniet
poloniets
poloniex.com
poloniexcold
poloniexe
poloniexs
poloniext
poloniexx
poloniey
poloniez
poloniiex
poloniix
poloniks
poloniox
polonium
polonix
polonniex
polooniex
pooniex
poooniex
plolniex
ploniex
plooniex
poloex
oloniex
pooloniex
poliniex
polniex
poleniex
polionex
pollniex
polloniex
polnoiex
polonyex
polonied
polonixe
blocktardes
blocktrade
bocktrades
changelly.com
changely
shapeshif
shapeshift
randomwhale
randowale
coinpayments
minnowboost
minnowboster
minowbooster
blocktades
bloocktrades
bloctrades
blocktradess
blocktrade
`.trim().split('\n');

export default list;
<commit_msg>Add additional bad actor impersonating exchange<commit_after>const list = `
polonox
poloneix
biitrex
biittrex
bitter
bitterx
bittex
bittrax
bittre
bittrec
bittres
bittrex.com
bittrexe
bittrexx
bittrez
bittrix
bittrx
bitttrex
bitrex
bitrexx
bitrix
bitrrex
bttrex
btrex
bttrex
ittrex
bittrex-deposit
openledgerdex
poloiex
poloinex
polomiex
polon
poloneex
poloneix
polonex
poloni
poloniax
polonie
poloniec
poloniee
polonieex
poloniek
polonieks
polonies
poloniet
poloniets
poloniex.com
poloniexcold
poloniexe
poloniexs
poloniext
poloniexx
poloniey
poloniez
poloniiex
poloniix
poloniks
poloniox
polonium
polonix
polonniex
polooniex
pooniex
poooniex
plolniex
ploniex
plooniex
poloex
oloniex
pooloniex
poliniex
polniex
poleniex
polionex
pollniex
polloniex
polnoiex
polonyex
polonied
polonixe
blocktardes
blocktrade
bocktrades
changelly.com
changely
shapeshif
shapeshift
randomwhale
randowale
coinpayments
minnowboost
minnowboster
minowbooster
blocktades
bloocktrades
bloctrades
blocktradess
blocktrade
`.trim().split('\n');

export default list;
<|endoftext|>


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

import PaggingSize from '../_PaggingSize';
import PaggingPage from '../_PaggingPage';

import './Pagging.css';

export default class Pagging extends Component {

    constructor(props) {

        super(props);

        this.pageChangedHandle = this.pageChangedHandle.bind(this);
        this.pageSizeChangedHandle = this.pageSizeChangedHandle.bind(this);

    }

    pageChangedHandle(page) {

        const {pageSize, onChange} = this.props;

        this.props.page != page && onChange && onChange({
            page,
            pageSize
        });

    }

    pageSizeChangedHandle(pageSize) {

        const {page, onChange} = this.props;

        this.props.pageSize != pageSize && onChange && onChange({
            page,
            pageSize
        });

    }

    render() {

        const {count, page, total, pageSize, selectedCount, selectedCountVisible, pageSizeVisible} = this.props;

        return (

                    {
                        selectedCountVisible ?

                                {`Selected: ${selectedCount}`}

                            :
                            null
                    }

                        {`Total: ${count}`}

                    {
                        pageSizeVisible ?
                            <PaggingSize pageSize={pageSize}
                                         onPageSizeChange={this.pageSizeChangedHandle}/>
                            :
                            null
                    }

                    <PaggingPage page={page}
                                 total={total}
                                 onPageChange={this.pageChangedHandle}/>

        );

    }
};

Pagging.propTypes = {

    /**
     *
     */
    className: PropTypes.string,

    /**
     *
     */
    style: PropTypes.object,

    /**
     * The total of data.
     */
    count: PropTypes.number,

    /**
     *
     */
    page: PropTypes.number,

    /**
     *
     */
    total: PropTypes.number,

    /**
     *
     */
    pageSize: PropTypes.number,

    /**
     *
     */
    selectedCount: PropTypes.number,

    /**
     *
     */
    selectedCountVisible: PropTypes.bool,

    /**
     *
     */
    pageSizeVisible: PropTypes.bool,

    /**
     *
     */
    onChange: PropTypes.func

};

Pagging.defaultProps = {

    className: '',
    style: null,

    count: 0,
    page: 0,
    total: 0,
    pageSize: 10,
    selectedCount: 0,

    selectedCountVisible: false,
    pageSizeVisible: true

};<commit_msg>update Pagging: add pageSizes config<commit_after>import React, {Component} from 'react';
import PropTypes from 'prop-types';

import PaggingSize from '../_PaggingSize';
import PaggingPage from '../_PaggingPage';

import './Pagging.css';

export default class Pagging extends Component {

    constructor(props) {

        super(props);

        this.pageChangedHandle = this.pageChangedHandle.bind(this);
        this.pageSizeChangedHandle = this.pageSizeChangedHandle.bind(this);

    }

    pageChangedHandle(page) {

        const {pageSize, onChange} = this.props;

        this.props.page != page && onChange && onChange({
            page,
            pageSize
        });

    }

    pageSizeChangedHandle(pageSize) {

        const {page, onChange} = this.props;

        this.props.pageSize != pageSize && onChange && onChange({
            page,
            pageSize
        });

    }

    render() {

        const {
            count, page, total, pageSize, pageSizes,
            selectedCount, selectedCountVisible, pageSizeVisible
        } = this.props;

        return (

                    {
                        selectedCountVisible ?

                                {`Selected: ${selectedCount}`}

                            :
                            null
                    }

                        {`Total: ${count}`}

                    {
                        pageSizeVisible ?
                            <PaggingSize pageSize={pageSize}
                                         pageSizes={pageSizes}
                                         onPageSizeChange={this.pageSizeChangedHandle}/>
                            :
                            null
                    }

                    <PaggingPage page={page}
                                 total={total}
                                 onPageChange={this.pageChangedHandle}/>

        );

    }
};

Pagging.propTypes = {

    /**
     *
     */
    className: PropTypes.string,

    /**
     *
     */
    style: PropTypes.object,

    /**
     * The total of data.
     */
    count: PropTypes.number,

    /**
     *
     */
    page: PropTypes.number,

    /**
     *
     */
    total: PropTypes.number,

    /**
     *
     */
    pageSize: PropTypes.number,

    /**
     *
     */
    pageSizes: PropTypes.arrayOf(PropTypes.number),

    /**
     *
     */
    selectedCount: PropTypes.number,

    /**
     *
     */
    selectedCountVisible: PropTypes.bool,

    /**
     *
     */
    pageSizeVisible: PropTypes.bool,

    /**
     *
     */
    onChange: PropTypes.func

};

Pagging.defaultProps = {

    className: '',
    style: null,

    count: 0,
    page: 0,
    total: 0,
    pageSize: 10,
    pageSizes: [5, 10, 15, 20],
    selectedCount: 0,

    selectedCountVisible: false,
    pageSizeVisible: true

};<|endoftext|>


<commit_before>/**
 * @file Pagging component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import PaggingSize from '../_PaggingSize';
import PaggingPage from '../_PaggingPage';
import Valid from '../_vendors/Valid';

class Pagging extends Component {

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    pageChangedHandle = page => {

        const {pageSize, onChange} = this.props;

        this.props.page != page && onChange && onChange({
            page,
            pageSize
        });

    };

    pageSizeChangedHandle = pageSize => {

        const {total, pageSizeValueField, onChange} = this.props,
            originPageSizeValue = typeof this.props.pageSize === 'object' ?
                this.props.pageSize[pageSizeValueField]
                :
                this.props.pageSize,
            pageSizeValue = typeof pageSize === 'object' ?
                pageSize[pageSizeValueField]
                :
                pageSize;

        if (originPageSizeValue !== pageSizeValue) {
            const totalPage = Math.ceil(total / pageSizeValue);
            onChange && onChange({
                page: Valid.range(this.props.page, 0, totalPage - 1),
                pageSize
            });
        }

    };

    render() {

        const {
                className, style, total, page, pageSize, pageSizes, pageSizeValueField, pageSizeDisplayField,
                selectedCount, selectedCountVisible, pageSizeVisible, pageSizeRightIconCls,
                paggingPrevIconCls, paggingNextIconCls, paggingFirstIconCls, paggingLastIconCls,
                paggingCountRenderer, parentEl
            } = this.props,

            totalPage = Math.ceil(total / pageSize),

            paggingClassNames = classNames('pagging', {
                [className]: className
            });

        return (

                    {
                        selectedCountVisible ?

                                {`Selected: ${selectedCount}`}

                            :
                            null
                    }

                        {
                            paggingCountRenderer ?
                                paggingCountRenderer(total, page, totalPage, pageSize, pageSizes)
                                :
                                `Total: ${total}`
                        }

                    {
                        pageSizeVisible ?
                            <PaggingSize pageSize={pageSize}
                                         pageSizes={pageSizes}
                                         valueField={pageSizeValueField}
                                         displayField={pageSizeDisplayField}
                                         parentEl={parentEl}
                                         rightIconCls={pageSizeRightIconCls}
                                         onPageSizeChange={this.pageSizeChangedHandle}/>
                            :
                            null
                    }

                    <PaggingPage page={page}
                                 totalPage={totalPage}
                                 paggingPrevIconCls={paggingPrevIconCls}
                                 paggingNextIconCls={paggingNextIconCls}
                                 paggingFirstIconCls={paggingFirstIconCls}
                                 paggingLastIconCls={paggingLastIconCls}
                                 onPageChange={this.pageChangedHandle}/>

        );

    }
}

Pagging.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * The total of data.
     */
    total: PropTypes.number,

    /**
     * The valid page.
     */
    page: PropTypes.number,

    /**
     * The number of per page.
     */
    pageSize: PropTypes.number,

    /**
     * The array of pageSize.
     */
    pageSizes: PropTypes.array,

    /**
     * The value field name of PageSize. (default: "value")
     */
    pageSizeValueField: PropTypes.string,

    /**
     * The display field name of PageSize. (default: "text")
     */
    pageSizeDisplayField: PropTypes.string,

    /**
     * The total count of selected.
     */
    selectedCount: PropTypes.number,

    /**
     * If true,the selectedCount will show.
     */
    selectedCountVisible: PropTypes.bool,

    /**
     * If false, the pageSize choice box will not show.
     */
    pageSizeVisible: PropTypes.bool,

    /**
     * Use this property to set page size right icon.
     */
    pageSizeRightIconCls: PropTypes.string,

    /**
     * Use this property to set prev button icon.
     */
    paggingPrevIconCls: PropTypes.string,

    /**
     * Use this property to set next button icon.
     */
    paggingNextIconCls: PropTypes.string,

    /**
     * Use this property to set first button icon.
     */
    paggingFirstIconCls: PropTypes.string,

    /**
     * Use this property to set last button icon.
     */
    paggingLastIconCls: PropTypes.string,

    paggingCountRenderer: PropTypes.func,

    /**
     * Callback function fired when Pagging component change.
     */
    onChange: PropTypes.func

};

Pagging.defaultProps = {

    total: 0,
    page: 0,
    pageSize: 10,
    pageSizes: [5, 10, 15, 20],
    pageSizeValueField: 'value',
    pageSizeDisplayField: 'text',
    selectedCount: 0,

    selectedCountVisible: false,
    pageSizeVisible: true,

    pageSizeRightIconCls: 'fas fa-angle-down',
    paggingPrevIconCls: 'fas fa-angle-left',
    paggingNextIconCls: 'fas fa-angle-right',
    paggingFirstIconCls: 'fas fa-angle-double-left',
    paggingLastIconCls: 'fas fa-angle-double-right'

};

export default Pagging;<commit_msg>update Pagging<commit_after>/**
 * @file Pagging component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import PaggingSize from '../_PaggingSize';
import PaggingPage from '../_PaggingPage';

import Valid from '../_vendors/Valid';

class Pagging extends Component {

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    handlePageChanged = page => {

        const {pageSize, onChange} = this.props;

        this.props.page != page && onChange && onChange({
            page,
            pageSize
        });

    };

    handlePageSizeChanged = pageSize => {

        const {total, pageSizeValueField, onChange} = this.props,
            originPageSizeValue = typeof this.props.pageSize === 'object' ?
                this.props.pageSize[pageSizeValueField]
                :
                this.props.pageSize,
            pageSizeValue = typeof pageSize === 'object' ?
                pageSize[pageSizeValueField]
                :
                pageSize;

        if (originPageSizeValue !== pageSizeValue) {
            const totalPage = Math.ceil(total / pageSizeValue);
            onChange && onChange({
                page: Valid.range(this.props.page, 0, totalPage - 1),
                pageSize
            });
        }

    };

    render() {

        const {
                className, style, total, page, pageSize, pageSizes, pageSizeValueField, pageSizeDisplayField,
                selectedCount, selectedCountVisible, pageSizeVisible, pageSizeRightIconCls,
                paggingPrevIconCls, paggingNextIconCls, paggingFirstIconCls, paggingLastIconCls,
                paggingCountRenderer, parentEl
            } = this.props,
            totalPage = Math.ceil(total / pageSize);

        return (

                    {
                        selectedCountVisible ?

                                {`Selected: ${selectedCount}`}

                            :
                            null
                    }

                        {
                            paggingCountRenderer ?
                                paggingCountRenderer(total, page, totalPage, pageSize, pageSizes)
                                :
                                `Total: ${total}`
                        }

                    {
                        pageSizeVisible ?
                            <PaggingSize pageSize={pageSize}
                                         pageSizes={pageSizes}
                                         valueField={pageSizeValueField}
                                         displayField={pageSizeDisplayField}
                                         parentEl={parentEl}
                                         rightIconCls={pageSizeRightIconCls}
                                         onPageSizeChange={this.handlePageSizeChanged}/>
                            :
                            null
                    }

                    <PaggingPage page={page}
                                 totalPage={totalPage}
                                 paggingPrevIconCls={paggingPrevIconCls}
                                 paggingNextIconCls={paggingNextIconCls}
                                 paggingFirstIconCls={paggingFirstIconCls}
                                 paggingLastIconCls={paggingLastIconCls}
                                 onPageChange={this.handlePageChanged}/>

        );

    }
}

Pagging.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * The total of data.
     */
    total: PropTypes.number,

    /**
     * The valid page.
     */
    page: PropTypes.number,

    /**
     * The number of per page.
     */
    pageSize: PropTypes.number,

    /**
     * The array of pageSize.
     */
    pageSizes: PropTypes.array,

    /**
     * The value field name of PageSize. (default: "value")
     */
    pageSizeValueField: PropTypes.string,

    /**
     * The display field name of PageSize. (default: "text")
     */
    pageSizeDisplayField: PropTypes.string,

    /**
     * The total count of selected.
     */
    selectedCount: PropTypes.number,

    /**
     * If true,the selectedCount will show.
     */
    selectedCountVisible: PropTypes.bool,

    /**
     * If false, the pageSize choice box will not show.
     */
    pageSizeVisible: PropTypes.bool,

    /**
     * Use this property to set page size right icon.
     */
    pageSizeRightIconCls: PropTypes.string,

    /**
     * Use this property to set prev button icon.
     */
    paggingPrevIconCls: PropTypes.string,

    /**
     * Use this property to set next button icon.
     */
    paggingNextIconCls: PropTypes.string,

    /**
     * Use this property to set first button icon.
     */
    paggingFirstIconCls: PropTypes.string,

    /**
     * Use this property to set last button icon.
     */
    paggingLastIconCls: PropTypes.string,

    paggingCountRenderer: PropTypes.func,
    parentEl: PropTypes.object,

    /**
     * Callback function fired when Pagging component change.
     */
    onChange: PropTypes.func

};

Pagging.defaultProps = {

    total: 0,
    page: 0,
    pageSize: 10,
    pageSizes: [5, 10, 15, 20],
    pageSizeValueField: 'value',
    pageSizeDisplayField: 'text',
    selectedCount: 0,

    selectedCountVisible: false,
    pageSizeVisible: true,

    pageSizeRightIconCls: 'fas fa-angle-down',
    paggingPrevIconCls: 'fas fa-angle-left',
    paggingNextIconCls: 'fas fa-angle-right',
    paggingFirstIconCls: 'fas fa-angle-double-left',
    paggingLastIconCls: 'fas fa-angle-double-right'

};

export default Pagging;
<|endoftext|>


<commit_before>/**
 * The Audio Component
 *
 * @module aui-audio
 */

var Lang = A.Lang,
    UA = A.UA,
    DOC = A.config.doc,

    owns = A.Object.owns,

    getClassName = A.getClassName,

    CSS_AUDIO_NODE = getClassName('audio', 'node'),

    DEFAULT_PLAYER_PATH = A.config.base + 'aui-audio/assets/player.swf',

    REGEX_FILE_EXTENSION = /\.([^\.]+)$/;

/**
 * A base class for Audio.
 *
 * Check the [live demo](http://alloyui.com/examples/audio/).
 *
 * @class A.Audio
 * @extends A.Component
 * @param {Object} config Object literal specifying widget configuration
 *     properties.
 * @constructor
 * @include http://alloyui.com/examples/audio/basic-markup.html
 * @include http://alloyui.com/examples/audio/basic.js
 */
var AudioImpl = A.Component.create({
    /**
     * Static property provides a string to identify the class.
     *
     * @property NAME
     * @type String
     * @static
     */
    NAME: 'audio',

    /**
     * Static property used to define the default attribute
     * configuration for the Audio.
     *
     * @property ATTRS
     * @type Object
     * @static
     */
    ATTRS: {

        /**
         * Variables used by Flash player.
         *
         * @attribute flashVars
         * @default {}
         * @type Object
         */
        flashVars: {
            value: {},
            validator: Lang.isObject
        },

        /**
         * An additional list of attributes.
         *
         * @attribute fixedAttributes
         * @default {}
         * @type Object
         */
        fixedAttributes: {
            value: {},
            validator: Lang.isObject
        },

        /**
         * URL (on .ogg format) used by Audio to play.
         *
         * @attribute oggUrl
         * @default ''
         * @type String
         */
        oggUrl: {
            value: '',
            validator: Lang.isString
        },

        /**
         * If `true` the render phase will be automatically invoked
         * preventing the `.render()` manual call.
         *
         * @attribute render
         * @default true
         * @type Boolean
         */
        render: {
            value: true,
            validator: Lang.isBoolean
        },

        /**
         * Sets the `aria-role` for Audio.
         *
         * @attribute role
         * @type String
         */
        role: {
            value: 'application',
            validator: Lang.isString
        },

        /**
         * The width of Audio's fallback using Flash.
         *
         * @attribute swfWidth
         * @default 100%
         * @type String
         */
        swfWidth: {
            value: '100%',
            validator: Lang.isString
        },

        /**
         * The height of Audio's fallback using Flash.
         *
         * @attribute swfHeight
         * @default 30
         * @type String
         */
        swfHeight: {
            value: '30',
            validator: Lang.isString
        },

        /**
         * URL (on .swf format) used by Audio to create
         * a fallback player with Flash.
         *
         * @attribute swfUrl
         * @default aui-audio/assets/player.swf
         * @type String
         */
        swfUrl: {
            value: DEFAULT_PLAYER_PATH,
            validator: Lang.isString
        },

        /**
         * The type of audio.
         *
         * @attribute type
         * @default mp3
         * @type String
         */
        type: {
            value: 'mp3',
            validator: Lang.isString
        },

        /**
         * URL used by Audio to play.
         *
         * @attribute url
         * @default ''
         * @type String
         */
        url: {
            value: '',
            validator: Lang.isString
        },

        /**
         * Boolean indicating if use of the WAI-ARIA Roles and States
         * should be enabled.
         *
         * @attribute useARIA
         * @default true
         * @type Boolean
         */
        useARIA: {
            value: true,
            validator: Lang.isBoolean,
            writeOnce: 'initOnly'
        }
    },

    /**
     * Static property used to define the attributes
     * for the bindUI lifecycle phase.
     *
     * @property BIND_UI_ATTRS
     * @type Array
     * @static
     */
    BIND_UI_ATTRS: ['url', 'oggUrl', 'swfUrl', 'fixedAttributes', 'flashVars'],

    /**
     * Static property used to define the attributes
     * for the syncUI lifecycle phase.
     *
     * @property SYNC_UI_ATTRS
     * @type Array
     * @static
     */
    SYNC_UI_ATTRS: ['url', 'oggUrl'],

    prototype: {

        /**
         * Render the Audio component instance. Lifecycle.
         *
         * @method renderUI
         * @protected
         */
        renderUI: function() {
            var instance = this;

            instance._renderAudioTask = A.debounce(instance._renderAudio, 1, instance);
            instance._renderSwfTask = A.debounce(instance._renderSwf, 1, instance);

            instance._renderAudio(!instance.get('oggUrl'));
        },

        /**
         * Bind the events on the Audio UI. Lifecycle.
         *
         * @method bindUI
         * @protected
         */
        bindUI: function() {
            var instance = this;

            instance.publish({
                audioReady: {
                    fireOnce: true
                },
                pause: {},
                play: {}
            });

            instance._audio.on({
                pause: instance._onPause,
                play: instance._onPlay
            });
        },

        /**
         * Sync the Audio UI. Lifecycle.
         *
         * @method syncUI
         * @protected
         */
        syncUI: function() {
            var instance = this;

            if (instance.get('useARIA')) {
                instance.plug(A.Plugin.Aria, {
                    roleName: instance.get('role')
                });
            }
        },

        /**
         * Load audio track.
         *
         * @method load
         */
        load: function() {
            var instance = this;

            if (instance._audio.hasMethod('load')) {
                instance._audio.invoke('load');
            }
        },

        /**
         * Pause audio track.
         *
         * @method pause
         */
        pause: function() {
            var instance = this;

            if (instance._audio.hasMethod('pause')) {
                instance._audio.invoke('pause');
            }
        },

        /**
         * Play audio track.
         *
         * @method play
         */
        play: function() {
            var instance = this;

            if (instance._audio.hasMethod('play')) {
                instance._audio.invoke('play');
            }
        },

        /**
         * Fires on video pause event fires.
         *
         * @method _onPause
         * @param {EventFacade} event
         * @protected
         */
        _onPause: function (event) {
            this.fire('play', {
                cropType: event.type
            });
        },

        /**
         * Fires on video play event fires.
         *
         * @method _onPlay
         * @param {EventFacade} event
         * @protected
         */
        _onPlay: function (event) {
            this.fire('pause', {
                cropType: event.type
            });
        },

        /**
         * Create `source` element
         * using passed type attribute.
         *
         * @method _createSource
         * @param type
         * @protected
         */
        _createSource: function(type) {
            var sourceNode = new A.Node(DOC.createElement('source'));

            sourceNode.attr('type', type);

            return sourceNode;
        },

        /**
         * Render SWF in DOM.
         *
         * @method _renderSwf
         * @protected
         */
        _renderSwf: function() {
            var instance = this;

            var swfUrl = instance.get('swfUrl');

            if (swfUrl) {
                var flashVars = instance.get('flashVars');

                instance._setMedia(flashVars);

                var flashVarString = A.QueryString.stringify(flashVars);

                if (instance._swfId) {
                    instance._audio.removeChild(A.one('#' + instance._swfId));
                }
                else {
                    instance._swfId = A.guid();
                }

                var applicationType = 'type="application/x-shockwave-flash" data="' + swfUrl + '"';

                var movie = '';

                if (UA.ie) {
                    applicationType = 'classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"';

                    movie = '<param name="movie" value="' + swfUrl + '"/>';
                }

                var fixedAttributes = instance.get('fixedAttributes');

                var fixedAttributesParam = [];

                for (var attributeName in fixedAttributes) {
                    if (owns(fixedAttributes, attributeName)) {
                        fixedAttributesParam.push('<param name="', attributeName, '" value="', fixedAttributes[
                            attributeName], '" />');
                    }
                }

                var flashVarsParam = '';

                if (flashVarString) {
                    flashVarsParam = '<param name="flashVars" value="' + flashVarString + '" />';
                }

                var height = instance.get('swfHeight');

                var width = instance.get('swfWidth');

                var tplObj = Lang.sub(
                    AudioImpl.TPL_FLASH, {
                        applicationType: applicationType,
                        id: instance._swfId,
                        fixedAttributes: fixedAttributesParam.join(''),
                        flashVars: flashVarsParam,
                        height: height,
                        movie: movie,
                        width: width
                    }
                );

                instance._audio.append(tplObj);
            }
        },

        /**
         * Render Audio in DOM.
         *
         * @method _renderAudio
         * @param fallback
         * @protected
         */
        _renderAudio: function(fallback) {
            var instance = this;

            var tpl = AudioImpl.TPL_AUDIO;

            if (UA.gecko && fallback) {
                tpl = AudioImpl.TPL_AUDIO_FALLBACK;
            }

            var tplObj = Lang.sub(tpl, [A.guid()]);

            var audio = A.Node.create(tplObj);

            instance.get('contentBox').append(audio);

            instance._audio = audio;

            return audio;
        },

        /**
         * Set media on `flashVars`.
         *
         * @method _setMedia
         * @param flashVars
         * @protected
         */
        _setMedia: function(flashVars) {
            var instance = this;

            if (!owns(flashVars, 'mp3') && !owns(flashVars, 'mp4') && !owns(flashVars, 'flv')) {
                var audioUrl = instance.get('url');

                var type = instance.get('type');

                if (!type) {
                    var typeMatch = REGEX_FILE_EXTENSION.exec(audioUrl);

                    if (typeMatch) {
                        type = typeMatch[1];
                    }
                }

                flashVars[type] = audioUrl;
            }
        },

        /**
         * Set the `fixedAttributes` on the UI.
         *
         * @method _uiSetFixedAttributes
         * @param val
         * @protected
         */
        _uiSetFixedAttributes: function() {
            var instance = this;

            instance._renderSwfTask();
        },

        /**
         * Set the `flashVars` on the UI.
         *
         * @method _uiSetFlashVars
         * @param val
         * @protected
         */
        _uiSetFlashVars: function() {
            var instance = this;

            instance._renderSwfTask();
        },

        /**
         * Set the `oggUrl` on the UI.
         *
         * @method _uiSetOggUrl
         * @param val
         * @protected
         */
        _uiSetOggUrl: function(val) {
            var instance = this;

            if (UA.gecko || UA.opera) {
                var audio = instance._audio;

                var usingAudio = instance._usingAudio();

                if ((!val && usingAudio) || (val && !usingAudio)) {
                    audio.remove(true);

                    audio = instance._renderAudio(!val);
                }

                if (!val) {
                    instance._renderSwfTask();
                }
                else {
                    var sourceOgg = instance._sourceOgg;

                    if (!sourceOgg) {
                        sourceOgg = instance._createSource('audio/ogg');

                        audio.append(sourceOgg);

                        instance._sourceOgg = sourceOgg;
                    }

                    sourceOgg.attr('src', val);
                }
            }
        },

        /**
         * Set the `swfUrl` on the UI.
         *
         * @method _uiSetSwfUrl
         * @param val
         * @protected
         */
        _uiSetSwfUrl: function() {
            var instance = this;

            instance._renderSwfTask();
        },

        /**
         * Set the `url` on the UI.
         *
         * @method _uiSetUrl
         * @param val
         * @protected
         */
        _uiSetUrl: function(val) {
            var instance = this;

            var oggUrl = instance.get('oggUrl');
            var audio = instance._audio;

            var sourceMp3 = instance._sourceMp3;

            if (UA.gecko && !instance._usingAudio()) {
                if (sourceMp3) {
                    sourceMp3.remove(true);

                    instance._sourceMp3 = null;
                }
            }
            else {
                if (audio || !oggUrl) {
                    if (!sourceMp3) {
                        sourceMp3 = instance._createSource('audio/mp3');

                        audio.append(sourceMp3);

                        instance._sourceMp3 = sourceMp3;
                    }

                    sourceMp3.attr('src', val);
                }
            }

            instance._renderSwfTask();
        },

        /**
         * Check if it's a `video` node.
         *
         * @method _usingVideo
         * @protected
         */
        _usingAudio: function() {
            var instance = this;

            return (instance._audio.get('nodeName').toLowerCase() === 'audio');
        }
    }
});

AudioImpl.TPL_AUDIO = '<audio id="{0}" controls="controls" class="' + CSS_AUDIO_NODE + '"></audio>';

AudioImpl.TPL_AUDIO_FALLBACK = '

';

AudioImpl.TPL_FLASH =
    '<object id="{id}" {applicationType} height="{height}" width="{width}">{movie}{fixedAttributes}{flashVars}</object>';

A.Audio = AudioImpl;<commit_msg>AUI-3113 - Publish pause and play events correctly<commit_after>/**
 * The Audio Component
 *
 * @module aui-audio
 */

var Lang = A.Lang,
    UA = A.UA,
    DOC = A.config.doc,

    owns = A.Object.owns,

    getClassName = A.getClassName,

    CSS_AUDIO_NODE = getClassName('audio', 'node'),

    DEFAULT_PLAYER_PATH = A.config.base + 'aui-audio/assets/player.swf',

    REGEX_FILE_EXTENSION = /\.([^\.]+)$/;

/**
 * A base class for Audio.
 *
 * Check the [live demo](http://alloyui.com/examples/audio/).
 *
 * @class A.Audio
 * @extends A.Component
 * @param {Object} config Object literal specifying widget configuration
 *     properties.
 * @constructor
 * @include http://alloyui.com/examples/audio/basic-markup.html
 * @include http://alloyui.com/examples/audio/basic.js
 */
var AudioImpl = A.Component.create({
    /**
     * Static property provides a string to identify the class.
     *
     * @property NAME
     * @type String
     * @static
     */
    NAME: 'audio',

    /**
     * Static property used to define the default attribute
     * configuration for the Audio.
     *
     * @property ATTRS
     * @type Object
     * @static
     */
    ATTRS: {

        /**
         * Variables used by Flash player.
         *
         * @attribute flashVars
         * @default {}
         * @type Object
         */
        flashVars: {
            value: {},
            validator: Lang.isObject
        },

        /**
         * An additional list of attributes.
         *
         * @attribute fixedAttributes
         * @default {}
         * @type Object
         */
        fixedAttributes: {
            value: {},
            validator: Lang.isObject
        },

        /**
         * URL (on .ogg format) used by Audio to play.
         *
         * @attribute oggUrl
         * @default ''
         * @type String
         */
        oggUrl: {
            value: '',
            validator: Lang.isString
        },

        /**
         * If `true` the render phase will be automatically invoked
         * preventing the `.render()` manual call.
         *
         * @attribute render
         * @default true
         * @type Boolean
         */
        render: {
            value: true,
            validator: Lang.isBoolean
        },

        /**
         * Sets the `aria-role` for Audio.
         *
         * @attribute role
         * @type String
         */
        role: {
            value: 'application',
            validator: Lang.isString
        },

        /**
         * The width of Audio's fallback using Flash.
         *
         * @attribute swfWidth
         * @default 100%
         * @type String
         */
        swfWidth: {
            value: '100%',
            validator: Lang.isString
        },

        /**
         * The height of Audio's fallback using Flash.
         *
         * @attribute swfHeight
         * @default 30
         * @type String
         */
        swfHeight: {
            value: '30',
            validator: Lang.isString
        },

        /**
         * URL (on .swf format) used by Audio to create
         * a fallback player with Flash.
         *
         * @attribute swfUrl
         * @default aui-audio/assets/player.swf
         * @type String
         */
        swfUrl: {
            value: DEFAULT_PLAYER_PATH,
            validator: Lang.isString
        },

        /**
         * The type of audio.
         *
         * @attribute type
         * @default mp3
         * @type String
         */
        type: {
            value: 'mp3',
            validator: Lang.isString
        },

        /**
         * URL used by Audio to play.
         *
         * @attribute url
         * @default ''
         * @type String
         */
        url: {
            value: '',
            validator: Lang.isString
        },

        /**
         * Boolean indicating if use of the WAI-ARIA Roles and States
         * should be enabled.
         *
         * @attribute useARIA
         * @default true
         * @type Boolean
         */
        useARIA: {
            value: true,
            validator: Lang.isBoolean,
            writeOnce: 'initOnly'
        }
    },

    /**
     * Static property used to define the attributes
     * for the bindUI lifecycle phase.
     *
     * @property BIND_UI_ATTRS
     * @type Array
     * @static
     */
    BIND_UI_ATTRS: ['url', 'oggUrl', 'swfUrl', 'fixedAttributes', 'flashVars'],

    /**
     * Static property used to define the attributes
     * for the syncUI lifecycle phase.
     *
     * @property SYNC_UI_ATTRS
     * @type Array
     * @static
     */
    SYNC_UI_ATTRS: ['url', 'oggUrl'],

    prototype: {

        /**
         * Render the Audio component instance. Lifecycle.
         *
         * @method renderUI
         * @protected
         */
        renderUI: function() {
            var instance = this;

            instance._renderAudioTask = A.debounce(instance._renderAudio, 1, instance);
            instance._renderSwfTask = A.debounce(instance._renderSwf, 1, instance);

            instance._renderAudio(!instance.get('oggUrl'));

            instance._audio.on(
                'play',
                A.bind('_onPlay', instance)
            );

            instance._audio.on(
                'pause',
                A.bind('_onPause', instance)
            );

        },

        /**
         * Bind the events on the Audio UI. Lifecycle.
         *
         * @method bindUI
         * @protected
         */
        bindUI: function() {
            var instance = this;

            instance.publish(
                'audioReady',
                {
                    fireOnce: true
                }
            );

            instance.publish('play');
            instance.publish('pause');
        },

        /**
         * Sync the Audio UI. Lifecycle.
         *
         * @method syncUI
         * @protected
         */
        syncUI: function() {
            var instance = this;

            if (instance.get('useARIA')) {
                instance.plug(A.Plugin.Aria, {
                    roleName: instance.get('role')
                });
            }
        },

        /**
         * Load audio track.
         *
         * @method load
         */
        load: function() {
            var instance = this;

            if (instance._audio.hasMethod('load')) {
                instance._audio.invoke('load');
            }
        },

        /**
         * Pause audio track.
         *
         * @method pause
         */
        pause: function() {
            var instance = this;

            if (instance._audio.hasMethod('pause')) {
                instance._audio.invoke('pause');
            }
        },

        /**
         * Play audio track.
         *
         * @method play
         */
        play: function() {
            var instance = this;

            if (instance._audio.hasMethod('play')) {
                instance._audio.invoke('play');
            }
        },

        /**
         * Fires on video pause event fires.
         *
         * @method _onPause
         * @param {EventFacade} event
         * @protected
         */
        _onPause: function (event) {
            this.fire('play', {
                cropType: event.type
            });
        },

        /**
         * Fires on video play event fires.
         *
         * @method _onPlay
         * @param {EventFacade} event
         * @protected
         */
        _onPlay: function (event) {
            this.fire('pause', {
                cropType: event.type
            });
        },

        /**
         * Create `source` element
         * using passed type attribute.
         *
         * @method _createSource
         * @param type
         * @protected
         */
        _createSource: function(type) {
            var sourceNode = new A.Node(DOC.createElement('source'));

            sourceNode.attr('type', type);

            return sourceNode;
        },

        /**
         * Render SWF in DOM.
         *
         * @method _renderSwf
         * @protected
         */
        _renderSwf: function() {
            var instance = this;

            var swfUrl = instance.get('swfUrl');

            if (swfUrl) {
                var flashVars = instance.get('flashVars');

                instance._setMedia(flashVars);

                var flashVarString = A.QueryString.stringify(flashVars);

                if (instance._swfId) {
                    instance._audio.removeChild(A.one('#' + instance._swfId));
                }
                else {
                    instance._swfId = A.guid();
                }

                var applicationType = 'type="application/x-shockwave-flash" data="' + swfUrl + '"';

                var movie = '';

                if (UA.ie) {
                    applicationType = 'classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"';

                    movie = '<param name="movie" value="' + swfUrl + '"/>';
                }

                var fixedAttributes = instance.get('fixedAttributes');

                var fixedAttributesParam = [];

                for (var attributeName in fixedAttributes) {
                    if (owns(fixedAttributes, attributeName)) {
                        fixedAttributesParam.push('<param name="', attributeName, '" value="', fixedAttributes[
                            attributeName], '" />');
                    }
                }

                var flashVarsParam = '';

                if (flashVarString) {
                    flashVarsParam = '<param name="flashVars" value="' + flashVarString + '" />';
                }

                var height = instance.get('swfHeight');

                var width = instance.get('swfWidth');

                var tplObj = Lang.sub(
                    AudioImpl.TPL_FLASH, {
                        applicationType: applicationType,
                        id: instance._swfId,
                        fixedAttributes: fixedAttributesParam.join(''),
                        flashVars: flashVarsParam,
                        height: height,
                        movie: movie,
                        width: width
                    }
                );

                instance._audio.append(tplObj);
            }
        },

        /**
         * Render Audio in DOM.
         *
         * @method _renderAudio
         * @param fallback
         * @protected
         */
        _renderAudio: function(fallback) {
            var instance = this;

            var tpl = AudioImpl.TPL_AUDIO;

            if (UA.gecko && fallback) {
                tpl = AudioImpl.TPL_AUDIO_FALLBACK;
            }

            var tplObj = Lang.sub(tpl, [A.guid()]);

            var audio = A.Node.create(tplObj);

            instance.get('contentBox').append(audio);

            instance._audio = audio;

            return audio;
        },

        /**
         * Set media on `flashVars`.
         *
         * @method _setMedia
         * @param flashVars
         * @protected
         */
        _setMedia: function(flashVars) {
            var instance = this;

            if (!owns(flashVars, 'mp3') && !owns(flashVars, 'mp4') && !owns(flashVars, 'flv')) {
                var audioUrl = instance.get('url');

                var type = instance.get('type');

                if (!type) {
                    var typeMatch = REGEX_FILE_EXTENSION.exec(audioUrl);

                    if (typeMatch) {
                        type = typeMatch[1];
                    }
                }

                flashVars[type] = audioUrl;
            }
        },

        /**
         * Set the `fixedAttributes` on the UI.
         *
         * @method _uiSetFixedAttributes
         * @param val
         * @protected
         */
        _uiSetFixedAttributes: function() {
            var instance = this;

            instance._renderSwfTask();
        },

        /**
         * Set the `flashVars` on the UI.
         *
         * @method _uiSetFlashVars
         * @param val
         * @protected
         */
        _uiSetFlashVars: function() {
            var instance = this;

            instance._renderSwfTask();
        },

        /**
         * Set the `oggUrl` on the UI.
         *
         * @method _uiSetOggUrl
         * @param val
         * @protected
         */
        _uiSetOggUrl: function(val) {
            var instance = this;

            if (UA.gecko || UA.opera) {
                var audio = instance._audio;

                var usingAudio = instance._usingAudio();

                if ((!val && usingAudio) || (val && !usingAudio)) {
                    audio.remove(true);

                    audio = instance._renderAudio(!val);
                }

                if (!val) {
                    instance._renderSwfTask();
                }
                else {
                    var sourceOgg = instance._sourceOgg;

                    if (!sourceOgg) {
                        sourceOgg = instance._createSource('audio/ogg');

                        audio.append(sourceOgg);

                        instance._sourceOgg = sourceOgg;
                    }

                    sourceOgg.attr('src', val);
                }
            }
        },

        /**
         * Set the `swfUrl` on the UI.
         *
         * @method _uiSetSwfUrl
         * @param val
         * @protected
         */
        _uiSetSwfUrl: function() {
            var instance = this;

            instance._renderSwfTask();
        },

        /**
         * Set the `url` on the UI.
         *
         * @method _uiSetUrl
         * @param val
         * @protected
         */
        _uiSetUrl: function(val) {
            var instance = this;

            var oggUrl = instance.get('oggUrl');
            var audio = instance._audio;

            var sourceMp3 = instance._sourceMp3;

            if (UA.gecko && !instance._usingAudio()) {
                if (sourceMp3) {
                    sourceMp3.remove(true);

                    instance._sourceMp3 = null;
                }
            }
            else {
                if (audio || !oggUrl) {
                    if (!sourceMp3) {
                        sourceMp3 = instance._createSource('audio/mp3');

                        audio.append(sourceMp3);

                        instance._sourceMp3 = sourceMp3;
                    }

                    sourceMp3.attr('src', val);
                }
            }

            instance._renderSwfTask();
        },

        /**
         * Check if it's a `video` node.
         *
         * @method _usingVideo
         * @protected
         */
        _usingAudio: function() {
            var instance = this;

            return (instance._audio.get('nodeName').toLowerCase() === 'audio');
        }
    }
});

AudioImpl.TPL_AUDIO = '<audio id="{0}" controls="controls" class="' + CSS_AUDIO_NODE + '"></audio>';

AudioImpl.TPL_AUDIO_FALLBACK = '

';

AudioImpl.TPL_FLASH =
    '<object id="{id}" {applicationType} height="{height}" width="{width}">{movie}{fixedAttributes}{flashVars}</object>';

A.Audio = AudioImpl;<|endoftext|>


<commit_before>$(function($){

    var EventBus = function(){
        this._subscribers = {};
    };

    $.extend(EventBus.prototype, {
        on: function(name, subscriber){
            if(!this._subscribers[name]) {
                this._subscribers[name] = [];
            }
            this._subscribers[name].push(subscriber);

            return this;
        },
        off: function(name, subscriber){
            if(this._subscribers[name]) {
                for(var key in this._subscribers[name]) {
                    if(this._subscribers[name][key] === subscriber) {
                        this._subscribers[name].splice(key, 1);
                    }
                }
            }

            return this;
        },
        trigger: function(name, arg){
            if(this._subscribers[name]) {
                for(var key in this._subscribers[name]) {
                    this._subscribers[name][key](arg);
                }
            }

            return this;
        }
    });

    var assertNotEmpty = function(options, name){
        if(!options[name]) {
            throw "options '"+name+"' is required and cannot be null";
        }

        return options[name];
    };

    /**
     * Required options:
     *
     * * eventBus
     * * box: dom element wrapped by jQuery
     *
     * @param options
     * @constructor
     */
    var UploadingFileView = function(options){
        this._init(options);
    };

    $.extend(UploadingFileView.prototype, {
        _init: function(options){
            this._eventBus = assertNotEmpty(options, "eventBus");
            this._box = assertNotEmpty(options, "box");
            this._progressBar = this._box.find(".js-bar");
            this._nameBox = this._box.find(".js-name");
            this._file = null;
            this._visible = true;

            this._setVisibility(false);

            var stopButton = this._box.find(".js-stop");
            var that = this;

            stopButton.on("click", function(){
                if(that._file) {
                    that._eventBus.trigger("uploading-file:delete", that._file);
                }
            });

            this.init(options);
        },
        init: function(options){},
        progressUpdate: function(progress){

            this._setVisibility(true);

            var done = (progress === 100) ? function(){$(this).addClass('full')} : function(){};

            this._progressBar.animate({ width: progress+'%' }, {
                duration: 'long',
                done: done
            });
        },
        _setVisibility: function(visible) {
            if(visible) {
                if(!this._visible) {
                    this._box.show();
                    this._visible = true;
                }
            } else {
                if(this._visible) {
                    this._box.hide();
                    this._visible = false;
                }
            }
        },
        clear: function(){
            this._progressBar.queue(function(){
                $(this).css("width", "0%").removeClass('full').dequeue();
            });
            this._file = null;

            this._setVisibility(false);
            this._update();
        },
        _update: function(){
            this._nameBox.text(this._file ? this._file.name() : "");
        },
        setFile: function(newFile){
            this._file = newFile;

            this._update();
            this._setVisibility(true);
        }
    });

    /**
     * Required options:
     *
     * * eventBus
     * * box
     * * previewBox
     * * errorBox
     * * attributesInput
     * * idInput
     * * uploadingFileBox
     *
     * All except eventBus should be dom elements wrapped by jQuery
     *
     * @param options
     * @constructor
     */
    var View = function(options){
        this._init(options);
    };

    $.extend(View.prototype, {
        _init: function(options){
            var that = this;
            this._eventBus = assertNotEmpty(options, "eventBus");
            this._box = assertNotEmpty(options, "box");
            this._previewBox = assertNotEmpty(options, "previewBox");
            this._errorBox = assertNotEmpty(options, "errorBox");
            this._attributesInput = assertNotEmpty(options, "attributesInput");
            this._idInput = assertNotEmpty(options, "idInput");
            this._uploadingFileBox = assertNotEmpty(options, "uploadingFileBox");
            this._uploadFileButton = assertNotEmpty(options, "uploadFileButton");

            this._uploadingFileView = new UploadingFileView({ eventBus: this._eventBus, box: this._uploadingFileBox });

            this._box.delegate(".js-delete", "click", function(){
                that._eventBus.trigger("file:delete");
            });

            this.init(options);
        },
        init: function(options){},
        clear: function(){
            this._previewBox.html("");
            this._errorBox.text("");
            this._uploadingFileView.clear();
            this._uploadFileButton.text(this._uploadFileButton.data("text-upload"));
        },
        progressUpdate: function(progress){
            this._uploadingFileView.progressUpdate(progress);
        },
        showError: function(error){
            this._errorBox.text(error);
            this._uploadingFileView.clear();
        },
        showPreview: function(response){
            this._uploadingFileView.clear();
            this._previewBox.html(response);
            this._uploadFileButton.text(this._uploadFileButton.data("text-replace"));
        },
        setAttributes: function(attributes){
            this._attributesInput.val(JSON.stringify(attributes));
            this._idInput.val(attributes.id);
        },
        clearAttributes: function(){
            this._attributesInput.val("");
            this._idInput.val("");
        },
        setFile: function(file){
            this._uploadingFileView.setFile(file);
        },
        clearUploadingFile: function(file){
            this._uploadingFileView.clear();
        }
    });

    /**
     * Required options:
     *
     * * eventBus
     * * uploader: object with start() and stop(File) methods
     * * view: dom element wrapped by jQuery
     * * errorMessages: associative array of error messages
     * * previewUrl:  url to retrieve file preview
     *
     * @param options
     * @constructor
     */
    var Controller = function(options){
        this._init(options);
    };

    $.extend(Controller.prototype, {
        _init: function(options) {
            this._eventBus = assertNotEmpty(options, "eventBus");
            this._uploader = assertNotEmpty(options, "uploader");
            this._view = assertNotEmpty(options, "view");
            this._errorMessages = assertNotEmpty(options, "errorMessages");
            this._previewUrl = assertNotEmpty(options, "previewUrl");
            var that = this;

            this._eventBus.on("file:delete",function () {
                that._view.clear();
                that._view.clearAttributes();
            }).on("uploading-file:delete", function (file) {
                that.onUploadingFileDelete(file)
            });
            this.init(options);
        },
        init: function(options){},
        onFileAdded: function(file){
            this._view.clear();
            this._view.setFile(file);
            this._uploader.start();
        },
        onProgress: function(progress){
            this._view.progressUpdate(progress);
        },
        onError: function(response){
            if(typeof(response) !== "object") {
                response = Utils.parseJson(response);
            }
            var error = this._errorMessages[response.message] ? this._errorMessages[response.message] : response.message;
            for(var name in response.messageParameters) {
                error = error.replace(name, response.messageParameters[name]);
            }
            this._view.showError(error);
        },
        onSuccess: function(response){
            var parsedResponse = Utils.parseJson(response);

            this._view.setAttributes(parsedResponse.attributes);
            var that = this;

            $.get(this._previewUrl, { fileId: parsedResponse.attributes.id, info: parsedResponse.attributes.extra_info }, function(response){
                that._view.showPreview(response);
            });
        },
        onUploadingFileDelete: function(file){
            this._view.clearUploadingFile(file);
            this._uploader.stop(file);
        }
    });

    var File = function(id, name){
        this.id = function(){
            return id;
        };

        this.name = function(){
            return name;
        };
    };

    var Utils = {
        parseJson: function(text){
            return JSON.parse(Utils.fixSerializedJson(text));
        },
        //serialized json can be wrapped by <pre> html tags when json is response of request sent by form
        //so trim this tags. This situation occurs when html4 runtime is used in plupload.
        fixSerializedJson: function(text){
            return text.replace(/^\s*<pre[^>]*>/, '').replace(/<\/pre>\s*$/, '');
        }
    };

    window.FloppyFileFormType = {
        View: View,
        UploadingFileView: UploadingFileView,
        Controller: Controller,
        EventBus: EventBus,
        File: File,
        Utils: Utils
    };
}(window.jQuery));<commit_msg>add few hooks for js form control<commit_after>$(function($){

    var EventBus = function(){
        this._subscribers = {};
    };

    $.extend(EventBus.prototype, {
        on: function(name, subscriber){
            if(!this._subscribers[name]) {
                this._subscribers[name] = [];
            }
            this._subscribers[name].push(subscriber);

            return this;
        },
        off: function(name, subscriber){
            if(this._subscribers[name]) {
                for(var key in this._subscribers[name]) {
                    if(this._subscribers[name][key] === subscriber) {
                        this._subscribers[name].splice(key, 1);
                    }
                }
            }

            return this;
        },
        trigger: function(name, arg){
            if(this._subscribers[name]) {
                for(var key in this._subscribers[name]) {
                    this._subscribers[name][key](arg);
                }
            }

            return this;
        }
    });

    var assertNotEmpty = function(options, name){
        if(!options[name]) {
            throw "options '"+name+"' is required and cannot be null";
        }

        return options[name];
    };

    /**
     * Required options:
     *
     * * eventBus
     * * box: dom element wrapped by jQuery
     *
     * @param options
     * @constructor
     */
    var UploadingFileView = function(options){
        this._init(options);
    };

    $.extend(UploadingFileView.prototype, {
        _init: function(options){
            this._eventBus = assertNotEmpty(options, "eventBus");
            this._box = assertNotEmpty(options, "box");
            this._progressBar = this._box.find(".js-bar");
            this._nameBox = this._box.find(".js-name");
            this._file = null;
            this._visible = true;

            this._setVisibility(false);

            var stopButton = this._box.find(".js-stop");
            var that = this;

            stopButton.on("click", function(){
                if(that._file) {
                    that._eventBus.trigger("uploading-file:delete", that._file);
                }
            });

            this.init(options);
        },
        init: function(options){},
        progressUpdate: function(progress){

            this._setVisibility(true);

            var done = (progress === 100) ? function(){$(this).addClass('full')} : function(){};

            this._progressBar.animate({ width: progress+'%' }, {
                duration: 'long',
                done: done
            });
        },
        _setVisibility: function(visible) {
            if(visible) {
                if(!this._visible) {
                    this._box.show();
                    this._visible = true;
                }
            } else {
                if(this._visible) {
                    this._box.hide();
                    this._visible = false;
                }
            }
        },
        clear: function(){
            this._progressBar.queue(function(){
                $(this).css("width", "0%").removeClass('full').dequeue();
            });
            this._file = null;

            this._setVisibility(false);
            this._update();
        },
        _update: function(){
            this._nameBox.text(this._file ? this._file.name() : "");
        },
        setFile: function(newFile){
            this._file = newFile;

            this._update();
            this._setVisibility(true);
        }
    });

    /**
     * Required options:
     *
     * * eventBus
     * * box
     * * previewBox
     * * errorBox
     * * attributesInput
     * * idInput
     * * uploadingFileBox
     *
     * All except eventBus should be dom elements wrapped by jQuery
     *
     * @param options
     * @constructor
     */
    var View = function(options){
        this._init(options);
    };

    $.extend(View.prototype, {
        _init: function(options){
            var that = this;
            this._eventBus = assertNotEmpty(options, "eventBus");
            this._box = assertNotEmpty(options, "box");
            this._previewBox = assertNotEmpty(options, "previewBox");
            this._errorBox = assertNotEmpty(options, "errorBox");
            this._attributesInput = assertNotEmpty(options, "attributesInput");
            this._idInput = assertNotEmpty(options, "idInput");
            this._uploadingFileBox = assertNotEmpty(options, "uploadingFileBox");
            this._uploadFileButton = assertNotEmpty(options, "uploadFileButton");

            this._uploadingFileView = new UploadingFileView({ eventBus: this._eventBus, box: this._uploadingFileBox });

            this._box.delegate(".js-delete", "click", function(){
                that._eventBus.trigger("file:delete");
            });

            this.init(options);
        },
        init: function(options){},
        clear: function(){
            this._previewBox.html("");
            this._errorBox.text("");
            this._uploadingFileView.clear();
            this._uploadFileButton.text(this._uploadFileButton.data("text-upload"));
        },
        progressUpdate: function(progress){
            this._uploadingFileView.progressUpdate(progress);
        },
        showError: function(error){
            this._errorBox.text(error);
            this._uploadingFileView.clear();
        },
        showPreview: function(response){
            this._uploadingFileView.clear();
            this._previewBox.html(response);
            this._uploadFileButton.text(this._uploadFileButton.data("text-replace"));
        },
        setAttributes: function(attributes){
            this._attributesInput.val(JSON.stringify(attributes));
            this._idInput.val(attributes.id);
        },
        clearAttributes: function(){
            this._attributesInput.val("");
            this._idInput.val("");
        },
        setFile: function(file){
            this._uploadingFileView.setFile(file);
        },
        clearUploadingFile: function(file){
            this._uploadingFileView.clear();
        }
    });

    /**
     * Required options:
     *
     * * eventBus
     * * uploader: object with start() and stop(File) methods
     * * view: dom element wrapped by jQuery
     * * errorMessages: associative array of error messages
     * * previewUrl:  url to retrieve file preview
     *
     * @param options
     * @constructor
     */
    var Controller = function(options){
        this._init(options);
    };

    $.extend(Controller.prototype, {
        _init: function(options) {
            this._eventBus = assertNotEmpty(options, "eventBus");
            this._uploader = assertNotEmpty(options, "uploader");
            this._view = assertNotEmpty(options, "view");
            this._errorMessages = assertNotEmpty(options, "errorMessages");
            this._previewUrl = assertNotEmpty(options, "previewUrl");
            var that = this;

            this._eventBus.on("file:delete",function () {
                that._view.clear();
                that._view.clearAttributes();
            }).on("uploading-file:delete", function (file) {
                that.onUploadingFileDelete(file)
            });
            this.init(options);
        },
        init: function(options){},
        onFileAdded: function(file){
            this._view.clear();
            this._view.setFile(file);
            this._uploader.start();
            this._eventBus.trigger("file:added", file);
        },
        onProgress: function(progress){
            this._view.progressUpdate(progress);
        },
        onError: function(response){
            if(typeof(response) !== "object") {
                response = Utils.parseJson(response);
            }
            var error = this._errorMessages[response.message] ? this._errorMessages[response.message] : response.message;
            for(var name in response.messageParameters) {
                error = error.replace(name, response.messageParameters[name]);
            }

            this._eventBus.trigger("file:uploadError", error);
            this._view.showError(error);
        },
        onSuccess: function(response){
            var parsedResponse = Utils.parseJson(response);

            this._eventBus.trigger("file:uploaded", parsedResponse.attributes);
            this._view.setAttributes(parsedResponse.attributes);

            var that = this;

            $.get(this._previewUrl, { fileId: parsedResponse.attributes.id, info: parsedResponse.attributes.extra_info }, function(response){
                that._view.showPreview(response);
            });
        },
        onUploadingFileDelete: function(file){
            this._view.clearUploadingFile(file);
            this._uploader.stop(file);
        }
    });

    var File = function(id, name){
        this.id = function(){
            return id;
        };

        this.name = function(){
            return name;
        };
    };

    var Utils = {
        parseJson: function(text){
            return JSON.parse(Utils.fixSerializedJson(text));
        },
        //serialized json can be wrapped by <pre> html tags when json is response of request sent by form
        //so trim this tags. This situation occurs when html4 runtime is used in plupload.
        fixSerializedJson: function(text){
            return text.replace(/^\s*<pre[^>]*>/, '').replace(/<\/pre>\s*$/, '');
        }
    };

    window.FloppyFileFormType = {
        View: View,
        UploadingFileView: UploadingFileView,
        Controller: Controller,
        EventBus: EventBus,
        File: File,
        Utils: Utils
    };
}(window.jQuery));<|endoftext|>