<commit_before>var config    = require('./config'),
    toString  = ({}).toString,
    win       = window,
    console   = win.console,
    timeout   = win.setTimeout,
    def       = Object.defineProperty,
    OBJECT    = 'object',
    THIS_RE   = /[^\w]this[^\w]/,
    hasClassList = 'classList' in document.documentElement,
    ViewModel // late def

var utils = module.exports = {

    /**
     *  Convert a string template to a dom fragment
     */
    toFragment: require('./fragment'),

    /**
     *  get a value from an object keypath
     */
    get: function (obj, key) {
        /* jshint eqeqeq: false */
        if (key.indexOf('.') < 0) {
            return obj[key]
        }
        var path = key.split('.'),
            d = -1, l = path.length
        while (++d < l && obj != null) {
            obj = obj[path[d]]
        }
        return obj
    },

    /**
     *  set a value to an object keypath
     */
    set: function (obj, key, val) {
        /* jshint eqeqeq: false */
        if (key.indexOf('.') < 0) {
            obj[key] = val
            return
        }
        var path = key.split('.'),
            d = -1, l = path.length - 1
        while (++d < l) {
            if (obj[path[d]] == null) {
                obj[path[d]] = {}
            }
            obj = obj[path[d]]
        }
        obj[path[d]] = val
    },

    /**
     *  return the base segment of a keypath
     */
    baseKey: function (key) {
        return key.indexOf('.') > 0
            ? key.split('.')[0]
            : key
    },

    /**
     *  Create a prototype-less object
     *  which is a better hash/map
     */
    hash: function () {
        return Object.create(null)
    },

    /**
     *  get an attribute and remove it.
     */
    attr: function (el, type) {
        var attr = config.prefix + '-' + type,
            val = el.getAttribute(attr)
        if (val !== null) {
            el.removeAttribute(attr)
        }
        return val
    },

    /**
     *  Define an ienumerable property
     *  This avoids it being included in JSON.stringify
     *  or for...in loops.
     */
    defProtected: function (obj, key, val, enumerable, writable) {
        def(obj, key, {
            value        : val,
            enumerable   : enumerable,
            writable     : writable,
            configurable : true
        })
    },

    /**
     *  A less bullet-proof but more efficient type check
     *  than Object.prototype.toString
     */
    isObject: function (obj) {
        return typeof obj === OBJECT && obj && !Array.isArray(obj)
    },

    /**
     *  A more accurate but less efficient type check
     */
    isTrueObject: function (obj) {
        return toString.call(obj) === '[object Object]'
    },

    /**
     *  Most simple bind
     *  enough for the usecase and fast than native bind()
     */
    bind: function (fn, ctx) {
        return function (arg) {
            return fn.call(ctx, arg)
        }
    },

    /**
     *  Make sure null and undefined output empty string
     */
    guard: function (value) {
        /* jshint eqeqeq: false, eqnull: true */
        return value == null
            ? ''
            : (typeof value == 'object')
                ? JSON.stringify(value)
                : value
    },

    /**
     *  When setting value on the VM, parse possible numbers
     */
    checkNumber: function (value) {
        return (isNaN(value) || value === null || typeof value === 'boolean')
            ? value
            : Number(value)
    },

    /**
     *  simple extend
     */
    extend: function (obj, ext) {
        for (var key in ext) {
            if (obj[key] !== ext[key]) {
                obj[key] = ext[key]
            }
        }
        return obj
    },

    /**
     *  filter an array with duplicates into uniques
     */
    unique: function (arr) {
        var hash = utils.hash(),
            i = arr.length,
            key, res = []
        while (i--) {
            key = arr[i]
            if (hash[key]) continue
            hash[key] = 1
            res.push(key)
        }
        return res
    },

    /**
     *  Convert the object to a ViewModel constructor
     *  if it is not already one
     */
    toConstructor: function (obj) {
        ViewModel = ViewModel || require('./viewmodel')
        return utils.isObject(obj)
            ? ViewModel.extend(obj)
            : typeof obj === 'function'
                ? obj
                : null
    },

    /**
     *  Check if a filter function contains references to `this`
     *  If yes, mark it as a computed filter.
     */
    checkFilter: function (filter) {
        if (THIS_RE.test(filter.toString())) {
            filter.computed = true
        }
    },

    /**
     *  convert certain option values to the desired format.
     */
    processOptions: function (options) {
        var components = options.components,
            partials   = options.partials,
            template   = options.template,
            filters    = options.filters,
            key
        if (components) {
            for (key in components) {
                components[key] = utils.toConstructor(components[key])
            }
        }
        if (partials) {
            for (key in partials) {
                partials[key] = utils.toFragment(partials[key])
            }
        }
        if (filters) {
            for (key in filters) {
                utils.checkFilter(filters[key])
            }
        }
        if (template) {
            options.template = utils.toFragment(template)
        }
    },

    /**
     *  used to defer batch updates
     */
    nextTick: function (cb) {
        timeout(cb, 0)
    },

    /**
     *  add class for IE9
     *  uses classList if available
     */
    addClass: function (el, cls) {
        if (hasClassList) {
            el.classList.add(cls)
        } else {
            var cur = ' ' + el.className + ' '
            if (cur.indexOf(' ' + cls + ' ') < 0) {
                el.className = (cur + cls).trim()
            }
        }
    },

    /**
     *  remove class for IE9
     */
    removeClass: function (el, cls) {
        if (hasClassList) {
            el.classList.remove(cls)
        } else {
            var cur = ' ' + el.className + ' ',
                tar = ' ' + cls + ' '
            while (cur.indexOf(tar) >= 0) {
                cur = cur.replace(tar, ' ')
            }
            el.className = cur.trim()
        }
    },

    /**
     *  Convert an object to Array
     *  used in v-repeat and array filters
     */
    objectToArray: function (obj) {
        var res = [], val, data
        for (var key in obj) {
            val = obj[key]
            data = utils.isObject(val)
                ? val
                : { $value: val }
            data.$key = key
            res.push(data)
        }
        return res
    }
}

enableDebug()
function enableDebug () {
    /**
     *  log for debugging
     */
    utils.log = function (msg) {
        if (config.debug && console) {
            console.log(msg)
        }
    }

    /**
     *  warnings, traces by default
     *  can be suppressed by `silent` option.
     */
    utils.warn = function (msg) {
        if (!config.silent && console) {
            console.warn(msg)
            if (config.debug && console.trace) {
                console.trace()
            }
        }
    }
}<commit_msg>bring back the rAF<commit_after>var config    = require('./config'),
    toString  = ({}).toString,
    win       = window,
    console   = win.console,
    def       = Object.defineProperty,
    OBJECT    = 'object',
    THIS_RE   = /[^\w]this[^\w]/,
    hasClassList = 'classList' in document.documentElement,
    ViewModel // late def

var defer =
    win.requestAnimationFrame ||
    win.webkitRequestAnimationFrame ||
    win.setTimeout

var utils = module.exports = {

    /**
     *  Convert a string template to a dom fragment
     */
    toFragment: require('./fragment'),

    /**
     *  get a value from an object keypath
     */
    get: function (obj, key) {
        /* jshint eqeqeq: false */
        if (key.indexOf('.') < 0) {
            return obj[key]
        }
        var path = key.split('.'),
            d = -1, l = path.length
        while (++d < l && obj != null) {
            obj = obj[path[d]]
        }
        return obj
    },

    /**
     *  set a value to an object keypath
     */
    set: function (obj, key, val) {
        /* jshint eqeqeq: false */
        if (key.indexOf('.') < 0) {
            obj[key] = val
            return
        }
        var path = key.split('.'),
            d = -1, l = path.length - 1
        while (++d < l) {
            if (obj[path[d]] == null) {
                obj[path[d]] = {}
            }
            obj = obj[path[d]]
        }
        obj[path[d]] = val
    },

    /**
     *  return the base segment of a keypath
     */
    baseKey: function (key) {
        return key.indexOf('.') > 0
            ? key.split('.')[0]
            : key
    },

    /**
     *  Create a prototype-less object
     *  which is a better hash/map
     */
    hash: function () {
        return Object.create(null)
    },

    /**
     *  get an attribute and remove it.
     */
    attr: function (el, type) {
        var attr = config.prefix + '-' + type,
            val = el.getAttribute(attr)
        if (val !== null) {
            el.removeAttribute(attr)
        }
        return val
    },

    /**
     *  Define an ienumerable property
     *  This avoids it being included in JSON.stringify
     *  or for...in loops.
     */
    defProtected: function (obj, key, val, enumerable, writable) {
        def(obj, key, {
            value        : val,
            enumerable   : enumerable,
            writable     : writable,
            configurable : true
        })
    },

    /**
     *  A less bullet-proof but more efficient type check
     *  than Object.prototype.toString
     */
    isObject: function (obj) {
        return typeof obj === OBJECT && obj && !Array.isArray(obj)
    },

    /**
     *  A more accurate but less efficient type check
     */
    isTrueObject: function (obj) {
        return toString.call(obj) === '[object Object]'
    },

    /**
     *  Most simple bind
     *  enough for the usecase and fast than native bind()
     */
    bind: function (fn, ctx) {
        return function (arg) {
            return fn.call(ctx, arg)
        }
    },

    /**
     *  Make sure null and undefined output empty string
     */
    guard: function (value) {
        /* jshint eqeqeq: false, eqnull: true */
        return value == null
            ? ''
            : (typeof value == 'object')
                ? JSON.stringify(value)
                : value
    },

    /**
     *  When setting value on the VM, parse possible numbers
     */
    checkNumber: function (value) {
        return (isNaN(value) || value === null || typeof value === 'boolean')
            ? value
            : Number(value)
    },

    /**
     *  simple extend
     */
    extend: function (obj, ext) {
        for (var key in ext) {
            if (obj[key] !== ext[key]) {
                obj[key] = ext[key]
            }
        }
        return obj
    },

    /**
     *  filter an array with duplicates into uniques
     */
    unique: function (arr) {
        var hash = utils.hash(),
            i = arr.length,
            key, res = []
        while (i--) {
            key = arr[i]
            if (hash[key]) continue
            hash[key] = 1
            res.push(key)
        }
        return res
    },

    /**
     *  Convert the object to a ViewModel constructor
     *  if it is not already one
     */
    toConstructor: function (obj) {
        ViewModel = ViewModel || require('./viewmodel')
        return utils.isObject(obj)
            ? ViewModel.extend(obj)
            : typeof obj === 'function'
                ? obj
                : null
    },

    /**
     *  Check if a filter function contains references to `this`
     *  If yes, mark it as a computed filter.
     */
    checkFilter: function (filter) {
        if (THIS_RE.test(filter.toString())) {
            filter.computed = true
        }
    },

    /**
     *  convert certain option values to the desired format.
     */
    processOptions: function (options) {
        var components = options.components,
            partials   = options.partials,
            template   = options.template,
            filters    = options.filters,
            key
        if (components) {
            for (key in components) {
                components[key] = utils.toConstructor(components[key])
            }
        }
        if (partials) {
            for (key in partials) {
                partials[key] = utils.toFragment(partials[key])
            }
        }
        if (filters) {
            for (key in filters) {
                utils.checkFilter(filters[key])
            }
        }
        if (template) {
            options.template = utils.toFragment(template)
        }
    },

    /**
     *  used to defer batch updates
     */
    nextTick: function (cb) {
        defer(cb, 0)
    },

    /**
     *  add class for IE9
     *  uses classList if available
     */
    addClass: function (el, cls) {
        if (hasClassList) {
            el.classList.add(cls)
        } else {
            var cur = ' ' + el.className + ' '
            if (cur.indexOf(' ' + cls + ' ') < 0) {
                el.className = (cur + cls).trim()
            }
        }
    },

    /**
     *  remove class for IE9
     */
    removeClass: function (el, cls) {
        if (hasClassList) {
            el.classList.remove(cls)
        } else {
            var cur = ' ' + el.className + ' ',
                tar = ' ' + cls + ' '
            while (cur.indexOf(tar) >= 0) {
                cur = cur.replace(tar, ' ')
            }
            el.className = cur.trim()
        }
    },

    /**
     *  Convert an object to Array
     *  used in v-repeat and array filters
     */
    objectToArray: function (obj) {
        var res = [], val, data
        for (var key in obj) {
            val = obj[key]
            data = utils.isObject(val)
                ? val
                : { $value: val }
            data.$key = key
            res.push(data)
        }
        return res
    }
}

