<commit_before>const svgNamespace = 'http://www.w3.org/2000/svg'

const weakMap = new WeakMap()

const createQuoteError = (problem) => Error(`Quote ${problem}`)
const createAssertionError = (actual, expected) =>
  Error(`Expected ${expected}. Found ${actual}.`)

const resolve = (obj) => {
  if (typeof obj === 'function') {
    let afterUpdate

    obj = obj((cb) => {
      afterUpdate = cb
    })

    if (obj) obj.afterUpdate = afterUpdate
  }

  return obj
}

const readMeta = (target, meta = {}) => {
  if (!meta._read) {
    Object.assign(meta, weakMap.get(target) ?? {})

    meta._read = true
  }

  return meta
}

const getNextSibling = (current) => current?.nextSibling

const getListener = (key) => (e) => {
  const map = weakMap.get(e.target)

  if (map && map[key]) {
    map[key](e)
  }
}

const morphAttribute = (target, key, value, meta, listeners) => {
  const document = target.ownerDocument
  const remove = value == null || value === false

  if (key.indexOf('on') === 0) {
    readMeta(target, meta)

    if (remove) {
      if (meta[key]) {
        meta[key] = null
      }
    } else {
      meta[key] = value

      if (!listeners.includes(key)) {
        listeners.push(key)

        const type = key.substring(2)

        document.addEventListener(type, getListener(key))
      }
    }
  } else {
    if (remove) {
      target.removeAttribute(key)
    } else {
      const stringified = value === true ? '' : value

      if (target.getAttribute(key) !== stringified) {
        target.setAttribute(key, stringified)
      }
    }

    if (key === 'value' || value === true || value === false) {
      if (target[key] !== value) {
        target[key] = value
      }
    }
  }
}

const morphChild = (
  target,
  childNode,
  next,
  variables,
  isSameView,
  forceAppend,
  listeners
) => {
  const document = target.ownerDocument

  const append = forceAppend || childNode == null

  let replace = false

  let currentChild = childNode

  if (next.type === 'text') {
    if (!append && childNode.nodeType !== 3) {
      replace = true
    }

    if (append || replace) {
      currentChild = document.createTextNode(next.value)
    } else if (childNode.data !== next.value) {
      childNode.data = next.value
    }
  } else {
    const tag = next.tag

    if (
      !append &&
      (childNode.nodeType !== 1 || childNode.nodeName.toLowerCase() !== tag)
    ) {
      replace = true
    }

    if (append || replace) {
      const isSvg = tag === 'svg' || target.namespaceURI === svgNamespace

      currentChild = isSvg
        ? document.createElementNS(svgNamespace, tag)
        : document.createElement(tag)
    }

    if (next.view != null) {
      morphRoot(currentChild, next, listeners)
    } else if (!isSameView || next.dynamic) {
      morph(currentChild, next, variables, isSameView, {}, listeners)
    }
  }

  if (forceAppend && childNode) {
    childNode.before(currentChild)
  } else if (append) {
    target.append(currentChild)
  } else if (replace) {
    childNode.replaceWith(currentChild)
  }

  if (currentChild != null && next.afterUpdate) {
    next.afterUpdate(currentChild)
  }

  return getNextSibling(currentChild)
}

const morph = (target, next, variables, isSameView, meta, listeners) => {
  const attributesLength = next.attributes.length

  const attrNames = []

  const hasExistingAttributes = target.attributes.length

  if (attributesLength) {
    for (let i = 0, length = attributesLength; i < length; i++) {
      const attribute = next.attributes[i]

      if (!isSameView || attribute.variable) {
        let value = attribute.value

        if (attribute.variable) {
          value = variables[value]
        }

        if (attribute.key) {
          morphAttribute(target, attribute.key, value, meta, listeners)

          attrNames.push(attribute.key)
        } else {
          for (const key of Object.keys(value)) {
            morphAttribute(target, key, value[key], meta, listeners)

            attrNames.push(key)
          }
        }
      }
    }
  }

  if (!isSameView && hasExistingAttributes) {
    for (const attr of target.attributes) {
      if (!~attrNames.indexOf(attr.name)) {
        target.removeAttribute(attr.name)
      }
    }
  }

  const childrenLength = next.children.length
  let childNode = target.firstChild

  let keys

  let prevKeys

  if (childrenLength) {
    let deopt = !isSameView

    for (let childIndex = 0; childIndex < childrenLength; childIndex++) {
      let child = next.children[childIndex]

      if (!deopt && !child.dynamic && !child.variable) {
        childNode = getNextSibling(childNode)
      } else {
        deopt = true

        if (child.variable) {
          const variableValue = child.value

          child = variables[variableValue]

          if (child?.[Symbol.iterator] == null || typeof child === 'string') {
            child = [child]
          }

          let keyIndex = 0
          let lengthDifference

          for (let grand of child) {
            grand = resolve(grand)

            if (grand == null) grand = ''

            let keysMatch = true

            if (grand.key != null) {
              if (!keys) {
                keys = {}

                readMeta(target, meta)

                prevKeys = meta.keys?.[variableValue] ?? {}
              }

              if (!keys[variableValue]) {
                keys[variableValue] = []
              }

              keys[variableValue].push(grand.key)

              keysMatch = prevKeys[keyIndex] === grand.key

              grand = grand.value

              lengthDifference = child.length - prevKeys.length
            }

            keyIndex++

            if (grand.type == null) {
              grand = {type: 'text', value: grand}
            }

            if (!keysMatch && lengthDifference < 0 && childNode != null) {
              lengthDifference++

              const extraNode = childNode

              childNode = childNode.nextSibling

              extraNode.remove()
            }

            if (isSameView && grand.view != null && !grand.dynamic) {
              childNode = getNextSibling(childNode)
            } else {
              const forceAppend =
                !keysMatch && lengthDifference > 0 && childNode

              if (forceAppend) {
                lengthDifference--

                keyIndex--
              }

              childNode = morphChild(
                target,
                childNode,
                grand,
                variables,
                isSameView,
                forceAppend,
                listeners
              )
            }
          }
        } else {
          childNode = morphChild(
            target,
            childNode,
            child,
            variables,
            isSameView,
            false,
            listeners
          )
        }
      }
    }
  }

  if (keys) {
    meta.keys = keys
  }

  if (childNode) {
    while (childNode.nextSibling) {
      childNode.nextSibling.remove()
    }

    childNode.remove()
  }

  if (meta._read) weakMap.set(target, meta)
}

const morphRoot = (target, next, listeners) => {
  const meta = readMeta(target)

  const isSameView = next.view === 0 || next.view === meta.view

  if (isSameView && next.view != null && !next.dynamic) {
    return
  }

  if (!isSameView) {
    meta.view = next.view
  }

  if (!isSameView || next.dynamic) {
    morph(target, next, next.variables, isSameView, meta, listeners)
  }
}

export const createDomView = (target, view) => {
  const listeners = []

  return (state) => {
    const current = resolve(view(state))

    morphRoot(target, current, listeners)

    if (current.afterUpdate) {
      current.afterUpdate(target)
    }
  }
}

const viewZero = {
  type: 'node',
  view: 0,
  dynamic: false
}

export const skipUpdate = () => viewZero

const valueTrue = {
  type: 'value',
  value: true
}

const END = Symbol('end')

const isSpaceChar = (char) => /\s/.test(char)
const isOfClose = (char) => char === '/' || char === '>' || isSpaceChar(char)
const isOfTag = (char) => !isOfClose(char)
const isOfKey = (char) => char !== '=' && !isOfClose(char)
const isQuoteChar = (char) => char === '"' || char === "'"

const tokenizer = {
  *get(acc, strs, vlength) {
    for (let index = 0, length = strs.length; index < length; index++) {
      const str = strs[index]
      let first = index > 0

      let tag = acc.tag
      let i = 0

      const current = () => str.charAt(i)
      const next = () => str.charAt(i + 1)

      while (current()) {
        if (!tag && current() === '<') {
          let value = ''
          let end = false

          if (next() === '/') {
            end = true

            i++
          }

          while (next() && isOfTag(next())) {
            i++

            value += current()
          }

          yield {
            type: !end ? 'tag' : 'endtag',
            value
          }

          first = false

          tag = value

          i++
        } else if (tag && isSpaceChar(current())) {
          i++
        } else if (tag && current() === '/' && next() === '>') {
          yield* [
            END,
            {
              type: 'endtag',
              value: tag
            },
            END
          ]

          first = false

          tag = false

          i += 2
        } else if (tag && current() === '>') {
          yield END

          first = false

          tag = false

          i++
        } else if (tag && isOfKey(current())) {
          let value = ''

          i--

          while (next() && isOfKey(next())) {
            i++

            value += current()
          }

          yield {
            type: 'key',
            value
          }

          first = false

          if (next() === '=') {
            i++

            let quote = ''
            let value = ''

            if (next() && isQuoteChar(next())) {
              i++

              quote = current()

              while (next() !== quote) {
                if (next()) {
                  i++

                  value += current()
                } else {
                  throw createQuoteError('mismatch')
                }
              }

              i++

              yield {
                type: 'value',
                value
              }
            } else if (next()) {
              throw createQuoteError('expected')
            }
          } else {
            yield valueTrue
          }

          i++
        } else if (!tag) {
          let value = ''

          while (current() && current() !== '<') {
            value += current()

            i++
          }

          let trim = true

          if (!current() && first) {
            trim = false
          }

          if ((!trim && value) || (trim && value.trim())) {
            yield {
              type: 'text',
              value
            }
          }
        }
      }

      acc.tag = tag

      if (index < vlength) {
        yield {
          type: 'variable',
          value: index
        }
      }
    }
  }
}

const parse = (tokens, parent, tag) => {
  const child = {
    tag,
    type: 'node',
    dynamic: false,
    attributes: [],
    children: []
  }

  let current

  for (;;) {
    current = tokens.next()

    if (current.done) break

    const token = current.value

    if (token === END) {
      break
    } else if (token.type === 'key') {
      const next = tokens.next()?.value

      if (next.type === 'value') {
        child.attributes.push({key: token.value, value: next.value})
      } else {
        const value = next.value

        child.dynamic = true

        child.attributes.push({
          key: token.value,
          variable: true,
          value
        })
      }
    } else if (token.type === 'variable') {
      child.dynamic = true

      child.attributes.push({
        key: false,
        variable: true,
        value: token.value
      })
    }
  }

  for (;;) {
    current = tokens.next()

    if (current.done) break

    const token = current.value

    if (token.type === 'endtag' && token.value === child.tag) {
      break
    } else if (token.type === 'tag') {
      const dynamic = parse(tokens, child, token.value)

      child.dynamic = child.dynamic || dynamic
    } else if (token.type === 'text') {
      child.children.push({
        type: 'text',
        value: token.value
      })
    } else if (token.type === 'variable') {
      child.dynamic = true

      child.children.push({
        type: 'variable',
        variable: true,
        value: token.value
      })
    }
  }

  parent.children.push(child)

  return child.dynamic
}

let view = 1

const toTemplate = (strs, vlength) => {
  const acc = {
    tag: false
  }

  const tokens = tokenizer.get(acc, strs, vlength)

  const children = []

  let current

  for (;;) {
    current = tokens.next()

    if (current.done) break

    const token = current.value

    if (token.type === 'tag') {
      parse(tokens, {children}, token.value)
    } else if (token.type === 'text') {
      children.push({value: token.value})
    }
  }

  if (children.length !== 1) {
    throw createAssertionError(children.length, 1)
  } else if (children[0].type !== 'node') {
    throw createAssertionError(children[0].type, "'node'")
  }

  children[0].view = view++

  return children[0]
}

export const html = (strs, ...variables) => {
  let result = weakMap.get(strs)

  if (!result) {
    result = toTemplate(strs, variables.length)

    weakMap.set(strs, result)
  }

  return Object.assign({variables}, result)
}

export const createApp = (state) => {
  let viewCalled
  let view

  const callView = () => {
    viewCalled = false

    return Promise.resolve().then(() => {
      if (!viewCalled) {
        viewCalled = true

        view(typeof state === 'object' ? Object.assign({}, state) : state)
      }
    })
  }

  const proxy = (state) =>
    typeof state === 'object'
      ? new Proxy(state, {
          set(state, key, val) {
            state[key] = val

            callView()

            return true
          }
        })
      : state

  state = proxy(state)

  return {
    render(v) {
      view = v

      callView()
    },
    set state(val) {
      state = proxy(val)

      callView()
    },
    get state() {
      return state
    }
  }
}
<commit_msg>Use capture for non-bubbling events<commit_after>const svgNamespace = 'http://www.w3.org/2000/svg'

const weakMap = new WeakMap()

const createQuoteError = (problem) => Error(`Quote ${problem}`)
const createAssertionError = (actual, expected) =>
  Error(`Expected ${expected}. Found ${actual}.`)

const resolve = (obj) => {
  if (typeof obj === 'function') {
    let afterUpdate

    obj = obj((cb) => {
      afterUpdate = cb
    })

    if (obj) obj.afterUpdate = afterUpdate
  }

  return obj
}

const readMeta = (target, meta = {}) => {
  if (!meta._read) {
    Object.assign(meta, weakMap.get(target) ?? {})

    meta._read = true
  }

  return meta
}

const getNextSibling = (current) => current?.nextSibling

const getListener = (key) => (e) => {
  const map = weakMap.get(e.target)

  if (map && map[key]) {
    map[key](e)
  }
}

const morphAttribute = (target, key, value, meta, listeners) => {
  const document = target.ownerDocument
  const remove = value == null || value === false

  if (key.indexOf('on') === 0) {
    readMeta(target, meta)

    if (remove) {
      if (meta[key]) {
        meta[key] = null
      }
    } else {
      meta[key] = value

      if (!listeners.includes(key)) {
        listeners.push(key)

        const type = key.substring(2)

        document.addEventListener(type, getListener(key), {capture: true})
      }
    }
  } else {
    if (remove) {
      target.removeAttribute(key)
    } else {
      const stringified = value === true ? '' : value

      if (target.getAttribute(key) !== stringified) {
        target.setAttribute(key, stringified)
      }
    }

    if (key === 'value' || value === true || value === false) {
      if (target[key] !== value) {
        target[key] = value
      }
    }
  }
}

const morphChild = (
  target,
  childNode,
  next,
  variables,
  isSameView,
  forceAppend,
  listeners
) => {
  const document = target.ownerDocument

  const append = forceAppend || childNode == null

  let replace = false

  let currentChild = childNode

  if (next.type === 'text') {
    if (!append && childNode.nodeType !== 3) {
      replace = true
    }

    if (append || replace) {
      currentChild = document.createTextNode(next.value)
    } else if (childNode.data !== next.value) {
      childNode.data = next.value
    }
  } else {
    const tag = next.tag

    if (
      !append &&
      (childNode.nodeType !== 1 || childNode.nodeName.toLowerCase() !== tag)
    ) {
      replace = true
    }

    if (append || replace) {
      const isSvg = tag === 'svg' || target.namespaceURI === svgNamespace

      currentChild = isSvg
        ? document.createElementNS(svgNamespace, tag)
        : document.createElement(tag)
    }

    if (next.view != null) {
      morphRoot(currentChild, next, listeners)
    } else if (!isSameView || next.dynamic) {
      morph(currentChild, next, variables, isSameView, {}, listeners)
    }
  }

  if (forceAppend && childNode) {
    childNode.before(currentChild)
  } else if (append) {
    target.append(currentChild)
  } else if (replace) {
    childNode.replaceWith(currentChild)
  }

  if (currentChild != null && next.afterUpdate) {
    next.afterUpdate(currentChild)
  }

  return getNextSibling(currentChild)
}

const morph = (target, next, variables, isSameView, meta, listeners) => {
  const attributesLength = next.attributes.length

  const attrNames = []

  const hasExistingAttributes = target.attributes.length

  if (attributesLength) {
    for (let i = 0, length = attributesLength; i < length; i++) {
      const attribute = next.attributes[i]

      if (!isSameView || attribute.variable) {
        let value = attribute.value

        if (attribute.variable) {
          value = variables[value]
        }

        if (attribute.key) {
          morphAttribute(target, attribute.key, value, meta, listeners)

          attrNames.push(attribute.key)
        } else {
          for (const key of Object.keys(value)) {
            morphAttribute(target, key, value[key], meta, listeners)

            attrNames.push(key)
          }
        }
      }
    }
  }

  if (!isSameView && hasExistingAttributes) {
    for (const attr of target.attributes) {
      if (!~attrNames.indexOf(attr.name)) {
        target.removeAttribute(attr.name)
      }
    }
  }

  const childrenLength = next.children.length
  let childNode = target.firstChild

  let keys

  let prevKeys

  if (childrenLength) {
    let deopt = !isSameView

    for (let childIndex = 0; childIndex < childrenLength; childIndex++) {
      let child = next.children[childIndex]

      if (!deopt && !child.dynamic && !child.variable) {
        childNode = getNextSibling(childNode)
      } else {
        deopt = true

        if (child.variable) {
          const variableValue = child.value

          child = variables[variableValue]

          if (child?.[Symbol.iterator] == null || typeof child === 'string') {
            child = [child]
          }

          let keyIndex = 0
          let lengthDifference

          for (let grand of child) {
            grand = resolve(grand)

            if (grand == null) grand = ''

            let keysMatch = true

            if (grand.key != null) {
              if (!keys) {
                keys = {}

                readMeta(target, meta)

                prevKeys = meta.keys?.[variableValue] ?? {}
              }

              if (!keys[variableValue]) {
                keys[variableValue] = []
              }

              keys[variableValue].push(grand.key)

              keysMatch = prevKeys[keyIndex] === grand.key

              grand = grand.value

              lengthDifference = child.length - prevKeys.length
            }

            keyIndex++

            if (grand.type == null) {
              grand = {type: 'text', value: grand}
            }

            if (!keysMatch && lengthDifference < 0 && childNode != null) {
              lengthDifference++

              const extraNode = childNode

              childNode = childNode.nextSibling

              extraNode.remove()
            }

            if (isSameView && grand.view != null && !grand.dynamic) {
              childNode = getNextSibling(childNode)
            } else {
              const forceAppend =
                !keysMatch && lengthDifference > 0 && childNode

              if (forceAppend) {
                lengthDifference--

                keyIndex--
              }

              childNode = morphChild(
                target,
                childNode,
                grand,
                variables,
                isSameView,
                forceAppend,
                listeners
              )
            }
          }
        } else {
          childNode = morphChild(
            target,
            childNode,
            child,
            variables,
            isSameView,
            false,
            listeners
          )
        }
      }
    }
  }

  if (keys) {
    meta.keys = keys
  }

  if (childNode) {
    while (childNode.nextSibling) {
      childNode.nextSibling.remove()
    }

    childNode.remove()
  }

  if (meta._read) weakMap.set(target, meta)
}

const morphRoot = (target, next, listeners) => {
  const meta = readMeta(target)

  const isSameView = next.view === 0 || next.view === meta.view

  if (isSameView && next.view != null && !next.dynamic) {
    return
  }

  if (!isSameView) {
    meta.view = next.view
  }

  if (!isSameView || next.dynamic) {
    morph(target, next, next.variables, isSameView, meta, listeners)
  }
}

export const createDomView = (target, view) => {
  const listeners = []

  return (state) => {
    const current = resolve(view(state))

    morphRoot(target, current, listeners)

    if (current.afterUpdate) {
      current.afterUpdate(target)
    }
  }
}

const viewZero = {
  type: 'node',
  view: 0,
  dynamic: false
}

export const skipUpdate = () => viewZero

const valueTrue = {
  type: 'value',
  value: true
}

const END = Symbol('end')

const isSpaceChar = (char) => /\s/.test(char)
const isOfClose = (char) => char === '/' || char === '>' || isSpaceChar(char)
const isOfTag = (char) => !isOfClose(char)
const isOfKey = (char) => char !== '=' && !isOfClose(char)
const isQuoteChar = (char) => char === '"' || char === "'"