enableDebug()
function enableDebug () {
    /**
     *  log for debugging
     */
    utils.log = function (msg) {
        if (config.debug && console) {
            console.log(msg)
        }
    }

    /**
     *  warnings, traces by default
     *  can be suppressed by `silent` option.
     */
    utils.warn = function (msg) {
        if (!config.silent && console) {
            console.warn(msg)
            if (config.debug && console.trace) {
                console.trace()
            }
        }
    }
}<|endoftext|>


<commit_before>const _ = require('underscore');
const moment = require('moment');

const cleanDate = date => moment(date, 'YYYYMMDD').format('MMM. Do YYYY');
const sentenceCase = txt => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
const inStr = (needle, objs, keys) => _.map(objs, obj => keys.some(key => obj[key].toLowerCase().indexOf(needle) > -1)).some(el => el);

module.exports = {
  cleanDate: cleanDate,
  sentenceCase: sentenceCase,
  inStr: inStr
}
<commit_msg>Use shorthand exports<commit_after>const _ = require('underscore');
const moment = require('moment');

module.exports.cleanDate = date => moment(date, 'YYYYMMDD').format('MMM. Do YYYY');
module.exports.sentenceCase = x => x.charAt(0).toUpperCase() + x.substr(1).toLowerCase();
module.exports.inStr = (needle, objs, keys) => _.map(objs, obj => keys.some(key => obj[key].toLowerCase().indexOf(needle) > -1)).some(el => el);
<|endoftext|>


<commit_before>export function getInterfaceLanguage() {
  if (!!navigator && !!navigator.language) {
    return navigator.language;
  } else if (!!navigator && !!navigator.languages && !!navigator.languages[0]) {
    return navigator.languages[0];
  } else if (!!navigator && !!navigator.userLanguage) {
    return navigator.userLanguage;
  } else if (!!navigator && !!navigator.browserLanguage) {
    return navigator.browserLanguage;
  }
  return 'en-US';
}

export function validateProps(props) {
  const reservedNames = [
    '_interfaceLanguage',
    '_language',
    '_defaultLanguage',
    '_defaultLanguageFirstLevelKeys',
    '_props',
  ];
  Object.keys(props).forEach(key => {
    if (reservedNames.includes(key)) throw new Error(`${key} cannot be used as a key. It is a reserved word.`)
  });
}<commit_msg>Move to multiple lines to makes things more clear<commit_after>export function getInterfaceLanguage() {
  if (!!navigator && !!navigator.language) {
    return navigator.language;
  } else if (!!navigator && !!navigator.languages && !!navigator.languages[0]) {
    return navigator.languages[0];
  } else if (!!navigator && !!navigator.userLanguage) {
    return navigator.userLanguage;
  } else if (!!navigator && !!navigator.browserLanguage) {
    return navigator.browserLanguage;
  }
  return 'en-US';
}

export function validateProps(props) {
  const reservedNames = [
    '_interfaceLanguage',
    '_language',
    '_defaultLanguage',
    '_defaultLanguageFirstLevelKeys',
    '_props',
  ];
  Object.keys(props).forEach(key => {
    if (reservedNames.includes(key)) {
      throw new Error(`${key} cannot be used as a key. It is a reserved word.`);
    }
  });
}<|endoftext|>


<commit_before>import $ from 'jquery'

import { warn } from './utils/warnings'

var indexOf = [].indexOf

// utils
const unique = function (arr) {
  var item, j, len, result
  result = []
  for (j = 0, len = arr.length; j < len; j++) {
    item = arr[j]
    if (indexOf.call(result, item) < 0) {
      result.push(item)
    }
  }
  return result
}

const defer = function (fn) {
  return setTimeout(fn, 0)
}

const gcd = function (a, b) {
  var c
  while (b) {
    c = a % b
    a = b
    b = c
  }
  return a
}

const once = function (fn) {
  var called, result
  called = false
  result = null
  return function () {
    if (!called) {
      result = fn.apply(this, arguments)
      called = true
    }
    return result
  }
}

const wrapToPromise = function (value) {
  return $.Deferred().resolve(value).promise()
}

// same as promise.then(), but if filter returns promise
// it will be just passed forward without any special behavior
const then = function (pr, doneFilter, failFilter, progressFilter) {
  var compose, df
  df = $.Deferred()
  compose = function (fn1, fn2) {
    if (fn1 && fn2) {
      return function () {
        return fn2.call(this, fn1.apply(this, arguments))
      }
    } else {
      return fn1 || fn2
    }
  }
  pr.then(
    compose(doneFilter, df.resolve),
    compose(failFilter, df.reject),
    compose(progressFilter, df.notify)
  )
  return df.promise()
}

// Build copy of source with only specified methods.
// Handles chaining correctly.
const bindAll = function (source, methods) {
  var target
  target = {}

  $.each(methods, function (i, method) {
    var fn = source[method]

    if ($.isFunction(fn)) {
      target[method] = function (...args) {
        var result = fn.apply(source, args)

        // Fix chaining
        if (result === source) {
          return target
        } else {
          return result
        }
      }
    } else {
      target[method] = fn
    }
  })
  return target
}

const upperCase = function (s) {
  return s.replace(/([A-Z])/g, '_$1').toUpperCase()
}

const publicCallbacks = function (callbacks) {
  var result
  result = callbacks.add
  result.add = callbacks.add
  result.remove = callbacks.remove
  return result
}

const uuid = function () {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
    var r = (Math.random() * 16) | 0
    var v = c === 'x' ? r : (r & 3) | 8

    return v.toString(16)
  })
}

// splitUrlRegex("url") => ["url", "scheme", "host", "path", "query", "fragment"]
const splitUrlRegex =
  /^(?:([^:/?#]+):)?(?:\/\/([^/?#]*))?([^?#]*)\??([^#]*)#?(.*)$/
const uuidRegex =
  /[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/i
const groupIdRegex = new RegExp(`${uuidRegex.source}~[0-9]+`, 'i')
const cdnUrlRegex = new RegExp(
  `^/?(${uuidRegex.source})(?:/(-/(?:[^/]+/)+)?([^/]*))?$`,
  'i'
)
const splitCdnUrl = function (url) {
  return cdnUrlRegex.exec(splitUrlRegex.exec(url)[3])
}
const escapeRegExp = function (str) {
  return str.replace(/[\\-\\[]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&')
}

const globRegexp = function (str, flags = 'i') {
  var parts
  parts = $.map(str.split('*'), escapeRegExp)
  return new RegExp('^' + parts.join('.+') + '$', flags)
}

const normalizeUrl = function (url) {
  var scheme
  // google.com/ → google.com
  // /google.com/ → /google.com
  // //google.com/ → http://google.com
  // http://google.com/ → http://google.com
  scheme = document.location.protocol
  if (scheme !== 'http:') {
    scheme = 'https:'
  }
  return url.replace(/^\/\//, scheme + '//').replace(/\/+$/, '')
}
const fitText = function (text, max) {
  if (text.length > max) {
    const head = Math.ceil((max - 3) / 2)
    const tail = Math.floor((max - 3) / 2)
    return text.slice(0, head) + '...' + text.slice(-tail)
  } else {
    return text
  }
}

const fitSizeInCdnLimit = function (objSize) {
  return fitSize(objSize, [2048, 2048])
}

const fitSize = function (objSize, boxSize, upscale) {
  var heightRation, widthRatio
  if (objSize[0] > boxSize[0] || objSize[1] > boxSize[1] || upscale) {
    widthRatio = boxSize[0] / objSize[0]
    heightRation = boxSize[1] / objSize[1]
    if (!boxSize[0] || (boxSize[1] && widthRatio > heightRation)) {
      return [Math.round(heightRation * objSize[0]), boxSize[1]]
    } else {
      return [boxSize[0], Math.round(widthRatio * objSize[1])]
    }
  } else {
    return objSize.slice()
  }
}

const applyCropCoordsToInfo = function (info, crop, size, coords) {
  var downscale, h, modifiers, prefered, upscale, w, wholeImage
  ;({ width: w, height: h } = coords)
  prefered = crop.preferedSize
  modifiers = ''
  wholeImage = w === size[0] && h === size[1]
  if (!wholeImage) {
    modifiers += `-/crop/${w}x${h}/${coords.left},${coords.top}/`
  }
  downscale = crop.downscale && (w > prefered[0] || h > prefered[1])
  upscale = crop.upscale && (w < prefered[0] || h < prefered[1])
  if (downscale || upscale) {
    ;[coords.sw, coords.sh] = prefered
    modifiers += `-/resize/${prefered.join('x')}/`
  } else if (!wholeImage) {
    modifiers += '-/preview/'
  }
  info = $.extend({}, info)
  info.cdnUrlModifiers = modifiers
  info.cdnUrl = `${info.originalUrl}${modifiers || ''}`
  info.crop = coords
  return info
}

const fileInput = function (container, settings, fn) {
  var accept, input, run
  input = null
  accept = settings.inputAcceptTypes
  if (accept === '') {
    accept = settings.imagesOnly ? 'image/*' : null
  }

  ;(run = function () {
    input = (
      settings.multiple
        ? $('<input type="file" multiple>')
        : $('<input type="file">')
    )
      .attr('accept', accept)
      .css({
        position: 'absolute',
        top: 0,
        opacity: 0,
        margin: 0,
        padding: 0,
        width: 'auto',
        height: 'auto',
        cursor: container.css('cursor')
      })
      .on('change', function () {
        fn(this)
        $(this).hide()
        return run()
      })
    return container.append(input)
  })()

  return container
    .css({
      position: 'relative',
      overflow: 'hidden'
      // to make it posible to set `cursor:pointer` on button
      // http://stackoverflow.com/a/9182787/478603
    })
    .mousemove(function (e) {
      var left, top, width
      ;({ left, top } = $(this).offset())
      width = input.width()
      return input.css({
        left: e.pageX - left - width + 10,
        top: e.pageY - top - 10
      })
    })
}

const fileSelectDialog = function (container, settings, fn, attributes = {}) {
  var accept
  accept = settings.inputAcceptTypes
  if (accept === '') {
    accept = settings.imagesOnly ? 'image/*' : null
  }
  return $(
    settings.multiple ? '<input type="file" multiple>' : '<input type="file">'
  )
    .attr('accept', accept)
    .attr(attributes)
    .css({
      position: 'fixed',
      bottom: 0,
      opacity: 0
    })
    .on('change', function () {
      fn(this)
      return $(this).remove()
    })
    .appendTo(container)
    .focus()
    .click()
    .hide()
}

const fileSizeLabels = 'B KB MB GB TB PB EB ZB YB'.split(' ')

const readableFileSize = function (
  value,
  onNaN = '',
  prefix = '',
  postfix = ''
) {
  var digits, fixedTo, i, threshold
  value = parseInt(value, 10)
  if (isNaN(value)) {
    return onNaN
  }
  digits = 2
  i = 0
  threshold = 1000 - 5 * Math.pow(10, 2 - Math.max(digits, 3))
  while (value > threshold && i < fileSizeLabels.length - 1) {
    i++
    value /= 1024
  }
  value += 0.000000000000001
  fixedTo = Math.max(0, digits - Math.floor(value).toFixed(0).length)
  // fixed → number → string, to trim trailing zeroes
  value = Number(value.toFixed(fixedTo))
  // eslint-disable-next-line no-irregular-whitespace
  return `${prefix}${value} ${fileSizeLabels[i]}${postfix}`
}

const ajaxDefaults = {
  dataType: 'json',
  crossDomain: true,
  cache: false
}

const jsonp = function (url, type, data, settings = {}) {
  return $.ajax($.extend({ url, type, data }, settings, ajaxDefaults)).then(
    function (data) {
      if (data.error) {
        let message, code
        if (typeof data.error === 'string') {
          // /from_url/state/ case
          message = data.error
          code = data.error_code
        } else {
          // other cases (direct/multipart/group)
          message = data.error.content
          code = data.error.error_code
        }
        return $.Deferred().reject({ message, code })
      }

      return data
    },
    function (_, textStatus, errorThrown) {
      var text
      text = `${textStatus} (${errorThrown})`
      warn(`JSONP unexpected error: ${text} while loading ${url}`)

      return text
    }
  )
}

const canvasToBlob = function (canvas, type, quality, callback) {
  var arr, binStr, dataURL, i, j, ref
  if (window.HTMLCanvasElement.prototype.toBlob) {
    return canvas.toBlob(callback, type, quality)
  }
  dataURL = canvas.toDataURL(type, quality)
  dataURL = dataURL.split(',')
  binStr = window.atob(dataURL[1])
  arr = new Uint8Array(binStr.length)
  for (i = j = 0, ref = binStr.length; j < ref; i = j += 1) {
    arr[i] = binStr.charCodeAt(i)
  }
  return callback(
    new window.Blob([arr], {
      type: /:(.+\/.+);/.exec(dataURL[0])[1]
    })
  )
}

const taskRunner = function (capacity) {
  var queue, release, run, running
  running = 0
  queue = []
  release = function () {
    var task

    if (queue.length) {
      task = queue.shift()

      return defer(function () {
        return task(release)
      })
    } else {
      running -= 1

      return running
    }
  }

  run = function (task) {
    if (!capacity || running < capacity) {
      running += 1

      return defer(function () {
        return task(release)
      })
    } else {
      return queue.push(task)
    }
  }

  return run
}
// This is work around bug in jquery https://github.com/jquery/jquery/issues/2013
// action, add listener, callbacks,
// ... .then handlers, argument index, [final state]
const pipeTuples = [
  ['notify', 'progress', 2],
  ['resolve', 'done', 0],
  ['reject', 'fail', 1]
]

const fixedPipe = function (promise, ...fns) {
  return $.Deferred(function (newDefer) {
    return $.each(pipeTuples, function (i, tuple) {
      var fn
      // Map tuples (progress, done, fail) to arguments (done, fail, progress)
      fn = $.isFunction(fns[tuple[2]]) && fns[tuple[2]]
      return promise[tuple[1]](function () {
        var returned
        returned = fn && fn.apply(this, arguments)
        if (returned && $.isFunction(returned.promise)) {
          return returned
            .promise()
            .progress(newDefer.notify)
            .done(newDefer.resolve)
            .fail(newDefer.reject)
        } else {
          return newDefer[tuple[0] + 'With'](
            this === promise ? newDefer.promise() : this,
            fn ? [returned] : arguments
          )
        }
      })
    })
  }).promise()
}

export {
  unique,
  defer,
  gcd,
  once,
  wrapToPromise,
  then,
  bindAll,
  upperCase,
  publicCallbacks,
  uuid,
  splitUrlRegex,
  uuidRegex,
  groupIdRegex,
  cdnUrlRegex,
  splitCdnUrl,
  escapeRegExp,
  globRegexp,
  normalizeUrl,
  fitText,
  fitSizeInCdnLimit,
  fitSize,
  applyCropCoordsToInfo,
  fileInput,
  fileSelectDialog,
  fileSizeLabels,
  readableFileSize,
  ajaxDefaults,
  jsonp,
  canvasToBlob,
  taskRunner,
  fixedPipe
}
<commit_msg>feat: allow to select HEIC images when `imagesOnly` enabled (#881)<commit_after>import $ from 'jquery'

import { warn } from './utils/warnings'

var indexOf = [].indexOf

// utils
const unique = function (arr) {
  var item, j, len, result
  result = []
  for (j = 0, len = arr.length; j < len; j++) {
    item = arr[j]
    if (indexOf.call(result, item) < 0) {
      result.push(item)
    }
  }
  return result
}

const defer = function (fn) {
  return setTimeout(fn, 0)
}

const gcd = function (a, b) {
  var c
  while (b) {
    c = a % b
    a = b
    b = c
  }
  return a
}

const once = function (fn) {
  var called, result
  called = false
  result = null
  return function () {
    if (!called) {
      result = fn.apply(this, arguments)
      called = true
    }
    return result
  }
}

const wrapToPromise = function (value) {
  return $.Deferred().resolve(value).promise()
}

// same as promise.then(), but if filter returns promise
// it will be just passed forward without any special behavior
const then = function (pr, doneFilter, failFilter, progressFilter) {
  var compose, df
  df = $.Deferred()
  compose = function (fn1, fn2) {
    if (fn1 && fn2) {
      return function () {
        return fn2.call(this, fn1.apply(this, arguments))
      }
    } else {
      return fn1 || fn2
    }
  }
  pr.then(
    compose(doneFilter, df.resolve),
    compose(failFilter, df.reject),
    compose(progressFilter, df.notify)
  )
  return df.promise()
}

// Build copy of source with only specified methods.
// Handles chaining correctly.
const bindAll = function (source, methods) {
  var target
  target = {}

  $.each(methods, function (i, method) {
    var fn = source[method]

    if ($.isFunction(fn)) {
      target[method] = function (...args) {
        var result = fn.apply(source, args)

        // Fix chaining
        if (result === source) {
          return target
        } else {
          return result
        }
      }
    } else {
      target[method] = fn
    }
  })
  return target
}

const upperCase = function (s) {
  return s.replace(/([A-Z])/g, '_$1').toUpperCase()
}

const publicCallbacks = function (callbacks) {
  var result
  result = callbacks.add
  result.add = callbacks.add
  result.remove = callbacks.remove
  return result
}

const uuid = function () {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
    var r = (Math.random() * 16) | 0
    var v = c === 'x' ? r : (r & 3) | 8

    return v.toString(16)
  })
}

// splitUrlRegex("url") => ["url", "scheme", "host", "path", "query", "fragment"]
const splitUrlRegex =
  /^(?:([^:/?#]+):)?(?:\/\/([^/?#]*))?([^?#]*)\??([^#]*)#?(.*)$/
const uuidRegex =
  /[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/i
const groupIdRegex = new RegExp(`${uuidRegex.source}~[0-9]+`, 'i')
const cdnUrlRegex = new RegExp(
  `^/?(${uuidRegex.source})(?:/(-/(?:[^/]+/)+)?([^/]*))?$`,
  'i'
)
const splitCdnUrl = function (url) {
  return cdnUrlRegex.exec(splitUrlRegex.exec(url)[3])
}
const escapeRegExp = function (str) {
  return str.replace(/[\\-\\[]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&')
}

const globRegexp = function (str, flags = 'i') {
  var parts
  parts = $.map(str.split('*'), escapeRegExp)
  return new RegExp('^' + parts.join('.+') + '$', flags)
}

const normalizeUrl = function (url) {
  var scheme
  // google.com/ → google.com
  // /google.com/ → /google.com
  // //google.com/ → http://google.com
  // http://google.com/ → http://google.com
  scheme = document.location.protocol
  if (scheme !== 'http:') {
    scheme = 'https:'
  }
  return url.replace(/^\/\//, scheme + '//').replace(/\/+$/, '')
}
const fitText = function (text, max) {
  if (text.length > max) {
    const head = Math.ceil((max - 3) / 2)
    const tail = Math.floor((max - 3) / 2)
    return text.slice(0, head) + '...' + text.slice(-tail)
  } else {
    return text
  }
}

const fitSizeInCdnLimit = function (objSize) {
  return fitSize(objSize, [2048, 2048])
}

const fitSize = function (objSize, boxSize, upscale) {
  var heightRation, widthRatio
  if (objSize[0] > boxSize[0] || objSize[1] > boxSize[1] || upscale) {
    widthRatio = boxSize[0] / objSize[0]
    heightRation = boxSize[1] / objSize[1]
    if (!boxSize[0] || (boxSize[1] && widthRatio > heightRation)) {
      return [Math.round(heightRation * objSize[0]), boxSize[1]]
    } else {
      return [boxSize[0], Math.round(widthRatio * objSize[1])]
    }
  } else {
    return objSize.slice()
  }
}

const applyCropCoordsToInfo = function (info, crop, size, coords) {
  var downscale, h, modifiers, prefered, upscale, w, wholeImage
  ;({ width: w, height: h } = coords)
  prefered = crop.preferedSize
  modifiers = ''
  wholeImage = w === size[0] && h === size[1]
  if (!wholeImage) {
    modifiers += `-/crop/${w}x${h}/${coords.left},${coords.top}/`
  }
  downscale = crop.downscale && (w > prefered[0] || h > prefered[1])
  upscale = crop.upscale && (w < prefered[0] || h < prefered[1])
  if (downscale || upscale) {
    ;[coords.sw, coords.sh] = prefered
    modifiers += `-/resize/${prefered.join('x')}/`
  } else if (!wholeImage) {
    modifiers += '-/preview/'
  }
  info = $.extend({}, info)
  info.cdnUrlModifiers = modifiers
  info.cdnUrl = `${info.originalUrl}${modifiers || ''}`
  info.crop = coords
  return info
}

const imagesOnlyAcceptTypes = `image/*,image/heic`

const fileInput = function (container, settings, fn) {
  var accept, input, run
  input = null
  accept = settings.inputAcceptTypes
  if (accept === '') {
    accept = settings.imagesOnly ? imagesOnlyAcceptTypes : null
  }

  ;(run = function () {
    input = (
      settings.multiple
        ? $('<input type="file" multiple>')
        : $('<input type="file">')
    )
      .attr('accept', accept)
      .css({
        position: 'absolute',
        top: 0,
        opacity: 0,
        margin: 0,
        padding: 0,
        width: 'auto',
        height: 'auto',
        cursor: container.css('cursor')
      })
      .on('change', function () {
        fn(this)
        $(this).hide()
        return run()
      })
    return container.append(input)
  })()

  return container
    .css({
      position: 'relative',
      overflow: 'hidden'
      // to make it posible to set `cursor:pointer` on button
      // http://stackoverflow.com/a/9182787/478603
    })
    .mousemove(function (e) {
      var left, top, width
      ;({ left, top } = $(this).offset())
      width = input.width()
      return input.css({
        left: e.pageX - left - width + 10,
        top: e.pageY - top - 10
      })
    })
}

const fileSelectDialog = function (container, settings, fn, attributes = {}) {
  var accept
  accept = settings.inputAcceptTypes
  if (accept === '') {
    accept = settings.imagesOnly ? imagesOnlyAcceptTypes : null
  }
  return $(
    settings.multiple ? '<input type="file" multiple>' : '<input type="file">'
  )
    .attr('accept', accept)
    .attr(attributes)
    .css({
      position: 'fixed',
      bottom: 0,
      opacity: 0
    })
    .on('change', function () {
      fn(this)
      return $(this).remove()
    })
    .appendTo(container)
    .focus()
    .click()
    .hide()
}

const fileSizeLabels = 'B KB MB GB TB PB EB ZB YB'.split(' ')

const readableFileSize = function (
  value,
  onNaN = '',
  prefix = '',
  postfix = ''
) {
  var digits, fixedTo, i, threshold
  value = parseInt(value, 10)
  if (isNaN(value)) {
    return onNaN
  }
  digits = 2
  i = 0
  threshold = 1000 - 5 * Math.pow(10, 2 - Math.max(digits, 3))
  while (value > threshold && i < fileSizeLabels.length - 1) {
    i++
    value /= 1024
  }
  value += 0.000000000000001
  fixedTo = Math.max(0, digits - Math.floor(value).toFixed(0).length)
  // fixed → number → string, to trim trailing zeroes
  value = Number(value.toFixed(fixedTo))
  // eslint-disable-next-line no-irregular-whitespace
  return `${prefix}${value} ${fileSizeLabels[i]}${postfix}`
}

const ajaxDefaults = {
  dataType: 'json',
  crossDomain: true,
  cache: false
}

const jsonp = function (url, type, data, settings = {}) {
  return $.ajax($.extend({ url, type, data }, settings, ajaxDefaults)).then(
    function (data) {
      if (data.error) {
        let message, code
        if (typeof data.error === 'string') {
          // /from_url/state/ case
          message = data.error
          code = data.error_code
        } else {
          // other cases (direct/multipart/group)
          message = data.error.content
          code = data.error.error_code
        }
        return $.Deferred().reject({ message, code })
      }

      return data
    },
    function (_, textStatus, errorThrown) {
      var text
      text = `${textStatus} (${errorThrown})`
      warn(`JSONP unexpected error: ${text} while loading ${url}`)

      return text
    }
  )
}

const canvasToBlob = function (canvas, type, quality, callback) {
  var arr, binStr, dataURL, i, j, ref
  if (window.HTMLCanvasElement.prototype.toBlob) {
    return canvas.toBlob(callback, type, quality)
  }
  dataURL = canvas.toDataURL(type, quality)
  dataURL = dataURL.split(',')
  binStr = window.atob(dataURL[1])
  arr = new Uint8Array(binStr.length)
  for (i = j = 0, ref = binStr.length; j < ref; i = j += 1) {
    arr[i] = binStr.charCodeAt(i)
  }
  return callback(
    new window.Blob([arr], {
      type: /:(.+\/.+);/.exec(dataURL[0])[1]
    })
  )
}

const taskRunner = function (capacity) {
  var queue, release, run, running
  running = 0
  queue = []
  release = function () {
    var task

    if (queue.length) {
      task = queue.shift()

      return defer(function () {
        return task(release)
      })
    } else {
      running -= 1

      return running
    }
  }

  run = function (task) {
    if (!capacity || running < capacity) {
      running += 1

      return defer(function () {
        return task(release)
      })
    } else {
      return queue.push(task)
    }
  }

  return run
}
// This is work around bug in jquery https://github.com/jquery/jquery/issues/2013
// action, add listener, callbacks,
// ... .then handlers, argument index, [final state]
const pipeTuples = [
  ['notify', 'progress', 2],
  ['resolve', 'done', 0],
  ['reject', 'fail', 1]
]

const fixedPipe = function (promise, ...fns) {
  return $.Deferred(function (newDefer) {
    return $.each(pipeTuples, function (i, tuple) {
      var fn
      // Map tuples (progress, done, fail) to arguments (done, fail, progress)
      fn = $.isFunction(fns[tuple[2]]) && fns[tuple[2]]
      return promise[tuple[1]](function () {
        var returned
        returned = fn && fn.apply(this, arguments)
        if (returned && $.isFunction(returned.promise)) {
          return returned
            .promise()
            .progress(newDefer.notify)
            .done(newDefer.resolve)
            .fail(newDefer.reject)
        } else {
          return newDefer[tuple[0] + 'With'](
            this === promise ? newDefer.promise() : this,
            fn ? [returned] : arguments
          )
        }
      })
    })
  }).promise()
}

export {
  unique,
  defer,
  gcd,
  once,
  wrapToPromise,
  then,
  bindAll,
  upperCase,
  publicCallbacks,
  uuid,
  splitUrlRegex,
  uuidRegex,
  groupIdRegex,
  cdnUrlRegex,
  splitCdnUrl,
  escapeRegExp,
  globRegexp,
  normalizeUrl,
  fitText,
  fitSizeInCdnLimit,
  fitSize,
  applyCropCoordsToInfo,
  fileInput,
  fileSelectDialog,
  fileSizeLabels,
  readableFileSize,
  ajaxDefaults,
  jsonp,
  canvasToBlob,
  taskRunner,
  fixedPipe
}
<|endoftext|>


<commit_before>var VENDOR_PREFIXES = ['', 'webkit', 'moz', 'MS', 'ms', 'o'];
var TEST_ELEMENT = document.createElement('div');

var TYPE_FUNCTION = 'function';

var round = Math.round;
var abs = Math.abs;
var now = Date.now;

/**
 * set a timeout with a given scope
 * @param {Function} fn
 * @param {Number} timeout
 * @param {Object} context
 * @returns {number}
 */
function setTimeoutContext(fn, timeout, context) {
    return setTimeout(bindFn(fn, context), timeout);
}

/**
 * if the argument is an array, we want to execute the fn on each entry
 * if it aint an array we don't want to do a thing.
 * this is used by all the methods that accept a single and array argument.
 * @param {*|Array} arg
 * @param {String} fn
 * @param {Object} [context]
 * @returns {Boolean}
 */
function invokeArrayArg(arg, fn, context) {
    if (Array.isArray(arg)) {
        each(arg, context[fn], context);
        return true;
    }
    return false;
}

/**
 * walk objects and arrays
 * @param {Object} obj
 * @param {Function} iterator
 * @param {Object} context
 */
function each(obj, iterator, context) {
    var i;

    if (!obj) {
        return;
    }

    if (obj.forEach) {
        obj.forEach(iterator, context);
    } else if (obj.length !== undefined) {
        i = 0;
        while (i < obj.length) {
            iterator.call(context, obj[i], i, obj);
            i++;
        }
    } else {
        for (i in obj) {
            obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj);
        }
    }
}

/**
 * extend object.
 * means that properties in dest will be overwritten by the ones in src.
 * @param {Object} dest
 * @param {Object} src
 * @param {Boolean} [merge]
 * @returns {Object} dest
 */
function extend(dest, src, merge) {
    var keys = Object.keys(src);
    var i = 0;
    while (i < keys.length) {
        if (!merge || (merge && dest[keys[i]] === undefined)) {
            dest[keys[i]] = src[keys[i]];
        }
        i++;
    }
    return dest;
}

/**
 * merge the values from src in the dest.
 * means that properties that exist in dest will not be overwritten by src
 * @param {Object} dest
 * @param {Object} src
 * @returns {Object} dest
 */
function merge(dest, src) {
    return extend(dest, src, true);
}

/**
 * simple class inheritance
 * @param {Function} child
 * @param {Function} base
 * @param {Object} [properties]
 */
function inherit(child, base, properties) {
    var baseP = base.prototype,
        childP;

    childP = child.prototype = Object.create(baseP);
    childP.constructor = child;
    childP._super = baseP;

    if (properties) {
        extend(childP, properties);
    }
}

/**
 * simple function bind
 * @param {Function} fn
 * @param {Object} context
 * @returns {Function}
 */
function bindFn(fn, context) {
    return function boundFn() {
        return fn.apply(context, arguments);
    };
}

/**
 * let a boolean value also be a function that must return a boolean
 * this first item in args will be used as the context
 * @param {Boolean|Function} val
 * @param {Array} [args]
 * @returns {Boolean}
 */
function boolOrFn(val, args) {
    if (typeof val == TYPE_FUNCTION) {
        return val.apply(args ? args[0] || undefined : undefined, args);
    }
    return val;
}

/**
 * use the val2 when val1 is undefined
 * @param {*} val1
 * @param {*} val2
 * @returns {*}
 */
function ifUndefined(val1, val2) {
    return (val1 === undefined) ? val2 : val1;
}

/**
 * addEventListener with multiple events at once
 * @param {EventTarget} target
 * @param {String} types
 * @param {Function} handler
 */
function addEventListeners(target, types, handler) {
    each(splitStr(types), function(type) {
        target.addEventListener(type, handler, false);
    });
}

/**
 * removeEventListener with multiple events at once
 * @param {EventTarget} target
 * @param {String} types
 * @param {Function} handler
 */
function removeEventListeners(target, types, handler) {
    each(splitStr(types), function(type) {
        target.removeEventListener(type, handler, false);
    });
}

/**
 * find if a node is in the given parent
 * @method hasParent
 * @param {HTMLElement} node
 * @param {HTMLElement} parent
 * @return {Boolean} found
 */
function hasParent(node, parent) {
    while (node) {
        if (node == parent) {
            return true;
        }
        node = node.parentNode;
    }
    return false;
}

/**
 * small indexOf wrapper
 * @param {String} str
 * @param {String} find
 * @returns {Boolean} found
 */
function inStr(str, find) {
    return str.indexOf(find) > -1;
}

/**
 * split string on whitespace
 * @param {String} str
 * @returns {Array} words
 */
function splitStr(str) {
    return str.trim().split(/\s+/g);
}

/**
 * find if a array contains the object using indexOf or a simple polyFill
 * @param {Array} src
 * @param {String} find
 * @param {String} [findByKey]
 * @return {Boolean|Number} false when not found, or the index
 */
function inArray(src, find, findByKey) {
    if (src.indexOf && !findByKey) {
        return src.indexOf(find);
    } else {
        var i = 0;
        while (i < src.length) {
            if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) {
                return i;
            }
            i++;
        }
        return -1;
    }
}

/**
 * convert array-like objects to real arrays
 * @param {Object} obj
 * @returns {Array}
 */
function toArray(obj) {
    return Array.prototype.slice.call(obj, 0);
}

/**
 * unique array with objects based on a key (like 'id') or just by the array's value
 * @param {Array} src [{id:1},{id:2},{id:1}]
 * @param {String} [key]
 * @param {Boolean} [sort=False]
 * @returns {Array} [{id:1},{id:2}]
 */
function uniqueArray(src, key, sort) {
    var results = [];
    var values = [];
    var i = 0;

    while (i < src.length) {
        var val = key ? src[i][key] : src[i];
        if (inArray(values, val) < 0) {
            results.push(src[i]);
        }
        values[i] = val;
        i++;
    }

    if (sort) {
        if (!key) {
            results = results.sort();
        } else {
            results = results.sort(function sortUniqueArray(a, b) {
                return a[key] > b[key];
            });
        }
    }

    return results;
}

/**
 * get the prefixed property
 * @param {Object} obj
 * @param {String} property
 * @returns {String|Undefined} prefixed
 */
function prefixed(obj, property) {
    var prefix, prop;
    var camelProp = property[0].toUpperCase() + property.slice(1);

    var i = 0;
    while (i < VENDOR_PREFIXES.length) {
        prefix = VENDOR_PREFIXES[i];
        prop = (prefix) ? prefix + camelProp : property;

        if (prop in obj) {
            return prop;
        }
        i++;
    }
    return undefined;
}

/**
 * get a unique id
 * @returns {number} uniqueId
 */
var _uniqueId = 1;
function uniqueId() {
    return _uniqueId++;
}

/**
 * get the window object of an element
 * @param {HTMLElement} element
 * @returns {DocumentView|Window}
 */
function getWindowForElement(element) {
    var doc = element.ownerDocument || element;
    return (doc.defaultView || doc.parentWindow || window);
}
<commit_msg>fix(moz-prefix): prefix should be Moz not moz.<commit_after>var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o'];
var TEST_ELEMENT = document.createElement('div');

var TYPE_FUNCTION = 'function';

var round = Math.round;
var abs = Math.abs;
var now = Date.now;

/**
 * set a timeout with a given scope
 * @param {Function} fn
 * @param {Number} timeout
 * @param {Object} context
 * @returns {number}
 */
function setTimeoutContext(fn, timeout, context) {
    return setTimeout(bindFn(fn, context), timeout);
}

/**
 * if the argument is an array, we want to execute the fn on each entry
 * if it aint an array we don't want to do a thing.
 * this is used by all the methods that accept a single and array argument.
 * @param {*|Array} arg
 * @param {String} fn
 * @param {Object} [context]
 * @returns {Boolean}
 */
function invokeArrayArg(arg, fn, context) {
    if (Array.isArray(arg)) {
        each(arg, context[fn], context);
        return true;
    }
    return false;
}

/**
 * walk objects and arrays
 * @param {Object} obj
 * @param {Function} iterator
 * @param {Object} context
 */
function each(obj, iterator, context) {
    var i;

    if (!obj) {
        return;
    }

    if (obj.forEach) {
        obj.forEach(iterator, context);
    } else if (obj.length !== undefined) {
        i = 0;
        while (i < obj.length) {
            iterator.call(context, obj[i], i, obj);
            i++;
        }
    } else {
        for (i in obj) {
            obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj);
        }
    }
}

/**
 * extend object.
 * means that properties in dest will be overwritten by the ones in src.
 * @param {Object} dest
 * @param {Object} src
 * @param {Boolean} [merge]
 * @returns {Object} dest
 */
function extend(dest, src, merge) {
    var keys = Object.keys(src);
    var i = 0;
    while (i < keys.length) {
        if (!merge || (merge && dest[keys[i]] === undefined)) {
            dest[keys[i]] = src[keys[i]];
        }
        i++;
    }
    return dest;
}

/**
 * merge the values from src in the dest.
 * means that properties that exist in dest will not be overwritten by src
 * @param {Object} dest
 * @param {Object} src
 * @returns {Object} dest
 */
function merge(dest, src) {
    return extend(dest, src, true);
}

/**
 * simple class inheritance
 * @param {Function} child
 * @param {Function} base
 * @param {Object} [properties]
 */
function inherit(child, base, properties) {
    var baseP = base.prototype,
        childP;

    childP = child.prototype = Object.create(baseP);
    childP.constructor = child;
    childP._super = baseP;

    if (properties) {
        extend(childP, properties);
    }
}

/**
 * simple function bind
 * @param {Function} fn
 * @param {Object} context
 * @returns {Function}
 */
function bindFn(fn, context) {
    return function boundFn() {
        return fn.apply(context, arguments);
    };
}

/**
 * let a boolean value also be a function that must return a boolean
 * this first item in args will be used as the context
 * @param {Boolean|Function} val
 * @param {Array} [args]
 * @returns {Boolean}
 */
function boolOrFn(val, args) {
    if (typeof val == TYPE_FUNCTION) {
        return val.apply(args ? args[0] || undefined : undefined, args);
    }
    return val;
}

/**
 * use the val2 when val1 is undefined
 * @param {*} val1
 * @param {*} val2
 * @returns {*}
 */
function ifUndefined(val1, val2) {
    return (val1 === undefined) ? val2 : val1;
}

/**
 * addEventListener with multiple events at once
 * @param {EventTarget} target
 * @param {String} types
 * @param {Function} handler
 */
function addEventListeners(target, types, handler) {
    each(splitStr(types), function(type) {
        target.addEventListener(type, handler, false);
    });
}

/**
 * removeEventListener with multiple events at once
 * @param {EventTarget} target
 * @param {String} types
 * @param {Function} handler
 */
function removeEventListeners(target, types, handler) {
    each(splitStr(types), function(type) {
        target.removeEventListener(type, handler, false);
    });
}

/**
 * find if a node is in the given parent
 * @method hasParent
 * @param {HTMLElement} node
 * @param {HTMLElement} parent
 * @return {Boolean} found
 */
function hasParent(node, parent) {
    while (node) {
        if (node == parent) {
            return true;
        }
        node = node.parentNode;
    }
    return false;
}

/**
 * small indexOf wrapper
 * @param {String} str
 * @param {String} find
 * @returns {Boolean} found
 */
function inStr(str, find) {
    return str.indexOf(find) > -1;
}

/**
 * split string on whitespace
 * @param {String} str
 * @returns {Array} words
 */
function splitStr(str) {
    return str.trim().split(/\s+/g);
}

/**
 * find if a array contains the object using indexOf or a simple polyFill
 * @param {Array} src
 * @param {String} find
 * @param {String} [findByKey]
 * @return {Boolean|Number} false when not found, or the index
 */
function inArray(src, find, findByKey) {
    if (src.indexOf && !findByKey) {
        return src.indexOf(find);
    } else {
        var i = 0;
        while (i < src.length) {
            if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) {
                return i;
            }
            i++;
        }
        return -1;
    }
}

/**
 * convert array-like objects to real arrays
 * @param {Object} obj
 * @returns {Array}
 */
function toArray(obj) {
    return Array.prototype.slice.call(obj, 0);
}

/**
 * unique array with objects based on a key (like 'id') or just by the array's value
 * @param {Array} src [{id:1},{id:2},{id:1}]
 * @param {String} [key]
 * @param {Boolean} [sort=False]
 * @returns {Array} [{id:1},{id:2}]
 */
function uniqueArray(src, key, sort) {
    var results = [];
    var values = [];
    var i = 0;

    while (i < src.length) {
        var val = key ? src[i][key] : src[i];
        if (inArray(values, val) < 0) {
            results.push(src[i]);
        }
        values[i] = val;
        i++;
    }

    if (sort) {
        if (!key) {
            results = results.sort();
        } else {
            results = results.sort(function sortUniqueArray(a, b) {
                return a[key] > b[key];
            });
        }
    }

    return results;
}

/**
 * get the prefixed property
 * @param {Object} obj
 * @param {String} property
 * @returns {String|Undefined} prefixed
 */
function prefixed(obj, property) {
    var prefix, prop;
    var camelProp = property[0].toUpperCase() + property.slice(1);

    var i = 0;
    while (i < VENDOR_PREFIXES.length) {
        prefix = VENDOR_PREFIXES[i];
        prop = (prefix) ? prefix + camelProp : property;

        if (prop in obj) {
            return prop;
        }
        i++;
    }
    return undefined;
}

/**
 * get a unique id
 * @returns {number} uniqueId
 */
var _uniqueId = 1;
function uniqueId() {
    return _uniqueId++;
}

/**
 * get the window object of an element
 * @param {HTMLElement} element
 * @returns {DocumentView|Window}
 */
function getWindowForElement(element) {
    var doc = element.ownerDocument || element;
    return (doc.defaultView || doc.parentWindow || window);
}
<|endoftext|>


<commit_before>var
	Tweens = require('./util_tween');

module.exports = {
	STORAGE_PREFIX: 'timeliner-',
	Z_INDEX: 999,
	firstDefined: firstDefined,
	style: style,
	saveToFile: saveToFile,
	openAs: openAs,
	format_friendly_seconds: format_friendly_seconds,
	findTimeinLayer: findTimeinLayer,
	timeAtLayer: timeAtLayer,
	proxy_ctx: proxy_ctx
};

/**************************/
// Utils
/**************************/

function firstDefined() {
	for(var i = 0; i < arguments.length; i++) {
		if(typeof arguments[i] !== 'undefined') {
			return arguments[i];
		}
	}
	return (function(x) { return x; })();
}

function style(element, var_args) {
	for (var i = 1; i < arguments.length; ++i) {
		var styles = arguments[i];
		for (var s in styles) {
			element.style[s] = styles[s];
		}
	}
}

function saveToFile(string, filename) {
	var a = document.createElement("a");
	document.body.appendChild(a);
	a.style = "display: none";

	var blob = new Blob([string], { type: 'octet/stream' }), // application/json
		url = window.URL.createObjectURL(blob);

	a.href = url;
	a.download = filename;

	fakeClick(a);

	setTimeout(function() {
		// cleanup and revoke
		window.URL.revokeObjectURL(url);
		document.body.removeChild(a);
	}, 500);
}

var input, openCallback;

function handleFileSelect(evt) {
	var files = evt.target.files; // FileList object

	console.log('handle file select', files.length);

	var f = files[0];
	if (!f) return;
	// Can try to do MINE match
	// if (!f.type.match('application/json')) {
	//   return;
	// }
	console.log('match', f.type);

	var reader = new FileReader();

	// Closure to capture the file information.
	reader.onload = function(e) {
		var data = e.target.result;
		openCallback(data);
	};

	reader.readAsText(f);

	input.value = '';
}

function openAs(callback, target) {
	console.log('openfile...');
	openCallback = callback;

	if (!input) {
		input = document.createElement('input');
		input.style.display = 'none';
		input.type = 'file';
		input.addEventListener('change', handleFileSelect);
		target = target || document.body;
		target.appendChild(input);
	}

	fakeClick(input);
}

function fakeClick(target) {
	var e = document.createEvent("MouseEvents");
	e.initMouseEvent(
		'click', true, false, window, 0, 0, 0, 0, 0,
		false, false, false, false, 0, null
	);
	target.dispatchEvent(e);
}

function format_friendly_seconds(s, type) {
	// TODO Refactor to 60fps???
	// 20 mins * 60 sec = 1080
	// 1080s * 60fps = 1080 * 60 < Number.MAX_SAFE_INTEGER

	var raw_secs = s | 0;
	var secs_micro = s % 60;
	var secs = raw_secs % 60;
	var raw_mins = raw_secs / 60 | 0;
	var mins = raw_mins % 60;
	var hours = raw_mins / 60 | 0;

	var secs_str = (secs / 100).toFixed(2).substring(2);

	var str = mins + ':' + secs_str;

	if (s % 1 > 0) {
		var t2 = (s % 1) * 60;
		if (type === 'frames') str = secs + '+' + t2.toFixed(0) + 'f';
		else str += ((s % 1).toFixed(2)).substring(1);
		// else str = mins + ':' + secs_micro;
		// else str = secs_micro + 's'; /// .toFixed(2)
	}
	return str;
}

// get object at time
function findTimeinLayer(layer, time) {
	var values = layer.values;
	var i, il;

	// TODO optimize by checking time / binary search

	for (i=0, il=values.length; i<il; i++) {
		var value = values[i];
		if (value.time === time) {
			return {
				index: i,
				object: value
			};
		} else if (value.time > time) {
			return i;
		}
	}

	return i;
}

function timeAtLayer(layer, t) {
	// Find the value of layer at t seconds.
	// this expect layer to be sorted
	// not the most optimized for now, but would do.

	var values = layer.values;
	var i, il, entry, prev_entry;

	il = values.length;

	// can't do anything
	if (il === 0) return;

	if (layer._mute) return

	// find boundary cases
	entry = values[0];
	if (t < entry.time) {
		return {
			value: entry.value,
			can_tween: false, // cannot tween
			keyframe: false // not on keyframe
		};
	}

	for (i=0; i<il; i++) {
		prev_entry = entry;
		entry = values[i];

		if (t === entry.time) {
			// only exception is on the last KF, where we display tween from prev entry
			if (i === il - 1) {
				return {
					// index: i,
					entry: prev_entry,
					tween: prev_entry.tween,
					can_tween: il > 1,
					value: entry.value,
					keyframe: true
				};
			}
			return {
				// index: i,
				entry: entry,
				tween: entry.tween,
				can_tween: il > 1,
				value: entry.value,
				keyframe: true // il > 1
			};
		}
		if (t < entry.time) {
			// possibly a tween
			if (!prev_entry.tween) { // or if value is none
				return {
					value: prev_entry.value,
					tween: false,
					entry: prev_entry,
					can_tween: true,
					keyframe: false
				};
			}

			// calculate tween
			var time_diff = entry.time - prev_entry.time;
			var value_diff = entry.value - prev_entry.value;
			var tween = prev_entry.tween;

			var dt = t - prev_entry.time;
			var k = dt / time_diff;
			var new_value = prev_entry.value + Tweens[tween](k) * value_diff;

			return {
				entry: prev_entry,
				value: new_value,
				tween: prev_entry.tween,
				can_tween: true,
				keyframe: false
			};
		}
	}
	// time is after all entries
	return {
		value: entry.value,
		can_tween: false,
		keyframe: false
	};

}

function proxy_ctx(ctx) {
	// Creates a proxy 2d context wrapper which
	// allows the fluent / chaining API.
	var wrapper = {};

	function proxy_function(c) {
		return function() {
			// Warning: this doesn't return value of function call
			ctx[c].apply(ctx, arguments);
			return wrapper;
		};
	}

	function proxy_property(c) {
		return function(v) {
			ctx[c] = v;
			return wrapper;
		};
	}

	wrapper.run = function(args) {
		args(wrapper);
		return wrapper;
	};

	for (var c in ctx) {
		// if (!ctx.hasOwnProperty(c)) continue;
		// console.log(c, typeof(ctx[c]), ctx.hasOwnProperty(c));
		// string, number, boolean, function, object

		var type = typeof(ctx[c]);
		switch(type) {
			case 'object':
				break;
			case 'function':
				wrapper[c] = proxy_function(c);
				break;
			default:
				wrapper[c] = proxy_property(c);
				break;
		}
	}

	return wrapper;
}
<commit_msg>Use a less awkward way to return undefined<commit_after>var
	Tweens = require('./util_tween');

module.exports = {
	STORAGE_PREFIX: 'timeliner-',
	Z_INDEX: 999,
	firstDefined: firstDefined,
	style: style,
	saveToFile: saveToFile,
	openAs: openAs,
	format_friendly_seconds: format_friendly_seconds,
	findTimeinLayer: findTimeinLayer,
	timeAtLayer: timeAtLayer,
	proxy_ctx: proxy_ctx
};

/**************************/
// Utils
/**************************/

function firstDefined() {
	for(var i = 0; i < arguments.length; i++) {
		if(typeof arguments[i] !== 'undefined') {
			return arguments[i];
		}
	}
	return undefined;
}

function style(element, var_args) {
	for (var i = 1; i < arguments.length; ++i) {
		var styles = arguments[i];
		for (var s in styles) {
			element.style[s] = styles[s];
		}
	}
}

function saveToFile(string, filename) {
	var a = document.createElement("a");
	document.body.appendChild(a);
	a.style = "display: none";

	var blob = new Blob([string], { type: 'octet/stream' }), // application/json
		url = window.URL.createObjectURL(blob);

	a.href = url;
	a.download = filename;

	fakeClick(a);

	setTimeout(function() {
		// cleanup and revoke
		window.URL.revokeObjectURL(url);
		document.body.removeChild(a);
	}, 500);
}

var input, openCallback;

function handleFileSelect(evt) {
	var files = evt.target.files; // FileList object

	console.log('handle file select', files.length);

	var f = files[0];
	if (!f) return;
	// Can try to do MINE match
	// if (!f.type.match('application/json')) {
	//   return;
	// }
	console.log('match', f.type);

	var reader = new FileReader();

	// Closure to capture the file information.
	reader.onload = function(e) {
		var data = e.target.result;
		openCallback(data);
	};

	reader.readAsText(f);

	input.value = '';
}

function openAs(callback, target) {
	console.log('openfile...');
	openCallback = callback;

	if (!input) {
		input = document.createElement('input');
		input.style.display = 'none';
		input.type = 'file';
		input.addEventListener('change', handleFileSelect);
		target = target || document.body;
		target.appendChild(input);
	}

	fakeClick(input);
}

function fakeClick(target) {
	var e = document.createEvent("MouseEvents");
	e.initMouseEvent(
		'click', true, false, window, 0, 0, 0, 0, 0,
		false, false, false, false, 0, null
	);
	target.dispatchEvent(e);
}

function format_friendly_seconds(s, type) {
	// TODO Refactor to 60fps???
	// 20 mins * 60 sec = 1080
	// 1080s * 60fps = 1080 * 60 < Number.MAX_SAFE_INTEGER

	var raw_secs = s | 0;
	var secs_micro = s % 60;
	var secs = raw_secs % 60;
	var raw_mins = raw_secs / 60 | 0;
	var mins = raw_mins % 60;
	var hours = raw_mins / 60 | 0;

	var secs_str = (secs / 100).toFixed(2).substring(2);

	var str = mins + ':' + secs_str;

	if (s % 1 > 0) {
		var t2 = (s % 1) * 60;
		if (type === 'frames') str = secs + '+' + t2.toFixed(0) + 'f';
		else str += ((s % 1).toFixed(2)).substring(1);
		// else str = mins + ':' + secs_micro;
		// else str = secs_micro + 's'; /// .toFixed(2)
	}
	return str;
}

// get object at time
function findTimeinLayer(layer, time) {
	var values = layer.values;
	var i, il;

	// TODO optimize by checking time / binary search

	for (i=0, il=values.length; i<il; i++) {
		var value = values[i];
		if (value.time === time) {
			return {
				index: i,
				object: value
			};
		} else if (value.time > time) {
			return i;
		}
	}

	return i;
}

function timeAtLayer(layer, t) {
	// Find the value of layer at t seconds.
	// this expect layer to be sorted
	// not the most optimized for now, but would do.

	var values = layer.values;
	var i, il, entry, prev_entry;

	il = values.length;

	// can't do anything
	if (il === 0) return;

	if (layer._mute) return

	// find boundary cases
	entry = values[0];
	if (t < entry.time) {
		return {
			value: entry.value,
			can_tween: false, // cannot tween
			keyframe: false // not on keyframe
		};
	}

	for (i=0; i<il; i++) {
		prev_entry = entry;
		entry = values[i];

		if (t === entry.time) {
			// only exception is on the last KF, where we display tween from prev entry
			if (i === il - 1) {
				return {
					// index: i,
					entry: prev_entry,
					tween: prev_entry.tween,
					can_tween: il > 1,
					value: entry.value,
					keyframe: true
				};
			}
			return {
				// index: i,
				entry: entry,
				tween: entry.tween,
				can_tween: il > 1,
				value: entry.value,
				keyframe: true // il > 1
			};
		}
		if (t < entry.time) {
			// possibly a tween
			if (!prev_entry.tween) { // or if value is none
				return {
					value: prev_entry.value,
					tween: false,
					entry: prev_entry,
					can_tween: true,
					keyframe: false
				};
			}

			// calculate tween
			var time_diff = entry.time - prev_entry.time;
			var value_diff = entry.value - prev_entry.value;
			var tween = prev_entry.tween;

			var dt = t - prev_entry.time;
			var k = dt / time_diff;
			var new_value = prev_entry.value + Tweens[tween](k) * value_diff;

			return {
				entry: prev_entry,
				value: new_value,
				tween: prev_entry.tween,
				can_tween: true,
				keyframe: false
			};
		}
	}
	// time is after all entries
	return {
		value: entry.value,
		can_tween: false,
		keyframe: false
	};

}

function proxy_ctx(ctx) {
	// Creates a proxy 2d context wrapper which
	// allows the fluent / chaining API.
	var wrapper = {};

	function proxy_function(c) {
		return function() {
			// Warning: this doesn't return value of function call
			ctx[c].apply(ctx, arguments);
			return wrapper;
		};
	}

	function proxy_property(c) {
		return function(v) {
			ctx[c] = v;
			return wrapper;
		};
	}

	wrapper.run = function(args) {
		args(wrapper);
		return wrapper;
	};

	for (var c in ctx) {
		// if (!ctx.hasOwnProperty(c)) continue;
		// console.log(c, typeof(ctx[c]), ctx.hasOwnProperty(c));
		// string, number, boolean, function, object

		var type = typeof(ctx[c]);
		switch(type) {
			case 'object':
				break;
			case 'function':
				wrapper[c] = proxy_function(c);
				break;
			default:
				wrapper[c] = proxy_property(c);
				break;
		}
	}

	return wrapper;
}
<|endoftext|>


<commit_before>import { easeInOutQuint } from './easing'

export const values = Object.values || ((obj) => Object.keys(obj).map((key) => obj[key]))

export const compose = (...fns) => (val) => fns.reduceRight((currVal, fn) => fn(currVal), val)

export const minMap = (...vals) => (val) => Math.min(...vals, val)
export const maxMap = (...vals) => (val) => Math.max(...vals, val)

export const on = (evt, opts = false) => (cb) => (el) => el.addEventListener(evt, cb, opts)

export const onWindowScroll = (cb) => on('scroll', true)(cb)(window)

export const onScroll = (cb, { target = window } = {}) =>
  onWindowScroll((e) => (target === window || target === e.target) && cb(e))

export const onScrollEnd = (cb, { wait = 100, target = window } = {}) => ((timeoutID) => onScroll((evt) => {
  clearTimeout(timeoutID)
  timeoutID = setTimeout(() => evt.target === target ? cb() : undefined, wait)
}))(0)

export const onScrollStart = (cb, { target = window } = {}) => {
  let started = false
  onScrollEnd(() => { started = false }, { target })
  onScroll((e) => {
    if (!started) {
      started = true
      cb(e)
    }
  }, { target })
}

export const trackTouchesForElement = (el) => {
  let touchIds = []
  on('touchstart')(({ changedTouches }) => {
    const changedIds = [].slice.call(changedTouches).map(({ identifier }) => identifier)
    touchIds = [...touchIds, ...changedIds]
  })(el)

  on('touchend')(({ changedTouches }) => {
    const changedIds = [].slice.call(changedTouches).map(({ identifier }) => identifier)
    touchIds = touchIds.filter((touchId) => !changedIds.includes(touchId))
  })(el)

  return () => touchIds.length
}

export const animate = (el, {
  delta = 0,
  immediate = false,
  duration = immediate ? 0 : 800,
  easing = easeInOutQuint,
  prop = 'scrollTop'
} = {}) => new Promise((res, rej) => {
  if (!delta) res()
  const initialVal = el[prop]
  let startTime = null
  const step = (timestamp) => {
    if (!startTime) startTime = timestamp
    const progressTime = timestamp - startTime
    const progressRatio = easing(progressTime / duration)
    el[prop] = initialVal + (delta * progressRatio)
    if (progressTime < duration) {
      window.requestAnimationFrame(step)
    } else {
      // Give scroll control back to the user once animation is done.
      // el.style.overflow = overFlowStyle
      // MS Edge doesn't like the above apparently.
      el.setAttribute('style', el.getAttribute('style').replace(/(overflow:\s?)\w*/, '$1auto'))
      el[prop] = initialVal + delta // jump to end when animation is complete. necessary at least for immediate scroll

      res()
    }
  }
  // We are going to temporarily prevent the user from being able to scroll during the animation.
  // This will prevent a janky fight between user scroll and animation which is just bad user experience.
  el.style.overflow = 'hidden'
  window.requestAnimationFrame(step)
})
<commit_msg>fixes firefox bug<commit_after>import { easeInOutQuint } from './easing'

export const values = Object.values || ((obj) => Object.keys(obj).map((key) => obj[key]))

export const compose = (...fns) => (val) => fns.reduceRight((currVal, fn) => fn(currVal), val)

export const minMap = (...vals) => (val) => Math.min(...vals, val)
export const maxMap = (...vals) => (val) => Math.max(...vals, val)

export const on = (evt, opts = false) => (cb) => (el) => el.addEventListener(evt, cb, opts)

export const onWindowScroll = (cb) => on('scroll', true)(cb)(window)

export const onScroll = (cb, { target = window } = {}) =>
  onWindowScroll((e) => (target === window || target === e.target) && cb(e))

export const onScrollEnd = (cb, { wait = 100, target = window } = {}) => ((timeoutID) => onScroll((evt) => {
  clearTimeout(timeoutID)
  timeoutID = setTimeout(() => evt.target === target ? cb() : undefined, wait)
}))(0)

export const onScrollStart = (cb, { target = window } = {}) => {
  let started = false
  onScrollEnd(() => { started = false }, { target })
  onScroll((e) => {
    if (!started) {
      started = true
      cb(e)
    }
  }, { target })
}

export const trackTouchesForElement = (el) => {
  let touchIds = []
  on('touchstart')(({ changedTouches }) => {
    const changedIds = [].slice.call(changedTouches).map(({ identifier }) => identifier)
    touchIds = [...touchIds, ...changedIds]
  })(el)

  on('touchend')(({ changedTouches }) => {
    const changedIds = [].slice.call(changedTouches).map(({ identifier }) => identifier)
    touchIds = touchIds.filter((touchId) => !changedIds.includes(touchId))
  })(el)

  return () => touchIds.length
}

export const animate = (el, {
  delta = 0,
  immediate = false,
  duration = immediate ? 0 : 800,
  easing = easeInOutQuint,
  prop = 'scrollTop'
} = {}) => (new Promise((res, rej) => {
  if (!delta) res()
  const initialVal = el[prop]
  let startTime = null
  const step = (timestamp) => {
    if (!startTime) startTime = timestamp
    const progressTime = timestamp - startTime
    const progressRatio = easing(progressTime / duration)
    el[prop] = initialVal + (delta * progressRatio)
    if (progressTime < duration) {
      window.requestAnimationFrame(step)
    } else {
      el[prop] = initialVal + delta // jump to end when animation is complete. necessary at least for immediate scroll

      res()
    }
  }
  // We are going to temporarily prevent the user from being able to scroll during the animation.
  // This will prevent a janky fight between user scroll and animation which is just bad user experience.
  el.style.overflow = 'hidden'
  window.requestAnimationFrame(step)
})).then(() => setTimeout(() => {
  // Give scroll control back to the user once animation is done.
  // el.style.overflow = overFlowStyle
  // MS Edge doesn't like the above apparently.

  // Firefox doesn't like when this is done immediatly after jumping to the end.
  // Setting overflow somehow triggers a scroll event throwing this whole thing into an infinite loop.
  // Kicking to the next tick solves this.
  el.setAttribute('style', el.getAttribute('style').replace(/(overflow:\s?)\w*/, '$1auto'))
}, 0))
<|endoftext|>


<commit_before>/**
 * Gets the data attribute. the name must be kebab-case.
 */
export const getDataAttribute = (el, name) => el.getAttribute(`data-vv-${name}`);

/**
 * Determines the input field scope.
 */
export const getScope = (el) => {
  let scope = getDataAttribute(el, 'scope');
  if (! scope && el.form) {
    scope = getDataAttribute(el.form, 'scope');
  }

  return scope;
};

/**
 * Debounces a function.
 */
export const debounce = (callback, wait = 0, immediate) => {
  let timeout;
  if (wait == 0) {
    return callback;
  }
  return (...args) => {
    const later = () => {
      timeout = null;
      if (!immediate) callback(...args);
    };
    const callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) callback(args);
  };
};

/**
 * Emits a warning to the console.
 */
export const warn = (message) => {
  if (! console) {
    return;
  }

    console.warn(`[vee-validate]: ${message}`); // eslint-disable-line
};

/**
 * Checks if the value is an object.
 */
export const isObject = (object) => {
  return object !== null && object && typeof object === 'object' && ! Array.isArray(object);
};

/**
 * Checks if a function is callable.
 */
export const isCallable = (func) => typeof func === 'function';

/**
 * Check if element has the css class on it.
 */
export const hasClass = (el, className) => {
  if (el.classList) {
    return el.classList.contains(className);
  }

  return !!el.className.match(new RegExp(`(\\s|^)${className}(\\s|$)`));
};

/**
 * Adds the provided css className to the element.
 */
export const addClass = (el, className) => {
  if (el.classList) {
    el.classList.add(className);
    return;
  }

  if (!hasClass(el, className)) {
    el.className += ` ${className}`;
  }
};

/**
 * Remove the provided css className from the element.
 */
export const removeClass = (el, className) => {
  if (el.classList) {
    el.classList.remove(className);
    return;
  }

  if (hasClass(el, className)) {
    const reg = new RegExp(`(\\s|^)${className}(\\s|$)`);
    el.className = el.className.replace(reg, ' ');
  }
};

/**
 * Converts an array-like object to array.
 * Simple polyfill for Array.from
 */
export const toArray = (arrayLike) => {
  if (Array.from) {
    return Array.from(arrayLike);
  }

  const array = [];
  const length = arrayLike.length;
  for (let i = 0; i < length; i++) {
    array.push(arrayLike[i]);
  }

  return array;
};

/**
 * Assign polyfill from the mdn.
 */
export const assign = (target, ...others) => {
  if (Object.assign) {
    return Object.assign(target, ...others);
  }

  if (target == null) {
    throw new TypeError('Cannot convert undefined or null to object');
  }

  const to = Object(target);
  others.forEach(arg => {
    // Skip over if undefined or null
    if (arg != null) {
      Object.keys(arg).forEach(key => {
        to[key] = arg[key];
      });
    }
  });

  return to;
};

/**
 * polyfills array.find
 * @param {Array} array
 * @param {Function} predicate
 */
export const find = (array, predicate) => {
  if (array.find) {
    return array.find(predicate);
  }

  let result;
  array.some(item => {
    if (predicate(item)) {
      result = item;
      return true;
    }

    return false;
  });

  return result;
};

/**
 * Gets the rules from a binding value or the element dataset.
 *
 * @param {String} expression The binding expression.
 * @param {Object|String} value The binding value.
 * @param {element} el The element.
 * @returns {String|Object}
 */
export const getRules = (expression, value, el) => {
  if (! expression) {
    return getDataAttribute(el, 'rules');
  }

  if (typeof value === 'string') {
    return value;
  }

  if (~['string', 'object'].indexOf(typeof value.rules)) {
    return value.rules
  }

  return value;
};
<commit_msg>fix code style<commit_after>/**
 * Gets the data attribute. the name must be kebab-case.
 */
export const getDataAttribute = (el, name) => el.getAttribute(`data-vv-${name}`);

/**
 * Determines the input field scope.
 */
export const getScope = (el) => {
  let scope = getDataAttribute(el, 'scope');
  if (! scope && el.form) {
    scope = getDataAttribute(el.form, 'scope');
  }

  return scope;
};

/**
 * Debounces a function.
 */
export const debounce = (callback, wait = 0, immediate) => {
  let timeout;
  if (wait == 0) {
    return callback;
  }
  return (...args) => {
    const later = () => {
      timeout = null;
      if (!immediate) callback(...args);
    };
    const callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) callback(args);
  };
};

/**
 * Emits a warning to the console.
 */
export const warn = (message) => {
  if (! console) {
    return;
  }

    console.warn(`[vee-validate]: ${message}`); // eslint-disable-line
};

/**
 * Checks if the value is an object.
 */
export const isObject = (object) => {
  return object !== null && object && typeof object === 'object' && ! Array.isArray(object);
};

/**
 * Checks if a function is callable.
 */
export const isCallable = (func) => typeof func === 'function';

/**
 * Check if element has the css class on it.
 */
export const hasClass = (el, className) => {
  if (el.classList) {
    return el.classList.contains(className);
  }

  return !!el.className.match(new RegExp(`(\\s|^)${className}(\\s|$)`));
};

/**
 * Adds the provided css className to the element.
 */
export const addClass = (el, className) => {
  if (el.classList) {
    el.classList.add(className);
    return;
  }

  if (!hasClass(el, className)) {
    el.className += ` ${className}`;
  }
};

/**
 * Remove the provided css className from the element.
 */
export const removeClass = (el, className) => {
  if (el.classList) {
    el.classList.remove(className);
    return;
  }

  if (hasClass(el, className)) {
    const reg = new RegExp(`(\\s|^)${className}(\\s|$)`);
    el.className = el.className.replace(reg, ' ');
  }
};

/**
 * Converts an array-like object to array.
 * Simple polyfill for Array.from
 */
export const toArray = (arrayLike) => {
  if (Array.from) {
    return Array.from(arrayLike);
  }

  const array = [];
  const length = arrayLike.length;
  for (let i = 0; i < length; i++) {
    array.push(arrayLike[i]);
  }

  return array;
};

/**
 * Assign polyfill from the mdn.
 */
export const assign = (target, ...others) => {
  if (Object.assign) {
    return Object.assign(target, ...others);
  }

  if (target == null) {
    throw new TypeError('Cannot convert undefined or null to object');
  }

  const to = Object(target);
  others.forEach(arg => {
    // Skip over if undefined or null
    if (arg != null) {
      Object.keys(arg).forEach(key => {
        to[key] = arg[key];
      });
    }
  });

  return to;
};

/**
 * polyfills array.find
 * @param {Array} array
 * @param {Function} predicate
 */
export const find = (array, predicate) => {
  if (array.find) {
    return array.find(predicate);
  }

  let result;
  array.some(item => {
    if (predicate(item)) {
      result = item;
      return true;
    }

    return false;
  });

  return result;
};

/**
 * Gets the rules from a binding value or the element dataset.
 *
 * @param {String} expression The binding expression.
 * @param {Object|String} value The binding value.
 * @param {element} el The element.
 * @returns {String|Object}
 */
export const getRules = (expression, value, el) => {
  if (! expression) {
    return getDataAttribute(el, 'rules');
  }

  if (typeof value === 'string') {
    return value;
  }

  if (~['string', 'object'].indexOf(typeof value.rules)) {
    return value.rules
  }

  return value;
};
<|endoftext|>


<commit_before>'use strict'

const {
  AbstractWork,
  CreativeWork,
  Manifestation,
  Organization,
  Party
} = require('./core')

const {
  SCHEMA,
  inherit,
  propArray,
  propValue
} = require('./util')

// MusicComposition

function MusicComposition () {
  AbstractWork.call(this, 'MusicComposition')
}

inherit(MusicComposition, AbstractWork)
propArray(MusicComposition, new Party(), 'composer')
propValue(MusicComposition, String(), 'iswcCode')
propArray(MusicComposition, new Party(), 'lyricist')

// MusicGroup

function MusicGroup () {
  Organization.call(this, 'MusicGroup')
}

inherit(MusicGroup, Organization)
propArray(MusicGroup, String(), 'genre')

// MusicPlaylist

function MusicPlaylist (type = 'MusicPlaylist') {
  CreativeWork.call(this, SCHEMA, type)
}

inherit(MusicPlaylist, CreativeWork)
propArray(MusicPlaylist, new MusicRecording(), 'track')

// MusicRecording

function MusicRecording () {
  Manifestation.call(this, 'MusicRecording')
}

inherit(MusicRecording, Manifestation)
propArray(MusicRecording, new MusicGroup(), 'byArtist')
propValue(MusicRecording, String(), 'isrcCode')
propValue(MusicRecording, new MusicComposition(), 'recordingOf')

// MusicAlbum

function MusicAlbum () {
  MusicPlaylist.call(this, 'MusicAlbum')
}

inherit(MusicAlbum, MusicPlaylist)
propValue(MusicAlbum, String(), 'albumProductionType')
propArray(MusicAlbum, new MusicGroup(), 'byArtist')

// MusicRelease

function MusicRelease () {
  MusicPlaylist.call(this, 'MusicRelease')
}

inherit(MusicRelease, MusicPlaylist)
propValue(MusicRelease, String(), 'catalogNumber')
propValue(MusicRelease, String(), 'musicReleaseFormat')
propArray(MusicRelease, new Party(), 'recordLabel')
propValue(MusicRelease, new MusicAlbum(), 'releaseOf')

module.exports = {
  MusicAlbum,
  MusicComposition,
  MusicGroup,
  MusicPlaylist,
  MusicRecording,
  MusicRelease
}
<commit_msg>adding position to MusicRecording (as documented in schema) for sorting purposes<commit_after>'use strict'

const {
  AbstractWork,
  CreativeWork,
  Manifestation,
  Organization,
  Party
} = require('./core')

const {
  SCHEMA,
  inherit,
  propArray,
  propValue
} = require('./util')

// MusicComposition

function MusicComposition () {
  AbstractWork.call(this, 'MusicComposition')
}

inherit(MusicComposition, AbstractWork)
propArray(MusicComposition, new Party(), 'composer')
propValue(MusicComposition, String(), 'iswcCode')
propArray(MusicComposition, new Party(), 'lyricist')

// MusicGroup

function MusicGroup () {
  Organization.call(this, 'MusicGroup')
}

inherit(MusicGroup, Organization)
propArray(MusicGroup, String(), 'genre')

// MusicPlaylist

function MusicPlaylist (type = 'MusicPlaylist') {
  CreativeWork.call(this, SCHEMA, type)
}

inherit(MusicPlaylist, CreativeWork)
propArray(MusicPlaylist, new MusicRecording(), 'track')

// MusicRecording

function MusicRecording () {
  Manifestation.call(this, 'MusicRecording')
}

inherit(MusicRecording, Manifestation)
propArray(MusicRecording, new MusicGroup(), 'byArtist')
propValue(MusicRecording, String(), 'isrcCode')
propValue(MusicRecording, new MusicComposition(), 'recordingOf')
propValue(MusicRecording, Number(), 'position');

// MusicAlbum

function MusicAlbum () {
  MusicPlaylist.call(this, 'MusicAlbum')
}

inherit(MusicAlbum, MusicPlaylist)
propValue(MusicAlbum, String(), 'albumProductionType')
propArray(MusicAlbum, new MusicGroup(), 'byArtist')

// MusicRelease

function MusicRelease () {
  MusicPlaylist.call(this, 'MusicRelease')
}

inherit(MusicRelease, MusicPlaylist)
propValue(MusicRelease, String(), 'catalogNumber')
propValue(MusicRelease, String(), 'musicReleaseFormat')
propArray(MusicRelease, new Party(), 'recordLabel')
propValue(MusicRelease, new MusicAlbum(), 'releaseOf')

module.exports = {
  MusicAlbum,
  MusicComposition,
  MusicGroup,
  MusicPlaylist,
  MusicRecording,
  MusicRelease
}
<|endoftext|>


<commit_before>"use strict";

// Safari 7.0.6  needs webkit prefix
window.AudioContext = window.AudioContext || /* istanbul ignore next */ window.webkitAudioContext;
window.OfflineAudioContext = window.OfflineAudioContext || /* istanbul ignore next */ window.webkitOfflineAudioContext;

var _ = require("./utils");

var neuma = function(context) {
  function Neuma(spec) {
    return neuma.build(context, spec);
  }

  var audioContext = _.findAudioContext(context);

  Object.defineProperties(Neuma, {
    context: {
      value: audioContext,
      enumerable: true
    },
    outlet: {
      value: _.findAudioNode(context),
      enumerable: true
    },
    sampleRate: {
      value: audioContext.sampleRate,
      enumerable: true
    },
    Buffer: {
      value: Object.defineProperties({}, {
        create: {
          value: function(channels, length, sampleRate) {
            return neuma.Buffer.create(context, channels, length, sampleRate);
          },
          enumerable: true
        },
        from: {
          value: function(data) {
            return neuma.Buffer.from(context, data);
          },
          enumerable: true
        },
        load: {
          value: function(url) {
            return neuma.Buffer.load(context, url);
          },
          enumerable: true
        }
      }),
      enumerable: true
    },
    Interval: {
      value: function(interval, callback) {
        return new neuma.Interval(context, interval, callback);
      },
      enumerable: true
    },
  });

  return Neuma;
};

neuma._ = _;
neuma.Context  = require("./context");
neuma.SynthDef = require("./synthdef");
neuma.Synth    = require("./synth");
neuma.UGen     = require("./ugen");
neuma.Param    = require("./param");
neuma.Unit     = require("./unit");
neuma.DC       = require("./dc");
neuma.Buffer   = require("./buffer");
neuma.Interval = require("./interval");

var context = new neuma.Context(new window.AudioContext());

neuma.Neuma = Object.defineProperties(
  neuma(context), {
    use: {
      value: neuma.use,
      enumerable: true
    },
    render: {
      value: neuma.render,
      enumerable: true
    },
    master: {
      value: context.getMasterGain(),
      enumerable: true
    },
    analyer: {
      value: context.getAnalyser(),
      enumerable: true
    }
  }
);

neuma.build = function(context, spec) {
  return new neuma.SynthDef(context, spec);
};

neuma.register = function(name, func) {
  neuma.UGen.register(name, func);
  return neuma;
};

neuma.use = function(fn) {
  /* istanbul ignore else */
  if (neuma.use.used.indexOf(fn) === -1) {
    fn(neuma, _);
    neuma.use.used.push(fn);
  }
  return neuma;
};
neuma.use.used = [];

neuma.render = function(duration, func) {
  var sampleRate = neuma.Neuma.audioContext.sampleRate;
  var length = _.int(sampleRate * duration);

  return new Promise(function(resolve) {
    var audioContext = new window.OfflineAudioContext(2, length, sampleRate);
    audioContext.oncomplete = function(e) {
      resolve(new neuma.Buffer(e.renderedBuffer));
    };
    audioContext.startRendering();
    func(neuma(new neuma.Context(audioContext)));
  });
};

module.exports = neuma;
<commit_msg>add Neuma.currentTime<commit_after>"use strict";

// Safari 7.0.6  needs webkit prefix
window.AudioContext = window.AudioContext || /* istanbul ignore next */ window.webkitAudioContext;
window.OfflineAudioContext = window.OfflineAudioContext || /* istanbul ignore next */ window.webkitOfflineAudioContext;

var _ = require("./utils");

var neuma = function(context) {
  function Neuma(spec) {
    return neuma.build(context, spec);
  }

  var audioContext = _.findAudioContext(context);

  Object.defineProperties(Neuma, {
    context: {
      value: audioContext,
      enumerable: true
    },
    outlet: {
      value: _.findAudioNode(context),
      enumerable: true
    },
    sampleRate: {
      value: audioContext.sampleRate,
      enumerable: true
    },
    currentTime: {
      get: function() {
        return context.currentTime;
      },
      enumerable: true
    },
    Buffer: {
      value: Object.defineProperties({}, {
        create: {
          value: function(channels, length, sampleRate) {
            return neuma.Buffer.create(context, channels, length, sampleRate);
          },
          enumerable: true
        },
        from: {
          value: function(data) {
            return neuma.Buffer.from(context, data);
          },
          enumerable: true
        },
        load: {
          value: function(url) {
            return neuma.Buffer.load(context, url);
          },
          enumerable: true
        }
      }),
      enumerable: true
    },
    Interval: {
      value: function(interval, callback) {
        return new neuma.Interval(context, interval, callback);
      },
      enumerable: true
    },
  });

  return Neuma;
};

neuma._ = _;
neuma.Context  = require("./context");
neuma.SynthDef = require("./synthdef");
neuma.Synth    = require("./synth");
neuma.UGen     = require("./ugen");
neuma.Param    = require("./param");
neuma.Unit     = require("./unit");
neuma.DC       = require("./dc");
neuma.Buffer   = require("./buffer");
neuma.Interval = require("./interval");

var context = new neuma.Context(new window.AudioContext());

neuma.Neuma = Object.defineProperties(
  neuma(context), {
    use: {
      value: neuma.use,
      enumerable: true
    },
    render: {
      value: neuma.render,
      enumerable: true
    },
    master: {
      value: context.getMasterGain(),
      enumerable: true
    },
    analyer: {
      value: context.getAnalyser(),
      enumerable: true
    }
  }
);

neuma.build = function(context, spec) {
  return new neuma.SynthDef(context, spec);
};

neuma.register = function(name, func) {
  neuma.UGen.register(name, func);
  return neuma;
};

neuma.use = function(fn) {
  /* istanbul ignore else */
  if (neuma.use.used.indexOf(fn) === -1) {
    fn(neuma, _);
    neuma.use.used.push(fn);
  }
  return neuma;
};
neuma.use.used = [];

neuma.render = function(duration, func) {
  var sampleRate = neuma.Neuma.audioContext.sampleRate;
  var length = _.int(sampleRate * duration);

  return new Promise(function(resolve) {
    var audioContext = new window.OfflineAudioContext(2, length, sampleRate);
    audioContext.oncomplete = function(e) {
      resolve(new neuma.Buffer(e.renderedBuffer));
    };
    audioContext.startRendering();
    func(neuma(new neuma.Context(audioContext)));
  });
};

module.exports = neuma;
<|endoftext|>