const tokenizer = {
  *get(acc, strs, vlength) {
    for (let index = 0, length = strs.length; index < length; index++) {
      const str = strs[index]
      let first = index > 0

      let tag = acc.tag
      let i = 0

      const current = () => str.charAt(i)
      const next = () => str.charAt(i + 1)

      while (current()) {
        if (!tag && current() === '<') {
          let value = ''
          let end = false

          if (next() === '/') {
            end = true

            i++
          }

          while (next() && isOfTag(next())) {
            i++

            value += current()
          }

          yield {
            type: !end ? 'tag' : 'endtag',
            value
          }

          first = false

          tag = value

          i++
        } else if (tag && isSpaceChar(current())) {
          i++
        } else if (tag && current() === '/' && next() === '>') {
          yield* [
            END,
            {
              type: 'endtag',
              value: tag
            },
            END
          ]

          first = false

          tag = false

          i += 2
        } else if (tag && current() === '>') {
          yield END

          first = false

          tag = false

          i++
        } else if (tag && isOfKey(current())) {
          let value = ''

          i--

          while (next() && isOfKey(next())) {
            i++

            value += current()
          }

          yield {
            type: 'key',
            value
          }

          first = false

          if (next() === '=') {
            i++

            let quote = ''
            let value = ''

            if (next() && isQuoteChar(next())) {
              i++

              quote = current()

              while (next() !== quote) {
                if (next()) {
                  i++

                  value += current()
                } else {
                  throw createQuoteError('mismatch')
                }
              }

              i++

              yield {
                type: 'value',
                value
              }
            } else if (next()) {
              throw createQuoteError('expected')
            }
          } else {
            yield valueTrue
          }

          i++
        } else if (!tag) {
          let value = ''

          while (current() && current() !== '<') {
            value += current()

            i++
          }

          let trim = true

          if (!current() && first) {
            trim = false
          }

          if ((!trim && value) || (trim && value.trim())) {
            yield {
              type: 'text',
              value
            }
          }
        }
      }

      acc.tag = tag

      if (index < vlength) {
        yield {
          type: 'variable',
          value: index
        }
      }
    }
  }
}

const parse = (tokens, parent, tag) => {
  const child = {
    tag,
    type: 'node',
    dynamic: false,
    attributes: [],
    children: []
  }

  let current

  for (;;) {
    current = tokens.next()

    if (current.done) break

    const token = current.value

    if (token === END) {
      break
    } else if (token.type === 'key') {
      const next = tokens.next()?.value

      if (next.type === 'value') {
        child.attributes.push({key: token.value, value: next.value})
      } else {
        const value = next.value

        child.dynamic = true

        child.attributes.push({
          key: token.value,
          variable: true,
          value
        })
      }
    } else if (token.type === 'variable') {
      child.dynamic = true

      child.attributes.push({
        key: false,
        variable: true,
        value: token.value
      })
    }
  }

  for (;;) {
    current = tokens.next()

    if (current.done) break

    const token = current.value

    if (token.type === 'endtag' && token.value === child.tag) {
      break
    } else if (token.type === 'tag') {
      const dynamic = parse(tokens, child, token.value)

      child.dynamic = child.dynamic || dynamic
    } else if (token.type === 'text') {
      child.children.push({
        type: 'text',
        value: token.value
      })
    } else if (token.type === 'variable') {
      child.dynamic = true

      child.children.push({
        type: 'variable',
        variable: true,
        value: token.value
      })
    }
  }

  parent.children.push(child)

  return child.dynamic
}

let view = 1

const toTemplate = (strs, vlength) => {
  const acc = {
    tag: false
  }

  const tokens = tokenizer.get(acc, strs, vlength)

  const children = []

  let current

  for (;;) {
    current = tokens.next()

    if (current.done) break

    const token = current.value

    if (token.type === 'tag') {
      parse(tokens, {children}, token.value)
    } else if (token.type === 'text') {
      children.push({value: token.value})
    }
  }

  if (children.length !== 1) {
    throw createAssertionError(children.length, 1)
  } else if (children[0].type !== 'node') {
    throw createAssertionError(children[0].type, "'node'")
  }

  children[0].view = view++

  return children[0]
}

export const html = (strs, ...variables) => {
  let result = weakMap.get(strs)

  if (!result) {
    result = toTemplate(strs, variables.length)

    weakMap.set(strs, result)
  }

  return Object.assign({variables}, result)
}

export const createApp = (state) => {
  let viewCalled
  let view

  const callView = () => {
    viewCalled = false

    return Promise.resolve().then(() => {
      if (!viewCalled) {
        viewCalled = true

        view(typeof state === 'object' ? Object.assign({}, state) : state)
      }
    })
  }

  const proxy = (state) =>
    typeof state === 'object'
      ? new Proxy(state, {
          set(state, key, val) {
            state[key] = val

            callView()

            return true
          }
        })
      : state

  state = proxy(state)

  return {
    render(v) {
      view = v

      callView()
    },
    set state(val) {
      state = proxy(val)

      callView()
    },
    get state() {
      return state
    }
  }
}
<|endoftext|>


<commit_before>import React,{ Component } from 'react';
import {Animation} from '../../lib';
import range from 'lodash.range';
import assign from 'lodash.assign';
import flatten from 'lodash.flatten';

export default class SpinningDots extends Component {
    constructor() {
        super();
        this.state = {
            layers: 9,
            start: 4,
            width: 0,
            height: 0
        };
    }

    componentDidMount() {
        // store the height and width of the container
        let width = this.refs.container.clientWidth;
        let height = this.refs.container.clientHeight;

        // now that we know the size, re-render the stars
        this.setState({ width, height });
    }

    getStyles() {
        return {
            body: {
                background: '#0e7cf0',
                margin: '0px',
                color: 'white',
                position: 'absolute',
                top: 0,
                left: 0,
                width: '100%',
                height: '100%'
            },
            a: {
                color: '#6db0f7'
            },
            circle: {
                background: '#2a2a2a',
                borderRadius: '50%',
                width: '10px',
                height: '10px',
                position: 'absolute',
                top: '50%',
                left: '50%'
            },
            sourceLink: {
                textDecoration: 'none',
                padding: '6px',
                fontFamily: 'Roboto',
                fontWeight: 'bold',
                backgroundColor: 'white',
                color: 'black',
                position: 'absolute',
                top: 0,
                right: 0
            }
        };
    }

    getRotationAndTranslateForCircle( layer, fraction ) {
        const rotate = `rotate(${(360 * fraction)}deg)`;
        const translate = `translate(${(layer * 20 - 2.5)}px)`;
        return { rotation: rotate, translation: translate };
    }

    getAnimationForCircle( layer, rotation, translation ) {

        return {
            keyframes: [
                { transform: rotation + ' rotate(0deg) ' + translation },
                { transform: rotation + ' rotate(360deg) ' + translation }
            ], timing: {
                duration: 1000 * layer,
                iterations: Infinity
            }
        };
    }

    renderCircles( layerCount, startCount ) {

        let {circle} = this.getStyles();

        return flatten(range(layerCount).map(( l, idx ) => {
            const n = idx * startCount;

            return range(n).map(( c, cIdx ) => {

                let {rotation,translation} = this.getRotationAndTranslateForCircle(idx, cIdx / n);
                let {keyframes,timing} = this.getAnimationForCircle(idx, rotation, translation);

                return <Animation key={idx + '_' + cIdx} keyframes={keyframes} timing={timing}>
                    <div style={assign({},circle,{transform: `${rotation} ${translation}`})}>

                </Animation>;
            });
        }));

    }

    render() {
        const {body,sourceLink} = this.getStyles();
        const {layers,start} = this.state;

        return

            {this.renderCircles(layers, start)}

                View Source

;
    }
}
<commit_msg>remove width and height measurement on spinning dots. not needed<commit_after>import React,{ Component } from 'react';
import {Animation} from '../../lib';
import range from 'lodash.range';
import assign from 'lodash.assign';
import flatten from 'lodash.flatten';

export default class SpinningDots extends Component {
    constructor() {
        super();
        this.state = {
            layers: 9,
            start: 4
        };
    }

    getStyles() {
        return {
            body: {
                background: '#0e7cf0',
                margin: '0px',
                color: 'white',
                position: 'absolute',
                top: 0,
                left: 0,
                width: '100%',
                height: '100%'
            },
            a: {
                color: '#6db0f7'
            },
            circle: {
                background: '#2a2a2a',
                borderRadius: '50%',
                width: '10px',
                height: '10px',
                position: 'absolute',
                top: '50%',
                left: '50%'
            },
            sourceLink: {
                textDecoration: 'none',
                padding: '6px',
                fontFamily: 'Roboto',
                fontWeight: 'bold',
                backgroundColor: 'white',
                color: 'black',
                position: 'absolute',
                top: 0,
                right: 0
            }
        };
    }

    getRotationAndTranslateForCircle( layer, fraction ) {
        const rotate = `rotate(${(360 * fraction)}deg)`;
        const translate = `translate(${(layer * 20 - 2.5)}px)`;
        return { rotation: rotate, translation: translate };
    }

    getAnimationForCircle( layer, rotation, translation ) {

        return {
            keyframes: [
                { transform: rotation + ' rotate(0deg) ' + translation },
                { transform: rotation + ' rotate(360deg) ' + translation }
            ], timing: {
                duration: 1000 * layer,
                iterations: Infinity
            }
        };
    }

    renderCircles( layerCount, startCount ) {

        let {circle} = this.getStyles();

        return flatten(range(layerCount).map(( l, idx ) => {
            const n = idx * startCount;

            return range(n).map(( c, cIdx ) => {

                let {rotation,translation} = this.getRotationAndTranslateForCircle(idx, cIdx / n);
                let {keyframes,timing} = this.getAnimationForCircle(idx, rotation, translation);

                return <Animation key={idx + '_' + cIdx} keyframes={keyframes} timing={timing}>
                    <div style={assign({},circle,{transform: `${rotation} ${translation}`})}>

                </Animation>;
            });
        }));

    }

    render() {
        const {body,sourceLink} = this.getStyles();
        const {layers,start} = this.state;

        return

            {this.renderCircles(layers, start)}

                View Source

;
    }
}
<|endoftext|>


<commit_before>(function(){
    RestDS = function(readKey,writeKey,_post_path){
        this.data = "";
        this.enableLoadAndSave = true;
        this.postPath = _post_path || "/models/";
        this.getPath = this.postPath;
        this.setKeys(readKey,writeKey);
    };

    RestDS.prototype =
    {
        setKeys: function(read,write) {
            if (read) {
                this.load(this,function(){});// just load data
                this.readKey = read;
            }
            if (write) {
                this.writeKey = write;
            }
            else {
                this.writeKey= this.randomString();
            }
        },

        randomString: function() {
            var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
            var string_length = 8;
            var randomstring = '';
            for (var i=0; i<string_length; i++) {
                var rnum = Math.floor(Math.random() * chars.length);
                randomstring += chars.substring(rnum,rnum+1);
            }
            return randomstring;
        },

        // write the data
        save: function(_data) {
            this.data = _data;
            //var post_to = this.postPath + this.writeKey;
            var post_to = this.postPath;
            debug('post_to=' + post_to);
            /*
            var xmlhttp = HTTP.newRequest();
            xmlhttp.open('PUT', post_to, false);
            xmlhttp.send(this.data);
            */
            jQuery.post(post_to, this.data);
            this.readKey = this.writeKey;
            $('#readKey').text("Your Key:" + this.readKey);
            debug("readKey written: " + this.readKey);
        },

        load: function(context,callback) {
            if (this.readKey) {
                //var key = prompt("Please enter the model to load: ", this.readKey);
            	var key = this.readKey;
                this.writeKey = key;
                this.readKey = key;
            }
            else {
                if (this.writeKey) {
                    this.readKey = this.writeKey;
                }
                else {
                    this.readKey = this.writeKey = this.randomString();
                }
            }
            var get_from = this.getPath  + this.readKey;
            var self = this;
            debug("just about to load with " + this.readKey);
            if (this.readKey) {
                self = this;
                /*
                new Ajax.Request(get_from, {
                    asynchronous: true,
                    method: 'GET',
                    onSuccess: function(rsp) {
                        var text = rsp.responseText;
                        var _data = eval(text);
                        self.data = _data;
                        callback(_data,context,callback);
                        debug("returned from load");
                    },
                    onFailure: function(req,err) {
                        debug("failed!");
                    }
                });
                */
                jQuery.get(get_from, function(rsp, textStatus) {
                    console.log('rsp=' + rsp);
                    //var text = rsp.responseText;
                    var _data = eval(rsp);
                    self.data = _data;
                    callback(_data,context,callback);
                    debug("returned from load");
                });
            }
            else {
                debug("load caleld, but no read key specified...");
            }
        },

        toString: function() {
            return "Data Service (" + this.postPath + "" + this.writeKey + ")";
        }
    };
})();<commit_msg>Don't include read_key in the request path<commit_after>(function(){
    RestDS = function(readKey,writeKey,_post_path){
        this.data = "";
        this.enableLoadAndSave = true;
        this.postPath = _post_path || "/models/";
        this.getPath = this.postPath;
        this.setKeys(readKey,writeKey);
    };

    RestDS.prototype =
    {
        setKeys: function(read,write) {
            if (read) {
                this.load(this,function(){});// just load data
                this.readKey = read;
            }
            if (write) {
                this.writeKey = write;
            }
            else {
                this.writeKey= this.randomString();
            }
        },

        randomString: function() {
            var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
            var string_length = 8;
            var randomstring = '';
            for (var i=0; i<string_length; i++) {
                var rnum = Math.floor(Math.random() * chars.length);
                randomstring += chars.substring(rnum,rnum+1);
            }
            return randomstring;
        },

        // write the data
        save: function(_data) {
            this.data = _data;
            //var post_to = this.postPath + this.writeKey;
            var post_to = this.postPath;
            debug('post_to=' + post_to);
            /*
            var xmlhttp = HTTP.newRequest();
            xmlhttp.open('PUT', post_to, false);
            xmlhttp.send(this.data);
            */
            jQuery.post(post_to, this.data);
            this.readKey = this.writeKey;
            $('#readKey').text("Your Key:" + this.readKey);
            debug("readKey written: " + this.readKey);
        },

        load: function(context,callback) {
            if (this.readKey) {
                //var key = prompt("Please enter the model to load: ", this.readKey);
            	var key = this.readKey;
                this.writeKey = key;
                this.readKey = key;
            }
            else {
                if (this.writeKey) {
                    this.readKey = this.writeKey;
                }
                else {
                    this.readKey = this.writeKey = this.randomString();
                }
            }
            //var get_from = this.getPath  + this.readKey;
            var get_from = this.getPath;
            var self = this;
            debug("just about to load with " + this.readKey);
            if (this.readKey) {
                self = this;
                /*
                new Ajax.Request(get_from, {
                    asynchronous: true,
                    method: 'GET',
                    onSuccess: function(rsp) {
                        var text = rsp.responseText;
                        var _data = eval(text);
                        self.data = _data;
                        callback(_data,context,callback);
                        debug("returned from load");
                    },
                    onFailure: function(req,err) {
                        debug("failed!");
                    }
                });
                */
                jQuery.get(get_from, function(rsp, textStatus) {
                    console.log('rsp=' + rsp);
                    //var text = rsp.responseText;
                    var _data = eval(rsp);
                    self.data = _data;
                    callback(_data,context,callback);
                    debug("returned from load");
                });
            }
            else {
                debug("load caleld, but no read key specified...");
            }
        },

        toString: function() {
            return "Data Service (" + this.postPath + "" + this.writeKey + ")";
        }
    };
})();<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import TextBox from '../textbox';
import I18nHelper from '../../../utils/helpers/i18n';

class Decimal extends React.Component {
  state = {
    value: '0.00'
  }

  // componentDidUpdate(prevProps, prevState) {
  //   const test = this.testValue();
  //   console.log(prevState.value, this.props.value)
  //   console.log(prevState.value !== this.props.value, test)
  //   if (prevState.value !== this.props.value && test) {
  //     this.setState({
  //       value: this.props.value
  //     })
  //   }
  // }

  testValue = (value) => {
    const { precision } = this.props;

    const regex = /^[\d,]*[\.{1}]?\d{0,2}?$/;
    const isGoodDecimal = regex.test(value);
    console.log(value)
    console.log(isGoodDecimal)
    if (!isGoodDecimal) { return false; }

    return true;
  }

  handleChange = (evt) => {
    const target = evt.target;
    const { value, selectionEnd } = target;
    const testString = this.testValue(value);

    console.log(value)
    console.log(testString)

    if (testString) {
      this.setState({ value });
      this.props.onChange({ target: { value: value } })
      setTimeout(() => {
        target.setSelectionRange(selectionEnd, selectionEnd)
      });
    }
  }

  render() {
    return (
      <TextBox
        {...this.props}
        onChange={ this.handleChange }
        value={ this.state.value }
      />
    );
  }
};

Decimal.propTypes = {
  /**
   * The default value alignment on the input
   */
  align: PropTypes.string,
  /**
   * The decimal precision of the value in the input
   */
  precision: PropTypes.number,
  /**
   * The width of the input as a percentage
   */
  inputWidth: PropTypes.number,
  /**
   * The value of the input
   */
  value: PropTypes.string
}

Decimal.defaultProps = {
  align: 'left',
  precision: 2,
  inputWidth: 100
};

export default Decimal;
<commit_msg>Refactor and Dynamic Vars in Decimal<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import TextBox from '../textbox';
import I18nHelper from '../../../utils/helpers/i18n';

class Decimal extends React.Component {
  state = {
    value: '0.00'
  }

  testValue = (value) => {
    const { precision } = this.props;
    const format = I18nHelper.format();
    const del = `\\${format.delimiter}`;
    const sep = `\\${format.separator}`;

    const regex = new RegExp(`^[\\d${del}]*[${sep}{1}]?\\d{0,${precision}}?$`);
    const isGoodDecimal = regex.test(value);

    return isGoodDecimal;
  }

  handleChange = (evt) => {
    const target = evt.target;
    const { value, selectionEnd } = evt.target;
    const testString = this.testValue(value);

    if (testString) {
      this.setState({ value });
      this.props.onChange({ target: { value: value } })
      setTimeout(() => {
        target.setSelectionRange(selectionEnd, selectionEnd)
      });
    }
  }

  render() {
    return (
      <TextBox
        {...this.props}
        onChange={ this.handleChange }
        value={ this.state.value }
      />
    );
  }
};

Decimal.propTypes = {
  /**
   * The default value alignment on the input
   */
  align: PropTypes.string,
  /**
   * The decimal precision of the value in the input
   */
  precision: PropTypes.number,
  /**
   * The width of the input as a percentage
   */
  inputWidth: PropTypes.number,
  /**
   * The value of the input
   */
  value: PropTypes.string
}

Decimal.defaultProps = {
  align: 'left',
  precision: 2,
  inputWidth: 100
};

export default Decimal;
<|endoftext|>


<commit_before>'use strict';
const {globalShortcut, BrowserWindow, app} = require('electron');
const isAccelerator = require('electron-is-accelerator');
const _debug = require('debug');

const debug = _debug('electron-localshortcut');
const windowsWithShortcuts = new WeakMap();

// A placeholder to register shortcuts
// on any window of the app.
const ANY_WINDOW = {};

let _enableShortcut = shortcut => {
	debug(`Calling globalShortcut.register(${shortcut.accelerator}, ${shortcut.callback.name})`);
	globalShortcut.register(shortcut.accelerator, shortcut.callback);
	shortcut.registered = true;
};

let _disableShortcut = shortcut => {
	debug(`Calling globalShortcut.unregister(${shortcut.accelerator})`);
	globalShortcut.unregister(shortcut.accelerator);
	shortcut.registered = false;
};

function __mockup(enableShortcut, disableShortcut) {
	_enableShortcut = enableShortcut;
	_disableShortcut = disableShortcut;
}

function _enableWindowAndApp(win) {
	debug(`_enableWindowAndApp ${win.getTitle && win.getTitle()}`);
	if (windowsWithShortcuts.has(ANY_WINDOW)) {
		enableAll(ANY_WINDOW);
	}

	if (!windowsWithShortcuts.has(win)) {
		return;
	}

	enableAll(win);
}

function _disableWindowAndApp(win) {
	debug(`_disableWindowAndApp ${win.getTitle && win.getTitle()}`);
	if (windowsWithShortcuts.has(ANY_WINDOW)) {
		disableAll(ANY_WINDOW);
	}

	if (!windowsWithShortcuts.has(win)) {
		return;
	}

	disableAll(win);
}

function _indexOfShortcut(win, accelerator) {
	if (!windowsWithShortcuts.has(win)) {
		return -1;
	}
	_checkAccelerator(accelerator);

	const shortcuts = windowsWithShortcuts.get(win);
	let shortcutToUnregisterIdx = -1;
	shortcuts.some((s, idx) => {
		if (s.accelerator === accelerator) {
			shortcutToUnregisterIdx = idx;
			return true;
		}
		return false;
	});
	return shortcutToUnregisterIdx;
}

function _checkAccelerator(accelerator) {
	if (!isAccelerator(accelerator)) {
		const w = {};
		Error.captureStackTrace(w);
		const msg = `
WARNING: ${accelerator} is not a valid accelerator.

${w.stack.split('\n').slice(4).join('\n')}
`;
		console.error(msg);
	}
}

/**
 * Disable all of the shortcuts registered on the BrowserWindow instance.
Registered shortcuts no more works on the `window` instance, but the module keep a reference on them. You can reactivate them later by calling `enableAll` method on the same window instance.
 * @param  {BrowserWindow} win BrowserWindow instance
 * @return {Undefined}
 */
function disableAll(win) {
	const shortcuts = windowsWithShortcuts.get(win);
	if (shortcuts) {
		shortcuts.forEach(_disableShortcut);
	}
}

/**
 * Enable all of the shortcuts registered on the BrowserWindow instance that you had previously disabled calling `disableAll` method.
 * @param  {BrowserWindow} win BrowserWindow instance
 * @return {Undefined}
 */
function enableAll(win) {
	const shortcuts = windowsWithShortcuts.get(win);
	if (shortcuts) {
		shortcuts.forEach(_enableShortcut);
	}
}

/**
 * Unregisters all of the shortcuts registered on any focused BrowserWindow instance. This method does not unregister any shortcut you registered on a particular window instance.
 * @param  {BrowserWindow} win BrowserWindow instance
 * @return {Undefined}
 */
function unregisterAll(win) {
	if (win === undefined) {
		// Unregister shortcuts for any window in the app
		unregisterAll(ANY_WINDOW);
		return;
	}

	if (!windowsWithShortcuts.has(win)) {
		return;
	}

	disableAll(win);
	windowsWithShortcuts.delete(win);
}

/**
* Registers the shortcut `accelerator`on the BrowserWindow instance.
 * @param  {BrowserWindow} win - BrowserWindow instance to register. This argument could be omitted, in this case the function register the shortcut on all app windows.
 * @param  {String} accelerator - the shortcut to register
 * @param  {Function} callback    This function is called when the shortcut is pressed and the window is focused and not minimized.
 * @return {Undefined}
 */
function register(win, accelerator, callback) {
	if (arguments.length === 2 && typeof win === 'string') {
		// Register shortcut for any window in the app
		// win = accelerator, accelerator = callback
		register(ANY_WINDOW, win, accelerator);
		return;
	}

	_checkAccelerator(accelerator);

	const newShortcut = {accelerator, callback, registered: false};

	const _unregister = because => () => {
		debug(`Disabling shortcuts for app and for window '${(win.getTitle && win.getTitle()) || 'No name'}' because ${because}.`);
		_disableWindowAndApp(win);
	};

	const _register = because => () => {
		debug(`Enabling shortcuts for app and for window '${(win.getTitle && win.getTitle()) || 'No name'}' because ${because}.`);
		_enableWindowAndApp(win);
	};

	if (windowsWithShortcuts.has(win)) {
		const shortcuts = windowsWithShortcuts.get(win);
		shortcuts.push(newShortcut);
	} else {
		windowsWithShortcuts.set(win, [newShortcut]);

		if (win !== ANY_WINDOW) {
			win.on('close', _unregister('the window was closed.'));

			win.on('hide', _unregister('the window was hidden.'));

			win.on('minimize', _unregister('the window was minimized.'));

			win.on('restore', _register('the window was restored from minimized state.'));

			win.on('show', _register('the window was showed.'));
		}
	}

	const focusedWin = BrowserWindow.getFocusedWindow();
	const registeringAppShortcut = win === ANY_WINDOW;
	const appHasFocus = focusedWin !== null && focusedWin.isVisible();
	const registeringWindowHasFocus = focusedWin === win;
	const registeringWindowIsMinimized = () => focusedWin.isMinimized();

	if ((registeringAppShortcut && appHasFocus) ||
		(registeringWindowHasFocus && !registeringWindowIsMinimized())) {
		_register('the window was focused at shortcut registration.');
	}
}

/**
 * Unregisters the shortcut of `accelerator` registered on the BrowserWindow instance.
 * @param  {BrowserWindow} win - BrowserWindow instance to unregister. This argument could be omitted, in this case the function unregister the shortcut on all app windows. If you registered the shortcut on a particular window instance, it will do nothing.
 * @param  {String} accelerator - the shortcut to unregister
 * @return {Undefined}
 */
function unregister(win, accelerator) {
	if (arguments.length === 1 && typeof win === 'string') {
		// Unregister shortcut for any window in the app
		// win === accelerator
		unregister(ANY_WINDOW, win);
		return;
	}

	_checkAccelerator(accelerator);

	const shortcutToUnregisterIdx = _indexOfShortcut(win, accelerator);

	if (shortcutToUnregisterIdx !== -1) {
		_disableShortcut(accelerator);
		const shortcuts = windowsWithShortcuts.get(win);
		shortcuts.splice(shortcutToUnregisterIdx, 1);
	}
}

/**
 * Returns `true` or `false` depending on whether the shortcut `accelerator` is
registered on `window`.
 * @param  {BrowserWindow} win - BrowserWindow instance to check. This argument could be omitted, in this case the function returns whether the shortcut `accelerator` is registered on all app windows. If you registered the shortcut on a particular window instance, it return false.
 * @param  {String} accelerator - the shortcut to check
 * @return {Boolean} - if the shortcut `accelerator` is registered on `window`.
 */
function isRegistered(win, accelerator) {
	if (arguments.length === 1 && typeof win === 'string') {
		// Check shortcut for any window in the app
		// win = accelerator
		return isRegistered(ANY_WINDOW, win);
	}

	_checkAccelerator(accelerator);

	return _indexOfShortcut(win, accelerator) !== -1;
}

const windowBlur = because => (_, win) => {
	debug(`Disabling shortcuts for app and for window '${(win.getTitle && win.getTitle()) || 'No name'}' because ${because}.`);
	_disableWindowAndApp(win);
};

const windowFocus = because => (_, win) => {
	debug(`Enabling shortcuts for app and for window '${(win.getTitle && win.getTitle()) || 'No name'}' because ${because}.`);
	_enableWindowAndApp(win);
};

app.on('browser-window-focus', windowFocus('the window gained focus'));
app.on('browser-window-blur', windowBlur('the window loose focus'));

// All shortcuts should be unregistered by closing the window.
// just for double check
app.on('window-all-closed', unregisterAll);

module.exports = {
	register,
	unregister,
	isRegistered,
	unregisterAll,
	enableAll,
	disableAll,
	__mockup
};
<commit_msg>Fix memory leakage after calling unregisterAll()<commit_after>'use strict';
const {globalShortcut, BrowserWindow, app} = require('electron');
const isAccelerator = require('electron-is-accelerator');
const _debug = require('debug');

const debug = _debug('electron-localshortcut');
const windowsWithShortcuts = new WeakMap();
const windowsEventCallbacks = new WeakMap();

// A placeholder to register shortcuts
// on any window of the app.
const ANY_WINDOW = {};

let _enableShortcut = shortcut => {
	debug(`Calling globalShortcut.register(${shortcut.accelerator}, ${shortcut.callback.name})`);
	globalShortcut.register(shortcut.accelerator, shortcut.callback);
	shortcut.registered = true;
};

let _disableShortcut = shortcut => {
	debug(`Calling globalShortcut.unregister(${shortcut.accelerator})`);
	globalShortcut.unregister(shortcut.accelerator);
	shortcut.registered = false;
};

function __mockup(enableShortcut, disableShortcut) {
	_enableShortcut = enableShortcut;
	_disableShortcut = disableShortcut;
}

function _enableWindowAndApp(win) {
	debug(`_enableWindowAndApp ${win.getTitle && win.getTitle()}`);
	if (windowsWithShortcuts.has(ANY_WINDOW)) {
		enableAll(ANY_WINDOW);
	}

	if (!windowsWithShortcuts.has(win)) {
		return;
	}

	enableAll(win);
}

function _disableWindowAndApp(win) {
	debug(`_disableWindowAndApp ${win.getTitle && win.getTitle()}`);
	if (windowsWithShortcuts.has(ANY_WINDOW)) {
		disableAll(ANY_WINDOW);
	}

	if (!windowsWithShortcuts.has(win)) {
		return;
	}

	disableAll(win);
}

function _indexOfShortcut(win, accelerator) {
	if (!windowsWithShortcuts.has(win)) {
		return -1;
	}
	_checkAccelerator(accelerator);

	const shortcuts = windowsWithShortcuts.get(win);
	let shortcutToUnregisterIdx = -1;
	shortcuts.some((s, idx) => {
		if (s.accelerator === accelerator) {
			shortcutToUnregisterIdx = idx;
			return true;
		}
		return false;
	});
	return shortcutToUnregisterIdx;
}

function _checkAccelerator(accelerator) {
	if (!isAccelerator(accelerator)) {
		const w = {};
		Error.captureStackTrace(w);
		const msg = `
WARNING: ${accelerator} is not a valid accelerator.

${w.stack.split('\n').slice(4).join('\n')}
`;
		console.error(msg);
	}
}

/**
 * Disable all of the shortcuts registered on the BrowserWindow instance.
Registered shortcuts no more works on the `window` instance, but the module keep a reference on them. You can reactivate them later by calling `enableAll` method on the same window instance.
 * @param  {BrowserWindow} win BrowserWindow instance
 * @return {Undefined}
 */
function disableAll(win) {
	const shortcuts = windowsWithShortcuts.get(win);
	if (shortcuts) {
		shortcuts.forEach(_disableShortcut);
	}
}

/**
 * Enable all of the shortcuts registered on the BrowserWindow instance that you had previously disabled calling `disableAll` method.
 * @param  {BrowserWindow} win BrowserWindow instance
 * @return {Undefined}
 */
function enableAll(win) {
	const shortcuts = windowsWithShortcuts.get(win);
	if (shortcuts) {
		shortcuts.forEach(_enableShortcut);
	}
}

/**
 * Unregisters all of the shortcuts registered on any focused BrowserWindow instance. This method does not unregister any shortcut you registered on a particular window instance.
 * @param  {BrowserWindow} win BrowserWindow instance
 * @return {Undefined}
 */
function unregisterAll(win) {
	if (win === undefined) {
		// Unregister shortcuts for any window in the app
		unregisterAll(ANY_WINDOW);
		return;
	}

	if (!windowsWithShortcuts.has(win)) {
		return;
	}

	disableAll(win);
	windowsWithShortcuts.delete(win);

	/* unregister all event callbacks */
	const eventCallbacks = windowsEventCallbacks.get(win);
	for(let key in eventCallbacks) {
		win.removeListener(key, eventCallbacks[key]);
	}
	windowsEventCallbacks.delete(win);
}

/**
* Registers the shortcut `accelerator`on the BrowserWindow instance.
 * @param  {BrowserWindow} win - BrowserWindow instance to register. This argument could be omitted, in this case the function register the shortcut on all app windows.
 * @param  {String} accelerator - the shortcut to register
 * @param  {Function} callback    This function is called when the shortcut is pressed and the window is focused and not minimized.
 * @return {Undefined}
 */
function register(win, accelerator, callback) {
	if (arguments.length === 2 && typeof win === 'string') {
		// Register shortcut for any window in the app
		// win = accelerator, accelerator = callback
		register(ANY_WINDOW, win, accelerator);
		return;
	}

	_checkAccelerator(accelerator);

	const newShortcut = {accelerator, callback, registered: false};

	const _unregister = because => () => {
		debug(`Disabling shortcuts for app and for window '${(win.getTitle && win.getTitle()) || 'No name'}' because ${because}.`);
		_disableWindowAndApp(win);
	};

	const _register = because => () => {
		debug(`Enabling shortcuts for app and for window '${(win.getTitle && win.getTitle()) || 'No name'}' because ${because}.`);
		_enableWindowAndApp(win);
	};

	if (windowsWithShortcuts.has(win)) {
		const shortcuts = windowsWithShortcuts.get(win);
		shortcuts.push(newShortcut);
	} else {
		windowsWithShortcuts.set(win, [newShortcut]);

		if (win !== ANY_WINDOW) {
			const eventCallbacks = {
				'close': _unregister('the window was closed.'),
				'hide': _unregister('the window was hidden.'),
				'minimize': _unregister('the window was minimized.'),
				'restore': _register('the window was restored from minimized state.'),
				'show': _register('the window was showed.')
			};

			for(let key in eventCallbacks) {
				win.on(key, eventCallbacks[key]);
			}

			windowsEventCallbacks.set(win, eventCallbacks);
		}
	}

	const focusedWin = BrowserWindow.getFocusedWindow();
	const registeringAppShortcut = win === ANY_WINDOW;
	const appHasFocus = focusedWin !== null && focusedWin.isVisible();
	const registeringWindowHasFocus = focusedWin === win;
	const registeringWindowIsMinimized = () => focusedWin.isMinimized();

	if ((registeringAppShortcut && appHasFocus) ||
		(registeringWindowHasFocus && !registeringWindowIsMinimized())) {
		_register('the window was focused at shortcut registration.');
	}
}

/**
 * Unregisters the shortcut of `accelerator` registered on the BrowserWindow instance.
 * @param  {BrowserWindow} win - BrowserWindow instance to unregister. This argument could be omitted, in this case the function unregister the shortcut on all app windows. If you registered the shortcut on a particular window instance, it will do nothing.
 * @param  {String} accelerator - the shortcut to unregister
 * @return {Undefined}
 */
function unregister(win, accelerator) {
	if (arguments.length === 1 && typeof win === 'string') {
		// Unregister shortcut for any window in the app
		// win === accelerator
		unregister(ANY_WINDOW, win);
		return;
	}

	_checkAccelerator(accelerator);

	const shortcutToUnregisterIdx = _indexOfShortcut(win, accelerator);

	if (shortcutToUnregisterIdx !== -1) {
		_disableShortcut(accelerator);
		const shortcuts = windowsWithShortcuts.get(win);
		shortcuts.splice(shortcutToUnregisterIdx, 1);
	}
}

/**
 * Returns `true` or `false` depending on whether the shortcut `accelerator` is
registered on `window`.
 * @param  {BrowserWindow} win - BrowserWindow instance to check. This argument could be omitted, in this case the function returns whether the shortcut `accelerator` is registered on all app windows. If you registered the shortcut on a particular window instance, it return false.
 * @param  {String} accelerator - the shortcut to check
 * @return {Boolean} - if the shortcut `accelerator` is registered on `window`.
 */
function isRegistered(win, accelerator) {
	if (arguments.length === 1 && typeof win === 'string') {
		// Check shortcut for any window in the app
		// win = accelerator
		return isRegistered(ANY_WINDOW, win);
	}

	_checkAccelerator(accelerator);

	return _indexOfShortcut(win, accelerator) !== -1;
}

const windowBlur = because => (_, win) => {
	debug(`Disabling shortcuts for app and for window '${(win.getTitle && win.getTitle()) || 'No name'}' because ${because}.`);
	_disableWindowAndApp(win);
};

const windowFocus = because => (_, win) => {
	debug(`Enabling shortcuts for app and for window '${(win.getTitle && win.getTitle()) || 'No name'}' because ${because}.`);
	_enableWindowAndApp(win);
};

app.on('browser-window-focus', windowFocus('the window gained focus'));
app.on('browser-window-blur', windowBlur('the window loose focus'));

// All shortcuts should be unregistered by closing the window.
// just for double check
app.on('window-all-closed', unregisterAll);

module.exports = {
	register,
	unregister,
	isRegistered,
	unregisterAll,
	enableAll,
	disableAll,
	__mockup
};
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'

import FaAngleDown from 'react-icons/lib/fa/angle-down'

import styles from './SubmitChannelForm.scss'

class SubmitChannelForm extends React.Component {
  render() {
    const {
      closeChannelForm,
      closeContactsForm,

      node,
      contactCapacity,
      updateContactCapacity,
      openChannel,

      toggleCurrencyProps: {
        setContactsCurrencyFilters,
        showCurrencyFilters,
        currencyName,
        currentCurrencyFilters,
        onCurrencyFilterClick,
        contactFormUsdAmount
      }
    } = this.props

    const renderTitle = () => {
      // if the node has an alias set we will show that with the pubkey in parens
      // if not, just show the pubkey (would look ugly with rando parens)
      if (node.alias && node.alias.length) {
        return `${node.alias} (${node.pub_key})`
      }

      return node.pub_key
    }

    const formSubmitted = () => {
      // dont submit to LND if they havent set channel capacity amount
      if (contactCapacity <= 0) {
        return
      }

      // submit the channel to LND
      openChannel({
        pubkey: node.pub_key,
        host: node.addresses[0].addr,
        local_amt: contactCapacity
      })

      // close the ChannelForm component
      closeChannelForm()

      // close the AddChannel component
      closeContactsForm()
    }

    return (

Add Funds to Network

            Adding a connection will help you send and receive money on the Lightning Network. You
            aren't spening any money, rather moving the money you plan to use onto the network.

{renderTitle()}

            <input
              type="number"
              min="0"
              size=""
              placeholder="0.00000000"
              value={contactCapacity || ''}
              onChange={event => updateContactCapacity(event.target.value)}
              id="amount"
            />

 setContactsCurrencyFilters(!showCurrencyFilters)}
              >
                {currencyName}

                  <FaAngleDown />

                {currentCurrencyFilters.map(filter => (

 onCurrencyFilterClick(filter.key)}>
                    {filter.name}

                ))}

{`≈ ${contactFormUsdAmount || 0} USD`}

          <div
            className={`${styles.button} ${contactCapacity > 0 && styles.active}`}
            onClick={formSubmitted}
          >
            Submit

    )
  }
}

SubmitChannelForm.propTypes = {
  closeChannelForm: PropTypes.func.isRequired,
  closeContactsForm: PropTypes.func.isRequired,

  node: PropTypes.object.isRequired,
  contactCapacity: PropTypes.PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
  updateContactCapacity: PropTypes.func.isRequired,
  openChannel: PropTypes.func.isRequired,

  toggleCurrencyProps: PropTypes.object.isRequired
}

export default SubmitChannelForm
<commit_msg>fix(channel-form): improve copy<commit_after>import React from 'react'
import PropTypes from 'prop-types'

import FaAngleDown from 'react-icons/lib/fa/angle-down'

import styles from './SubmitChannelForm.scss'

class SubmitChannelForm extends React.Component {
  render() {
    const {
      closeChannelForm,
      closeContactsForm,

      node,
      contactCapacity,
      updateContactCapacity,
      openChannel,

      toggleCurrencyProps: {
        setContactsCurrencyFilters,
        showCurrencyFilters,
        currencyName,
        currentCurrencyFilters,
        onCurrencyFilterClick,
        contactFormUsdAmount
      }
    } = this.props

    const renderTitle = () => {
      // if the node has an alias set we will show that with the pubkey in parens
      // if not, just show the pubkey (would look ugly with rando parens)
      if (node.alias && node.alias.length) {
        return `${node.alias} (${node.pub_key})`
      }

      return node.pub_key
    }

    const formSubmitted = () => {
      // dont submit to LND if they havent set channel capacity amount
      if (contactCapacity <= 0) {
        return
      }

      // submit the channel to LND
      openChannel({
        pubkey: node.pub_key,
        host: node.addresses[0].addr,
        local_amt: contactCapacity
      })

      // close the ChannelForm component
      closeChannelForm()

      // close the AddChannel component
      closeContactsForm()
    }

    return (

Add Funds to Network

            Opening a channel will help you send and receive money on the Lightning Network. You
            aren't spening any money, rather moving the money you plan to use onto the network.

{renderTitle()}

            <input
              type="number"
              min="0"
              size=""
              placeholder="0.00000000"
              value={contactCapacity || ''}
              onChange={event => updateContactCapacity(event.target.value)}
              id="amount"
            />

 setContactsCurrencyFilters(!showCurrencyFilters)}
              >
                {currencyName}

                  <FaAngleDown />

                {currentCurrencyFilters.map(filter => (

 onCurrencyFilterClick(filter.key)}>
                    {filter.name}

                ))}

{`≈ ${contactFormUsdAmount || 0} USD`}

          <div
            className={`${styles.button} ${contactCapacity > 0 && styles.active}`}
            onClick={formSubmitted}
          >
            Submit

    )
  }
}

SubmitChannelForm.propTypes = {
  closeChannelForm: PropTypes.func.isRequired,
  closeContactsForm: PropTypes.func.isRequired,

  node: PropTypes.object.isRequired,
  contactCapacity: PropTypes.PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
  updateContactCapacity: PropTypes.func.isRequired,
  openChannel: PropTypes.func.isRequired,

  toggleCurrencyProps: PropTypes.object.isRequired
}

export default SubmitChannelForm
<|endoftext|>


<commit_before>game.PlayerEntity = me.Entity.extend({
	init: function(x, y, settings) /* initialize player */ {
		this._super(me.Entity, 'init', [x, y, {
			image: "player", //selecting image
			width: 64, // width of player
			height: 64, //height of player
			spritewidth: "64", // same as width
			spriteheight: "64", // same as height
			getShape: function() {
				return(new me.Rect(0, 0, 64, 64)).toPolygon();
			} //creating shape based on selection in image
		}]);

		this.body.setVelocity(5, 20);
		//tells movement of player when moved
		//changed position 0 to 20

		this.facing = "right";
		//keeps track of which direction player facing

		this.now = new Date().getTime();
		//sets variable to current date/time
		this.lastHit = this.now;
		//finds the date when your last hit player
		this.lastAttack = new Date();
		//havent used this yet

		me.game.viewport.follow(this.pos, me.game.viewport.AXIS.BOTH);
		//makes screen follow player movement

		this.renderable.addAnimation("idle", [65]);
		//setting an idle image
		this.renderable.addAnimation("walk", [117, 118, 119, 120, 121, 122, 123, 124, 125], 80);
		//creating a walk animation using orcSpear img
		this.renderable.addAnimation("attack", [65, 66, 67, 68, 69, 70, 71, 72, 71], 80);
		//creating an animationg for attacking

		this.renderable.setCurrentAnimation("idle");
		//sets current animation to the idle
	},

	update: function(delta) {
		this.now = new Date().getTime();

		if(me.input.isKeyPressed("right")) {
			this.body.vel.x += this.body.accel.x * me.timer.tick;
			//current postion changes by setVelocity()
			//me.timer.tick keeps movement smooth
			this.flipX(true);
			//flips the animation for right movement
			this.facing = "right";
			//says youre facing right
		}
		else if(me.input.isKeyPressed("left")) {
			this.body.vel.x -= this.body.accel.x * me.timer.tick;
			//current postion changes by setVelocity()
			//me.timer.tick keeps movement smooth
			this.flipX(false);
			//stops animation from flipping to right when moving left
			this.facing = "left";
			//says youre facing left
		}
		else {
			this.body.vel.x = 0;
			//if not pressing, no change in velocity
		}

		if(me.input.isKeyPressed("jump") && !this.body.jumping && !this.body.falling) {
			this.body.jumping = true;
			//sets precreated jumping var to true
			this.body.vel.y -= this.body.accel.y * me.timer.tick;
			//causes jump to actually happen
		}
		//allows for jumping when key is pressed,
		//and if not jumping/falling already

		if(me.input.isKeyPressed("attack")) {
			if(!this.renderable.isCurrentAnimation("attack")) {
				this.renderable.setCurrentAnimation("attack", "idle");
				//sets current animation then switches over
				this.renderable.setAnimationFrame();
				//begins animation from beginning not
				//from left off
			}
			//uses animation if not already in use
		}
		//shows action on attacking
		else if(this.body.vel.x !== 0 && !this.renderable.isCurrentAnimation("attack")){
			if(!this.renderable.isCurrentAnimation("walk")) {
				this.renderable.setCurrentAnimation("walk");
				//makes walk animation occur when moving
				//does so if not already walk animation
			}
		}
		//adds if statement for movement
		else if(!this.renderable.isCurrentAnimation("attack")) {
			this.renderable.setCurrentAnimation("idle");
			//makes sure to switch back to idle animation
		}

		me.collision.check(this, true, this.collideHandler.bind(this), true);
		//handles player collisions
		this.body.update(delta);
		//lets game know to update screen

		this._super(me.Entity, "update", [delta]);
		//updates in real time

		return true;
	},

	collideHandler : function(response) {
		if(response.b.type === 'EnemyBaseEntity') {
			var ydif = this.pos.y - response.b.pos.y;
			//represnets difference between players y position and bases
			var xdif = this.pos.x - response.b.pos.x;
			//represnets difference between players x position and bases

			if(ydif < -40 && xdif < 70 && xdif > -35) /* only checking if necaessary */ {
				this.body.falling = false;
				//stops player from fallng into base
				this.body.vel.y = - 1;
				//pushes player up from top
			}
			//need to check ydif first
			else if(xdif > -35 /* xdif relation to found number */ &&
			this.facing === 'right'  /* need to know which way facing */ &&
			(xdif < 0)) {
				this.body.vel.x = 0;
				//stop player from moving
				this.pos.x = this.pos.x - 1;
				//slightly move player backwards
			}
			else if(xdif < 70 /* xdif relation to found number */ &&
			this.facing === 'left' /* need to know which way facing */ &&
			(xdif > 0)) {
				this.body.vel.x = 0;
				//stop player movement
				this.pos.x = this.pos.x + 1;
				//move player away slightly
			}
		}
		//sees if player is colliding w/ enemy base
		//if so...

		if(this.renderable.isCurrentAnimation("attack") && this.now - this.lastHit >= 1000) {
			this.lastHit = this.now;
			response.b.loseHealth();
		}
	}
	//collideHandler function creates collsision for player w/ objects
});
//create player entity for use in game

game.PlayerBaseEntity = me.Entity.extend({
	init: function(x, y, settings) {
		this._super(me.Entity, 'init', [x, y, {
			image: "tower", //img for entity
			width: 100, //width of base
			height: 100, //height of base
			spritewidth: "100", //similar to width
			spriteheight: "100", //similar to height
			getShape: function() {
				return (new me.Rect(0, 0, 100, 70)).toPolygon();
			}
			//getShape function for use
		}]);
		//build constructor by calling super

		this.broken = false; //tower not destroyed
		this.health = 10; //health of the tower
		this.alwaysUpdate = true; //update if not on screen
		this.body.onCollision = this.onCollision.bind(this); //able to collide w/ tower
		this.type = "PlayerBase";

		this.renderable.addAnimation("idle", [0]);
		//add animation for unbroken tower
		this.renderable.addAnimation("broken", [1]);
		//add animation for broken tower
		this.renderable.setCurrentAnimation("idle");
		//sets the current animation to idle
	},
	//init function for initialize

	update: function(delta) {
		if(this.health <= 0) {
			this.broken = true; //breaks the tower
			this.renderable.setCurrentAnimation("broken");
			//sets the current animation to broken
		}
		//if health <= 0 then tower broken
		this.body.update(delta); //update for this

		this._super(me.Entity, "update", [delta]); //have to call super
		return true;
	},
	//update function to update

	onCollision: function() {
		//empty onCollision function for later
	},

	loseHealth: function(damage) {
		this.health = this.health - damage;
	}
});
//base entity similar to player

game.EnemyBaseEntity = me.Entity.extend({
	init: function(x, y, settings) {
		this._super(me.Entity, 'init', [x, y, {
			image: "tower", //img for entity
			width: 100, //width of base
			height: 100, //height of base
			spritewidth: "100", //similar to width
			spriteheight: "100", //similar to height
			getShape: function() {
				return (new me.Rect(0, 0, 100, 70)).toPolygon();
			}
			//getShape function for use
		}]);
		//build constructor by calling super

		this.broken = false; //tower not destroyed
		this.health = 10; //health of the tower
		this.alwaysUpdate = true; //update if not on screen
		this.body.onCollision = this.onCollision.bind(this); //able to collide w/ tower

		this.type = "EnemyBaseEntity"; //later for other collisions

		this.renderable.addAnimation("idle", [0]);
		//add animation for unbroken tower
		this.renderable.addAnimation("broken", [1]);
		//add animation for broken tower
		this.renderable.setCurrentAnimation("idle");
		//sets the current animation to idle
	},
	//init function for initialize

	update: function(delta) {
		if(this.health <= 0) {
			this.broken = true; //breaks the tower
			this.renderable.setCurrentAnimation("broken");
			//sets the current animation to broken
		}
		//if health <= 0 then tower broken
		this.body.update(delta); //update for this

		this._super(me.Entity, "update", [delta]); //have to call super
		return true;
	},
	//update function to update

	onCollision: function() {
		//empty onCollision function for later
	},

	loseHealth: function() {
		this.health--;
	}
});
//base entity similar to player

game.EnemyCreep = me.Entity.extend({
	init : function(x, y, settings) {
		this._super(me.Entity, 'init', [x, y, {
			image: "creep1", //gives enemy image to creep1
			width: 32, //sets width to 32
			height: 64, //sets height to 64
			spritewidth: "32", //same as width
			spriteheight: "64", //same as height
			getShape: function() {
				return (new me.Rect(0, 0, 32, 64)).toPolygon();
			}
			//getShape function creates rectangle for enemy
		}]);

		this.health = 2;
		//sets health to 2
		this.alwaysUpdate = true;
		//makes always update

		this.attacking = false;
		this.lastAttacking = new Date().getTime();
		this.lastHit = new Date().getTime();
		this.now = new Date().getTime();

		this.body.setVelocity(3, 20);
		//sets the movement velocity of EnemyCreep

		this.type = "EnemyCreep";
		//gives entity a type

		this.renderable.addAnimation("walk", [3, 4, 5], 80);
		//creates a walk animation
		this.renderable.setCurrentAnimation("walk");
		//sets the current animation to walk
	},

	update : function(delta) {
		this.now = new Date().getTime();

		this.body.vel.x -= this.body.accel.x * me.timer.tick;
		//causes creep to move

		me.collision.check(this, true, this.collideHandler.bind(this), true);

		this.body.update(delta);
		//update makes this happen in real time

		this._super(me.Entity, "update", [delta]);
		//updates the entity
		return true;
		//required
	},

	collideHandler: function(response) {
		if(response.b.type === 'PlayerBase') {
			this.attacking = true;
			this.lastAttacking = this.now;
			this.body.vel.x = 0;
			this.pos.x = this.pos.x + 1;
			if(this.now - this.lastHit >= 1000) {
				this.lastHit = this.now;
				response.b.loseHealth(1);
			}
		}
	},

	loseHealth: function() {

	}

});
//EnemyCreep entity to create enemy

game.GameManager = Object.extend({
	init : function(x, y, settings) {
		this.now = new Date().getTime();
		//makes now the current date/time
		this.lastCreep = new Date().getTime();
		//makes lastCreep equal to the current date/time

		this.alwaysUpdate = true;
		//makes it always update
	},
	//initialization function for gamemanager

	update: function() {
		this.now = new Date().getTime();
		//gets now var

		if(Math.round(this.now/1000) % 10 === 0 && (this.now - this.lastCreep >= 1000)) {
			this.lastCreep = this.now;
			//resets time
			var creepe = me.pool.pull("EnemyCreep", 1000, 0, {});
			//pulls enemy creep class from pool
			me.game.world.addChild(creepe, 5);
			//inserts creep into actual game
		}
		//does something if 10 sec since last

		return true;
		//always for update functions
	},
});
//handles things like timers, not entities<commit_msg>Creeps Hit Bases w/ Comments<commit_after>game.PlayerEntity = me.Entity.extend({
	init: function(x, y, settings) /* initialize player */ {
		this._super(me.Entity, 'init', [x, y, {
			image: "player", //selecting image
			width: 64, // width of player
			height: 64, //height of player
			spritewidth: "64", // same as width
			spriteheight: "64", // same as height
			getShape: function() {
				return(new me.Rect(0, 0, 64, 64)).toPolygon();
			} //creating shape based on selection in image
		}]);

		this.body.setVelocity(5, 20);
		//tells movement of player when moved
		//changed position 0 to 20

		this.facing = "right";
		//keeps track of which direction player facing

		this.now = new Date().getTime();
		//sets variable to current date/time
		this.lastHit = this.now;
		//finds the date when your last hit player
		this.lastAttack = new Date();
		//havent used this yet

		me.game.viewport.follow(this.pos, me.game.viewport.AXIS.BOTH);
		//makes screen follow player movement

		this.renderable.addAnimation("idle", [65]);
		//setting an idle image
		this.renderable.addAnimation("walk", [117, 118, 119, 120, 121, 122, 123, 124, 125], 80);
		//creating a walk animation using orcSpear img
		this.renderable.addAnimation("attack", [65, 66, 67, 68, 69, 70, 71, 72, 71], 80);
		//creating an animationg for attacking

		this.renderable.setCurrentAnimation("idle");
		//sets current animation to the idle
	},

	update: function(delta) {
		this.now = new Date().getTime();

		if(me.input.isKeyPressed("right")) {
			this.body.vel.x += this.body.accel.x * me.timer.tick;
			//current postion changes by setVelocity()
			//me.timer.tick keeps movement smooth
			this.flipX(true);
			//flips the animation for right movement
			this.facing = "right";
			//says youre facing right
		}
		else if(me.input.isKeyPressed("left")) {
			this.body.vel.x -= this.body.accel.x * me.timer.tick;
			//current postion changes by setVelocity()
			//me.timer.tick keeps movement smooth
			this.flipX(false);
			//stops animation from flipping to right when moving left
			this.facing = "left";
			//says youre facing left
		}
		else {
			this.body.vel.x = 0;
			//if not pressing, no change in velocity
		}

		if(me.input.isKeyPressed("jump") && !this.body.jumping && !this.body.falling) {
			this.body.jumping = true;
			//sets precreated jumping var to true
			this.body.vel.y -= this.body.accel.y * me.timer.tick;
			//causes jump to actually happen
		}
		//allows for jumping when key is pressed,
		//and if not jumping/falling already

		if(me.input.isKeyPressed("attack")) {
			if(!this.renderable.isCurrentAnimation("attack")) {
				this.renderable.setCurrentAnimation("attack", "idle");
				//sets current animation then switches over
				this.renderable.setAnimationFrame();
				//begins animation from beginning not
				//from left off
			}
			//uses animation if not already in use
		}
		//shows action on attacking
		else if(this.body.vel.x !== 0 && !this.renderable.isCurrentAnimation("attack")){
			if(!this.renderable.isCurrentAnimation("walk")) {
				this.renderable.setCurrentAnimation("walk");
				//makes walk animation occur when moving
				//does so if not already walk animation
			}
		}
		//adds if statement for movement
		else if(!this.renderable.isCurrentAnimation("attack")) {
			this.renderable.setCurrentAnimation("idle");
			//makes sure to switch back to idle animation
		}

		me.collision.check(this, true, this.collideHandler.bind(this), true);
		//handles player collisions
		this.body.update(delta);
		//lets game know to update screen

		this._super(me.Entity, "update", [delta]);
		//updates in real time

		return true;
	},

	collideHandler : function(response) {
		if(response.b.type === 'EnemyBaseEntity') {
			var ydif = this.pos.y - response.b.pos.y;
			//represnets difference between players y position and bases
			var xdif = this.pos.x - response.b.pos.x;
			//represnets difference between players x position and bases

			if(ydif < -40 && xdif < 70 && xdif > -35) /* only checking if necaessary */ {
				this.body.falling = false;
				//stops player from fallng into base
				this.body.vel.y = - 1;
				//pushes player up from top
			}
			//need to check ydif first
			else if(xdif > -35 /* xdif relation to found number */ &&
			this.facing === 'right'  /* need to know which way facing */ &&
			(xdif < 0)) {
				this.body.vel.x = 0;
				//stop player from moving
				this.pos.x = this.pos.x - 1;
				//slightly move player backwards
			}
			else if(xdif < 70 /* xdif relation to found number */ &&
			this.facing === 'left' /* need to know which way facing */ &&
			(xdif > 0)) {
				this.body.vel.x = 0;
				//stop player movement
				this.pos.x = this.pos.x + 1;
				//move player away slightly
			}
		}
		//sees if player is colliding w/ enemy base
		//if so...

		if(this.renderable.isCurrentAnimation("attack") && this.now - this.lastHit >= 1000) {
			this.lastHit = this.now;
			response.b.loseHealth();
		}
	}
	//collideHandler function creates collsision for player w/ objects
});
//create player entity for use in game

game.PlayerBaseEntity = me.Entity.extend({
	init: function(x, y, settings) {
		this._super(me.Entity, 'init', [x, y, {
			image: "tower", //img for entity
			width: 100, //width of base
			height: 100, //height of base
			spritewidth: "100", //similar to width
			spriteheight: "100", //similar to height
			getShape: function() {
				return (new me.Rect(0, 0, 100, 70)).toPolygon();
			}
			//getShape function for use
		}]);
		//build constructor by calling super

		this.broken = false; //tower not destroyed
		this.health = 10; //health of the tower
		this.alwaysUpdate = true; //update if not on screen
		this.body.onCollision = this.onCollision.bind(this); //able to collide w/ tower
		this.type = "PlayerBase"; //sets type to Player Base

		this.renderable.addAnimation("idle", [0]);
		//add animation for unbroken tower
		this.renderable.addAnimation("broken", [1]);
		//add animation for broken tower
		this.renderable.setCurrentAnimation("idle");
		//sets the current animation to idle
	},
	//init function for initialize

	update: function(delta) {
		if(this.health <= 0) {
			this.broken = true; //breaks the tower
			this.renderable.setCurrentAnimation("broken");
			//sets the current animation to broken
		}
		//if health <= 0 then tower broken
		this.body.update(delta); //update for this

		this._super(me.Entity, "update", [delta]); //have to call super
		return true;
	},
	//update function to update

	onCollision: function() {
		//empty onCollision function for later
	},

	loseHealth: function(damage) {
		this.health = this.health - damage;
	}
});
//base entity similar to player

game.EnemyBaseEntity = me.Entity.extend({
	init: function(x, y, settings) {
		this._super(me.Entity, 'init', [x, y, {
			image: "tower", //img for entity
			width: 100, //width of base
			height: 100, //height of base
			spritewidth: "100", //similar to width
			spriteheight: "100", //similar to height
			getShape: function() {
				return (new me.Rect(0, 0, 100, 70)).toPolygon();
			}
			//getShape function for use
		}]);
		//build constructor by calling super

		this.broken = false; //tower not destroyed
		this.health = 10; //health of the tower
		this.alwaysUpdate = true; //update if not on screen
		this.body.onCollision = this.onCollision.bind(this); //able to collide w/ tower

		this.type = "EnemyBaseEntity"; //later for other collisions

		this.renderable.addAnimation("idle", [0]);
		//add animation for unbroken tower
		this.renderable.addAnimation("broken", [1]);
		//add animation for broken tower
		this.renderable.setCurrentAnimation("idle");
		//sets the current animation to idle
	},
	//init function for initialize

	update: function(delta) {
		if(this.health <= 0) {
			this.broken = true; //breaks the tower
			this.renderable.setCurrentAnimation("broken");
			//sets the current animation to broken
		}
		//if health <= 0 then tower broken
		this.body.update(delta); //update for this

		this._super(me.Entity, "update", [delta]); //have to call super
		return true;
	},
	//update function to update

	onCollision: function() {
		//empty onCollision function for later
	},

	loseHealth: function() {
		this.health--;
	}
});
//base entity similar to player

game.EnemyCreep = me.Entity.extend({
	init : function(x, y, settings) {
		this._super(me.Entity, 'init', [x, y, {
			image: "creep1", //gives enemy image to creep1
			width: 32, //sets width to 32
			height: 64, //sets height to 64
			spritewidth: "32", //same as width
			spriteheight: "64", //same as height
			getShape: function() {
				return (new me.Rect(0, 0, 32, 64)).toPolygon();
			}
			//getShape function creates rectangle for enemy
		}]);

		this.health = 2;
		//sets health to 2
		this.alwaysUpdate = true;
		//makes always update

		this.attacking = false;
		//sets variable attacking to false

		this.lastAttacking = new Date().getTime();
		this.lastHit = new Date().getTime();
		this.now = new Date().getTime();
		//all for spacing out time in update function

		this.body.setVelocity(3, 20);
		//sets the movement velocity of EnemyCreep

		this.type = "EnemyCreep";
		//gives entity a type

		this.renderable.addAnimation("walk", [3, 4, 5], 80);
		//creates a walk animation
		this.renderable.setCurrentAnimation("walk");
		//sets the current animation to walk
	},

	update : function(delta) {
		this.now = new Date().getTime();
		//sets now to a current time

		this.body.vel.x -= this.body.accel.x * me.timer.tick;
		//causes creep to move

		me.collision.check(this, true, this.collideHandler.bind(this), true);
		//allows for creep collisions

		this.body.update(delta);
		//update makes this happen in real time

		this._super(me.Entity, "update", [delta]);
		//updates the entity
		return true;
		//required
	},

	collideHandler: function(response) {
		if(response.b.type === 'PlayerBase') {
			this.attacking = true;
			this.lastAttacking = this.now;
			this.body.vel.x = 0;
			//stops movement
			this.pos.x = this.pos.x + 1;
			//keeps moving creep to right to maintain its position
			if(this.now - this.lastHit >= 1000) {
				this.lastHit = this.now;
				//reset?
				response.b.loseHealth(1);
				//calls loseHealth function with one damage
			}
			//times out the hits
		}
		//if the creep hits player base
	},

	loseHealth: function() {

	}

});
//EnemyCreep entity to create enemy

game.GameManager = Object.extend({
	init : function(x, y, settings) {
		this.now = new Date().getTime();
		//makes now the current date/time
		this.lastCreep = new Date().getTime();
		//makes lastCreep equal to the current date/time

		this.alwaysUpdate = true;
		//makes it always update
	},
	//initialization function for gamemanager

	update: function() {
		this.now = new Date().getTime();
		//gets now var

		if(Math.round(this.now/1000) % 10 === 0 && (this.now - this.lastCreep >= 1000)) {
			this.lastCreep = this.now;
			//resets time
			var creepe = me.pool.pull("EnemyCreep", 1000, 0, {});
			//pulls enemy creep class from pool
			me.game.world.addChild(creepe, 5);
			//inserts creep into actual game
		}
		//does something if 10 sec since last

		return true;
		//always for update functions
	},
});
//handles things like timers, not entities<|endoftext|>