<commit_before>var resolve = require('./resolve')
var LazyWatcher = require('./lib/lazy-watcher')
var isSame = require('./lib/is-same')
var addCollectionMethods = require('./lib/add-collection-methods')
var onceIdle = require('./once-idle')

module.exports = Map

function Map (obs, lambda, opts) {
  // opts: comparer, maxTime, onRemove

  var comparer = opts && opts.comparer || null
  var releases = []
  var binder = LazyWatcher(update, listen, unlisten)

  if (opts && opts.nextTick) binder.nextTick = true
  if (opts && opts.idle) binder.idle = true

  var itemInvalidators = new global.Map()
  var lastValues = new global.Map()
  var rawSet = new global.Set()

  var items = []

  var raw = []
  var values = []
  var watches = []

  binder.value = values

  // incremental update
  var queue = []
  var maxTime = null
  if (opts && opts.maxTime) {
    maxTime = opts.maxTime
  }

  var result = function MutantMap (listener) {
    if (!listener) {
      return binder.getValue()
    }
    return binder.addListener(listener)
  }

  addCollectionMethods(result, raw, binder.checkUpdated)

  return result

  // scoped

  function listen () {
    if (typeof obs === 'function') {
      releases.push(obs(binder.onUpdate))
    }
    rebindAll()

    Array.from(itemInvalidators.values()).forEach(function (invalidators) {
      invalidators.forEach(function (invalidator) {
        invalidator.release = invalidator.observable(invalidate.bind(null, invalidator))
      })
    })

    if (opts && opts.onListen) {
      var release = opts.onListen()
      if (typeof release === 'function') {
        releases.push(release)
      }
    }
  }

  function unlisten () {
    while (releases.length) {
      releases.pop()()
    }
    rebindAll()

    Array.from(itemInvalidators.values()).forEach(function (invalidators) {
      invalidators.forEach(invokeRelease)
    })

    if (opts && opts.onUnlisten) {
      opts.onUnlisten()
    }
  }

  function update () {
    var changed = false

    if (items.length !== getLength(obs)) {
      changed = true
    }

    var startedAt = Date.now()

    for (var i = 0, len = getLength(obs); i < len; i++) {
      var item = get(obs, i)
      var currentItem = items[i]
      items[i] = item

      if (!isSame(item, currentItem, comparer) || (!binder.live && checkInvalidated(item))) {
        if (maxTime && Date.now() - startedAt > maxTime) {
          queueUpdateItem(i)
        } else {
          updateItem(i)
        }
        changed = true
      }
    }

    if (changed) {
      // clean up cache
      var oldLength = raw.length
      var newLength = getLength(obs)
      Array.from(lastValues.keys()).filter(notIncluded, obs).forEach(removeItem)
      items.length = newLength
      values.length = newLength
      raw.length = newLength
      for (var index = newLength; index < oldLength; index++) {
        rebind(index)
      }
      Array.from(rawSet.values()).filter(notIncluded, raw).forEach(removeMapped)
    }

    return changed
  }

  function checkInvalidated (item) {
    if (itemInvalidators.has(item)) {
      return itemInvalidators.get(item).some(function (invalidator) {
        lastValues.delete(invalidator.item)
        return !isSame(invalidator.currentValue, resolve(invalidator.observable), comparer)
      })
    }
  }

  function queueUpdateItem (i) {
    if (!queue.length) {
      doSoon(flushQueue)
    }
    if (!~queue.indexOf(i)) {
      queue.push(i)
    }
  }

  function flushQueue () {
    var startedAt = Date.now()
    while (queue.length && (!maxTime || Date.now() - startedAt < maxTime)) {
      updateItem(queue.shift())
    }
    binder.broadcast()
    if (queue.length) {
      doSoon(flushQueue)
    }
  }

  function invalidateOn (item, obs) {
    if (!itemInvalidators.has(item)) {
      itemInvalidators.set(item, [])
    }

    var invalidators = itemInvalidators.get(item)
    var invalidator = {
      currentValue: resolve(obs),
      observable: obs,
      item: item,
      release: null
    }

    invalidators.push(invalidator)

    if (binder.live) {
      invalidator.release = invalidator.observable(invalidate.bind(null, invalidator))
    }
  }

  function addInvalidateCallback (item) {
    return invalidateOn.bind(null, item)
  }

  function removeItem (item) {
    lastValues.delete(item)
    if (itemInvalidators.has(item)) {
      itemInvalidators.get(item).forEach(invokeRelease)
      itemInvalidators.delete(item)
    }
  }

  function removeMapped (mappedItem) {
    rawSet.delete(mappedItem)
    if (opts && opts.onRemove) {
      opts.onRemove(mappedItem)
    }
  }

  function invalidate (entry) {
    var changed = []
    var length = getLength(obs)
    lastValues.delete(entry.item)
    for (var i = 0; i < length; i++) {
      if (get(obs, i) === entry.item) {
        changed.push(i)
      }
    }
    if (changed.length) {
      var rawValue = raw[changed[0]]
      changed.forEach(function (index) {
        raw[index] = null
      })
      if (!raw.includes(rawValue)) {
        removeMapped(rawValue)
      }
      changed.forEach(updateItem)
      binder.broadcast()
    }
  }

  function updateItem (i) {
    if (i < getLength(obs)) {
      var item = get(obs, i)
      if (!lastValues.has(item) || !isSame(item, item, comparer)) {
        if (itemInvalidators.has(item)) {
          itemInvalidators.get(item).forEach(invokeRelease)
          itemInvalidators.delete(item)
        }
        var newValue = lambda(item, addInvalidateCallback(item))
        if (newValue !== raw[i]) {
          raw[i] = newValue
        }
        rawSet.add(newValue)
        lastValues.set(item, raw[i])
      } else {
        raw[i] = lastValues.get(item)
      }
      rebind(i)
      values[i] = resolve(raw[i])
    }
  }

  function rebind (index) {
    if (watches[index]) {
      watches[index]()
      watches[index] = null
    }

    if (binder.live) {
      if (typeof raw[index] === 'function') {
        watches[index] = updateValue(raw[index], index)
      }
    }
  }

  function rebindAll () {
    for (var i = 0; i < raw.length; i++) {
      rebind(i)
    }
  }

  function updateValue (obs, index) {
    return obs(function (value) {
      if (!isSame(values[index], value, comparer)) {
        values[index] = value
        binder.broadcast()
      }
    })
  }

  function doSoon (fn) {
    if (opts.idle) {
      onceIdle(fn)
    } else if (opts.delayTime) {
      setTimeout(fn, opts.delayTime)
    } else {
      setImmediate(fn)
    }
  }
}

function get (target, index) {
  if (typeof target === 'function' && !target.get) {
    target = target()
  }

  if (Array.isArray(target)) {
    return target[index]
  } else if (target && target.get) {
    return target.get(index)
  }
}

function getLength (target) {
  if (typeof target === 'function' && !target.getLength) {
    target = target()
  }

  if (Array.isArray(target)) {
    return target.length
  } else if (target && target.get) {
    return target.getLength()
  }

  return 0
}

function notIncluded (value) {
  if (this.includes) {
    return !this.includes(value)
  } else if (this.indexOf) {
    return !~this.indexOf(value)
  } else if (typeof this === 'function') {
    var array = this()
    if (array && array.includes) {
      return !array.includes(value)
    }
  }
  return true
}

function invokeRelease (item) {
  if (item.release) {
    item.release()
    item.release = null
  }
}
<commit_msg>map: throw early error when lambda not provided<commit_after>var resolve = require('./resolve')
var LazyWatcher = require('./lib/lazy-watcher')
var isSame = require('./lib/is-same')
var addCollectionMethods = require('./lib/add-collection-methods')
var onceIdle = require('./once-idle')

module.exports = Map

function Map (obs, lambda, opts) {
  // opts: comparer, maxTime, onRemove

  if (typeof lambda !== 'function') throw new Error('mutant/map lambda must be a function')

  var comparer = opts && opts.comparer || null
  var releases = []
  var binder = LazyWatcher(update, listen, unlisten)

  if (opts && opts.nextTick) binder.nextTick = true
  if (opts && opts.idle) binder.idle = true

  var itemInvalidators = new global.Map()
  var lastValues = new global.Map()
  var rawSet = new global.Set()

  var items = []

  var raw = []
  var values = []
  var watches = []

  binder.value = values

  // incremental update
  var queue = []
  var maxTime = null
  if (opts && opts.maxTime) {
    maxTime = opts.maxTime
  }

  var result = function MutantMap (listener) {
    if (!listener) {
      return binder.getValue()
    }
    return binder.addListener(listener)
  }

  addCollectionMethods(result, raw, binder.checkUpdated)

  return result

  // scoped

  function listen () {
    if (typeof obs === 'function') {
      releases.push(obs(binder.onUpdate))
    }
    rebindAll()

    Array.from(itemInvalidators.values()).forEach(function (invalidators) {
      invalidators.forEach(function (invalidator) {
        invalidator.release = invalidator.observable(invalidate.bind(null, invalidator))
      })
    })

    if (opts && opts.onListen) {
      var release = opts.onListen()
      if (typeof release === 'function') {
        releases.push(release)
      }
    }
  }

  function unlisten () {
    while (releases.length) {
      releases.pop()()
    }
    rebindAll()

    Array.from(itemInvalidators.values()).forEach(function (invalidators) {
      invalidators.forEach(invokeRelease)
    })

    if (opts && opts.onUnlisten) {
      opts.onUnlisten()
    }
  }

  function update () {
    var changed = false

    if (items.length !== getLength(obs)) {
      changed = true
    }

    var startedAt = Date.now()

    for (var i = 0, len = getLength(obs); i < len; i++) {
      var item = get(obs, i)
      var currentItem = items[i]
      items[i] = item

      if (!isSame(item, currentItem, comparer) || (!binder.live && checkInvalidated(item))) {
        if (maxTime && Date.now() - startedAt > maxTime) {
          queueUpdateItem(i)
        } else {
          updateItem(i)
        }
        changed = true
      }
    }

    if (changed) {
      // clean up cache
      var oldLength = raw.length
      var newLength = getLength(obs)
      Array.from(lastValues.keys()).filter(notIncluded, obs).forEach(removeItem)
      items.length = newLength
      values.length = newLength
      raw.length = newLength
      for (var index = newLength; index < oldLength; index++) {
        rebind(index)
      }
      Array.from(rawSet.values()).filter(notIncluded, raw).forEach(removeMapped)
    }

    return changed
  }

  function checkInvalidated (item) {
    if (itemInvalidators.has(item)) {
      return itemInvalidators.get(item).some(function (invalidator) {
        lastValues.delete(invalidator.item)
        return !isSame(invalidator.currentValue, resolve(invalidator.observable), comparer)
      })
    }
  }

  function queueUpdateItem (i) {
    if (!queue.length) {
      doSoon(flushQueue)
    }
    if (!~queue.indexOf(i)) {
      queue.push(i)
    }
  }

  function flushQueue () {
    var startedAt = Date.now()
    while (queue.length && (!maxTime || Date.now() - startedAt < maxTime)) {
      updateItem(queue.shift())
    }
    binder.broadcast()
    if (queue.length) {
      doSoon(flushQueue)
    }
  }

  function invalidateOn (item, obs) {
    if (!itemInvalidators.has(item)) {
      itemInvalidators.set(item, [])
    }

    var invalidators = itemInvalidators.get(item)
    var invalidator = {
      currentValue: resolve(obs),
      observable: obs,
      item: item,
      release: null
    }

    invalidators.push(invalidator)

    if (binder.live) {
      invalidator.release = invalidator.observable(invalidate.bind(null, invalidator))
    }
  }

  function addInvalidateCallback (item) {
    return invalidateOn.bind(null, item)
  }

  function removeItem (item) {
    lastValues.delete(item)
    if (itemInvalidators.has(item)) {
      itemInvalidators.get(item).forEach(invokeRelease)
      itemInvalidators.delete(item)
    }
  }

  function removeMapped (mappedItem) {
    rawSet.delete(mappedItem)
    if (opts && opts.onRemove) {
      opts.onRemove(mappedItem)
    }
  }

  function invalidate (entry) {
    var changed = []
    var length = getLength(obs)
    lastValues.delete(entry.item)
    for (var i = 0; i < length; i++) {
      if (get(obs, i) === entry.item) {
        changed.push(i)
      }
    }
    if (changed.length) {
      var rawValue = raw[changed[0]]
      changed.forEach(function (index) {
        raw[index] = null
      })
      if (!raw.includes(rawValue)) {
        removeMapped(rawValue)
      }
      changed.forEach(updateItem)
      binder.broadcast()
    }
  }

  function updateItem (i) {
    if (i < getLength(obs)) {
      var item = get(obs, i)
      if (!lastValues.has(item) || !isSame(item, item, comparer)) {
        if (itemInvalidators.has(item)) {
          itemInvalidators.get(item).forEach(invokeRelease)
          itemInvalidators.delete(item)
        }
        var newValue = lambda(item, addInvalidateCallback(item))
        if (newValue !== raw[i]) {
          raw[i] = newValue
        }
        rawSet.add(newValue)
        lastValues.set(item, raw[i])
      } else {
        raw[i] = lastValues.get(item)
      }
      rebind(i)
      values[i] = resolve(raw[i])
    }
  }

  function rebind (index) {
    if (watches[index]) {
      watches[index]()
      watches[index] = null
    }

    if (binder.live) {
      if (typeof raw[index] === 'function') {
        watches[index] = updateValue(raw[index], index)
      }
    }
  }

  function rebindAll () {
    for (var i = 0; i < raw.length; i++) {
      rebind(i)
    }
  }

  function updateValue (obs, index) {
    return obs(function (value) {
      if (!isSame(values[index], value, comparer)) {
        values[index] = value
        binder.broadcast()
      }
    })
  }

  function doSoon (fn) {
    if (opts.idle) {
      onceIdle(fn)
    } else if (opts.delayTime) {
      setTimeout(fn, opts.delayTime)
    } else {
      setImmediate(fn)
    }
  }
}

function get (target, index) {
  if (typeof target === 'function' && !target.get) {
    target = target()
  }

  if (Array.isArray(target)) {
    return target[index]
  } else if (target && target.get) {
    return target.get(index)
  }
}

function getLength (target) {
  if (typeof target === 'function' && !target.getLength) {
    target = target()
  }

  if (Array.isArray(target)) {
    return target.length
  } else if (target && target.get) {
    return target.getLength()
  }

  return 0
}

function notIncluded (value) {
  if (this.includes) {
    return !this.includes(value)
  } else if (this.indexOf) {
    return !~this.indexOf(value)
  } else if (typeof this === 'function') {
    var array = this()
    if (array && array.includes) {
      return !array.includes(value)
    }
  }
  return true
}

function invokeRelease (item) {
  if (item.release) {
    item.release()
    item.release = null
  }
}
<|endoftext|>


<commit_before>import {Pos} from "../model"

// ;; #kind=interface #path=Mappable
// There are various things that positions can be mapped through.
// We'll denote those as 'mappable'. This is not an actual class in
// the codebase, only an agreed-on interface.

// :: (pos: Pos, bias: ?number) → MapResult
// #path=Mappable.map
// Map a position through this object. When given, the `bias`
// determines in which direction to move when a chunk of content is
// inserted at or around the mapped position.

export class MovedRange {
  constructor(start, size, dest = null) {
    this.start = start
    this.size = size
    this.dest = dest
  }

  get end() {
    return new Pos(this.start.path, this.start.offset + this.size)
  }

  toString() {
    return "[moved " + this.start + "+" + this.size + " to " + this.dest + "]"
  }
}

class Side {
  constructor(from, to, ref) {
    this.from = from
    this.to = to
    this.ref = ref
  }
}

export class ReplacedRange {
  constructor(from, to, newFrom, newTo, ref = from, newRef = newFrom) {
    this.before = new Side(from, to, ref)
    this.after = new Side(newFrom, newTo, newRef)
  }

  toString() {
    return "[replaced " + this.before.from + "-" + this.before.to + " with " + this.after.from + "-" + this.after.to + "]"
  }
}

const empty = []

function offsetFrom(base, pos) {
  if (pos.path.length > base.path.length) {
    let path = [pos.path[base.path.length] - base.offset]
    for (let i = base.path.length + 1; i < pos.path.length; i++)
      path.push(pos.path[i])
    return new Pos(path, pos.offset)
  } else {
    return new Pos([], pos.offset - base.offset)
  }
}

function mapThrough(map, pos, bias = 1, back) {
  for (let i = 0; i < map.replaced.length; i++) {
    let range = map.replaced[i], side = back ? range.after : range.before
    let left, right
    if ((left = pos.cmp(side.from)) >= 0 &&
        (right = pos.cmp(side.to)) <= 0) {
      let other = back ? range.before : range.after
      return new MapResult(bias < 0 ? other.from : other.to,
                           !!(left && right),
                           {rangeID: i, offset: offsetFrom(side.ref, pos)})
    }
  }

  for (let i = 0; i < map.moved.length; i++) {
    let range = map.moved[i]
    let start = back ? range.dest : range.start
    if (pos.cmp(start) >= 0 &&
        Pos.cmp(pos.path, pos.offset, start.path, start.offset + range.size) <= 0) {
      let dest = back ? range.start : range.dest
      let depth = start.depth
      if (pos.depth > depth) {
        let offset = dest.offset + (pos.path[depth] - start.offset)
        return new MapResult(new Pos(dest.path.concat(offset).concat(pos.path.slice(depth + 1)), pos.offset))
      } else {
        return new MapResult(new Pos(dest.path, dest.offset + (pos.offset - start.offset)))
      }
    }
  }

  return new MapResult(pos)
}

// ;; A position map, holding information about the way positions in
// the pre-step version of a document correspond to positions in the
// post-step version. This class implements `Mappable`.
export class PosMap {
  constructor(moved, replaced) {
    this.moved = moved || empty
    this.replaced = replaced || empty
  }

  recover(offset) {
    return this.replaced[offset.rangeID].after.ref.extend(offset.offset)
  }

  // :: (Pos, ?number) → MapResult
  // Map the given position through this map. The `bias` parameter can
  // be used to control what happens when the transform inserted
  // content at (or around) this position—if `bias` is negative, the a
  // position before the inserted content will be returned, if it is
  // positive, a position after the insertion is returned.
  map(pos, bias) {
    return mapThrough(this, pos, bias, false)
  }

  // :: () → PosMap
  // Create an inverted version of this map. The result can be used to
  // map positions in the post-step document to the pre-step document.
  invert() { return new InvertedPosMap(this) }

  toString() { return this.moved.concat(this.replaced).join(" ") }
}

// ;; The return value of mapping a position.
export class MapResult {
  constructor(pos, deleted = false, recover = null) {
    // :: Pos The mapped version of the position.
    this.pos = pos
    // :: bool Tells you whether the position was deleted, that is,
    // whether the step removed its surroundings from the document.
    this.deleted = deleted
    this.recover = recover
  }
}

class InvertedPosMap {
  constructor(map) { this.inner = map }

  recover(offset) {
    return this.inner.replaced[offset.rangeID].before.ref.extend(offset.offset)
  }

  map(pos, bias) {
    return mapThrough(this.inner, pos, bias, true)
  }

  invert() { return this.inner }

  toString() { return "-" + this.inner }
}

export const nullMap = new PosMap

// ;; A remapping represents a pipeline of zero or more mappings. It
// is a specialized data structured used to manage mapping through a
// series of steps, typically including inverted and non-inverted
// versions of the same step. (This comes up when ‘rebasing’ steps for
// collaboration or history management.) This class implements
// `Mappable`.
export class Remapping {
  // :: (?[PosMap], ?[PosMap])
  constructor(head = [], tail = [], mirror = Object.create(null)) {
    // :: [PosMap]
    // The maps in the head of the mapping are applied to input
    // positions first, back-to-front. So the map at the end of this
    // array (if any) is the very first one applied.
    this.head = head
    // The maps in the tail are applied last, front-to-back.
    this.tail = tail
    this.mirror = mirror
  }

  // :: (PosMap, ?number) → number
  // Add a map to the mapping's front. If this map is the mirror image
  // (produced by an inverted step) of another map in this mapping,
  // that map's id (as returned by this method or
  // [`addToBack`](#Remapping.addToBack)) should be passed as a second
  // parameter to register the correspondence.
  addToFront(map, corr) {
    this.head.push(map)
    let id = -this.head.length
    if (corr != null) this.mirror[id] = corr
    return id
  }

  // :: (PosMap, ?number) → number
  // Add a map to the mapping's back. If the map is the mirror image
  // of another mapping in this object, the id of that map should be
  // passed to register the correspondence.
  addToBack(map, corr) {
    this.tail.push(map)
    let id = this.tail.length - 1
    if (corr != null) this.mirror[corr] = id
    return id
  }

  get(id) {
    return id < 0 ? this.head[-id - 1] : this.tail[id]
  }

  // :: (Pos, ?number) → MapResult
  // Map a position through this remapping, optionally passing a bias
  // direction.
  map(pos, bias) {
    let deleted = false

    for (let i = -this.head.length; i < this.tail.length; i++) {
      let map = this.get(i)
      let result = map.map(pos, bias)
      if (result.recover) {
        let corr = this.mirror[i]
        if (corr != null) {
          i = corr
          pos = this.get(corr).recover(result.recover)
          continue
        }
      }
      if (result.deleted) deleted = true
      pos = result.pos
    }

    return new MapResult(pos, deleted)
  }
}
<commit_msg>Put #kind=interface after #path<commit_after>import {Pos} from "../model"

// ;; #path=Mappable #kind=interface
// There are various things that positions can be mapped through.
// We'll denote those as 'mappable'. This is not an actual class in
// the codebase, only an agreed-on interface.

// :: (pos: Pos, bias: ?number) → MapResult
// #path=Mappable.map
// Map a position through this object. When given, the `bias`
// determines in which direction to move when a chunk of content is
// inserted at or around the mapped position.

export class MovedRange {
  constructor(start, size, dest = null) {
    this.start = start
    this.size = size
    this.dest = dest
  }

  get end() {
    return new Pos(this.start.path, this.start.offset + this.size)
  }

  toString() {
    return "[moved " + this.start + "+" + this.size + " to " + this.dest + "]"
  }
}

class Side {
  constructor(from, to, ref) {
    this.from = from
    this.to = to
    this.ref = ref
  }
}

export class ReplacedRange {
  constructor(from, to, newFrom, newTo, ref = from, newRef = newFrom) {
    this.before = new Side(from, to, ref)
    this.after = new Side(newFrom, newTo, newRef)
  }

  toString() {
    return "[replaced " + this.before.from + "-" + this.before.to + " with " + this.after.from + "-" + this.after.to + "]"
  }
}

const empty = []

function offsetFrom(base, pos) {
  if (pos.path.length > base.path.length) {
    let path = [pos.path[base.path.length] - base.offset]
    for (let i = base.path.length + 1; i < pos.path.length; i++)
      path.push(pos.path[i])
    return new Pos(path, pos.offset)
  } else {
    return new Pos([], pos.offset - base.offset)
  }
}

function mapThrough(map, pos, bias = 1, back) {
  for (let i = 0; i < map.replaced.length; i++) {
    let range = map.replaced[i], side = back ? range.after : range.before
    let left, right
    if ((left = pos.cmp(side.from)) >= 0 &&
        (right = pos.cmp(side.to)) <= 0) {
      let other = back ? range.before : range.after
      return new MapResult(bias < 0 ? other.from : other.to,
                           !!(left && right),
                           {rangeID: i, offset: offsetFrom(side.ref, pos)})
    }
  }

  for (let i = 0; i < map.moved.length; i++) {
    let range = map.moved[i]
    let start = back ? range.dest : range.start
    if (pos.cmp(start) >= 0 &&
        Pos.cmp(pos.path, pos.offset, start.path, start.offset + range.size) <= 0) {
      let dest = back ? range.start : range.dest
      let depth = start.depth
      if (pos.depth > depth) {
        let offset = dest.offset + (pos.path[depth] - start.offset)
        return new MapResult(new Pos(dest.path.concat(offset).concat(pos.path.slice(depth + 1)), pos.offset))
      } else {
        return new MapResult(new Pos(dest.path, dest.offset + (pos.offset - start.offset)))
      }
    }
  }

  return new MapResult(pos)
}

// ;; A position map, holding information about the way positions in
// the pre-step version of a document correspond to positions in the
// post-step version. This class implements `Mappable`.
export class PosMap {
  constructor(moved, replaced) {
    this.moved = moved || empty
    this.replaced = replaced || empty
  }

  recover(offset) {
    return this.replaced[offset.rangeID].after.ref.extend(offset.offset)
  }

  // :: (Pos, ?number) → MapResult
  // Map the given position through this map. The `bias` parameter can
  // be used to control what happens when the transform inserted
  // content at (or around) this position—if `bias` is negative, the a
  // position before the inserted content will be returned, if it is
  // positive, a position after the insertion is returned.
  map(pos, bias) {
    return mapThrough(this, pos, bias, false)
  }

  // :: () → PosMap
  // Create an inverted version of this map. The result can be used to
  // map positions in the post-step document to the pre-step document.
  invert() { return new InvertedPosMap(this) }

  toString() { return this.moved.concat(this.replaced).join(" ") }
}

// ;; The return value of mapping a position.
export class MapResult {
  constructor(pos, deleted = false, recover = null) {
    // :: Pos The mapped version of the position.
    this.pos = pos
    // :: bool Tells you whether the position was deleted, that is,
    // whether the step removed its surroundings from the document.
    this.deleted = deleted
    this.recover = recover
  }
}

class InvertedPosMap {
  constructor(map) { this.inner = map }

  recover(offset) {
    return this.inner.replaced[offset.rangeID].before.ref.extend(offset.offset)
  }

  map(pos, bias) {
    return mapThrough(this.inner, pos, bias, true)
  }

  invert() { return this.inner }

  toString() { return "-" + this.inner }
}

export const nullMap = new PosMap

// ;; A remapping represents a pipeline of zero or more mappings. It
// is a specialized data structured used to manage mapping through a
// series of steps, typically including inverted and non-inverted
// versions of the same step. (This comes up when ‘rebasing’ steps for
// collaboration or history management.) This class implements
// `Mappable`.
export class Remapping {
  // :: (?[PosMap], ?[PosMap])
  constructor(head = [], tail = [], mirror = Object.create(null)) {
    // :: [PosMap]
    // The maps in the head of the mapping are applied to input
    // positions first, back-to-front. So the map at the end of this
    // array (if any) is the very first one applied.
    this.head = head
    // The maps in the tail are applied last, front-to-back.
    this.tail = tail
    this.mirror = mirror
  }

  // :: (PosMap, ?number) → number
  // Add a map to the mapping's front. If this map is the mirror image
  // (produced by an inverted step) of another map in this mapping,
  // that map's id (as returned by this method or
  // [`addToBack`](#Remapping.addToBack)) should be passed as a second
  // parameter to register the correspondence.
  addToFront(map, corr) {
    this.head.push(map)
    let id = -this.head.length
    if (corr != null) this.mirror[id] = corr
    return id
  }

  // :: (PosMap, ?number) → number
  // Add a map to the mapping's back. If the map is the mirror image
  // of another mapping in this object, the id of that map should be
  // passed to register the correspondence.
  addToBack(map, corr) {
    this.tail.push(map)
    let id = this.tail.length - 1
    if (corr != null) this.mirror[corr] = id
    return id
  }

  get(id) {
    return id < 0 ? this.head[-id - 1] : this.tail[id]
  }

  // :: (Pos, ?number) → MapResult
  // Map a position through this remapping, optionally passing a bias
  // direction.
  map(pos, bias) {
    let deleted = false

    for (let i = -this.head.length; i < this.tail.length; i++) {
      let map = this.get(i)
      let result = map.map(pos, bias)
      if (result.recover) {
        let corr = this.mirror[i]
        if (corr != null) {
          i = corr
          pos = this.get(corr).recover(result.recover)
          continue
        }
      }
      if (result.deleted) deleted = true
      pos = result.pos
    }

    return new MapResult(pos, deleted)
  }
}
<|endoftext|>


<commit_before>function initializeMaps(markers) {
	var myLatLng = {lat: -25.2744, lng: 133.7751};

  var map = new google.maps.Map(document.getElementById('map_canvas'), {
    zoom: 4,
    center: myLatLng
  });

	var bounds = new google.maps.LatLngBounds();

	markers.forEach(function(point) {
	 	generateIcon(point[0], function(src) {
		  var pos = new google.maps.LatLng(point[1], point[2]);

	  	bounds.extend(pos);

		  new google.maps.Marker({
		  	position: pos,
			  map: map,
			  icon: src
		  });
		});
	});

	// map.fitBounds(bounds);
}

var generateIconCache = {};

function generateIcon(number, callback) {
  if (generateIconCache[number] !== undefined) {
    callback(generateIconCache[number]);
  }

  var fontSize = 16,
    imageWidth = imageHeight = 35;

  if (number >= 1000) {
    fontSize = 10;
    imageWidth = imageHeight = 55;
  } else if (number < 1000 && number > 100) {
    fontSize = 14;
    imageWidth = imageHeight = 45;
  }

  var svg = d3.select(document.createElement('div')).append('svg')
    .attr('viewBox', '0 0 54.4 54.4')
    .append('g')

  var circles = svg.append('circle')
    .attr('cx', '27.2')
    .attr('cy', '27.2')
    .attr('r', '21.2')
    .style('fill', '#2063C6');

  var path = svg.append('path')
    .attr('d', 'M27.2,0C12.2,0,0,12.2,0,27.2s12.2,27.2,27.2,27.2s27.2-12.2,27.2-27.2S42.2,0,27.2,0z M6,27.2 C6,15.5,15.5,6,27.2,6s21.2,9.5,21.2,21.2c0,11.7-9.5,21.2-21.2,21.2S6,38.9,6,27.2z')
    .attr('fill', '#FFFFFF');

  var text = svg.append('text')
    .attr('dx', 27)
    .attr('dy', 32)
    .attr('text-anchor', 'middle')
    .attr('style', 'font-size:' + fontSize + 'px; fill: #FFFFFF; font-family: Arial, Verdana; font-weight: bold')
    .text(number);

  var svgNode = svg.node().parentNode.cloneNode(true),
    image = new Image();

  d3.select(svgNode).select('clippath').remove();

  var xmlSource = (new XMLSerializer()).serializeToString(svgNode);

  image.onload = (function(imageWidth, imageHeight) {
    var canvas = document.createElement('canvas'),
      context = canvas.getContext('2d'),
      dataURL;

    d3.select(canvas)
      .attr('width', imageWidth)
      .attr('height', imageHeight);

    context.drawImage(image, 0, 0, imageWidth, imageHeight);

    dataURL = canvas.toDataURL();
    generateIconCache[number] = dataURL;

    callback(dataURL);
  }).bind(this, imageWidth, imageHeight);

  image.src = 'data:image/svg+xml;base64,' + btoa(encodeURIComponent(xmlSource).replace(/%([0-9A-F]{2})/g, function(match, p1) {
    return String.fromCharCode('0x' + p1);
  }));
}
<commit_msg>Style maps to be greyscaled<commit_after>function initializeMaps(markers) {
	var myLatLng = {lat: -25.2744, lng: 133.7751};

	var mapStyle = [{"featureType":"landscape","stylers":[{"saturation":-100},{"lightness":65},{"visibility":"on"}]},{"featureType":"poi","stylers":[{"saturation":-100},{"lightness":51},{"visibility":"simplified"}]},{"featureType":"road.highway","stylers":[{"saturation":-100},{"visibility":"simplified"}]},{"featureType":"road.arterial","stylers":[{"saturation":-100},{"lightness":30},{"visibility":"on"}]},{"featureType":"road.local","stylers":[{"saturation":-100},{"lightness":40},{"visibility":"on"}]},{"featureType":"transit","stylers":[{"saturation":-100},{"visibility":"simplified"}]},{"featureType":"administrative.province","stylers":[{"visibility":"off"}]},{"featureType":"water","elementType":"labels","stylers":[{"visibility":"on"},{"lightness":-25},{"saturation":-100}]},{"featureType":"water","elementType":"geometry","stylers":[{"hue":"#ffff00"},{"lightness":-25},{"saturation":-97}]}];
  var map = new google.maps.Map(document.getElementById('map_canvas'), {
    zoom: 4,
    center: myLatLng,
		styles: mapStyle
  });

	var bounds = new google.maps.LatLngBounds();

	markers.forEach(function(point) {
	 	generateIcon(point[0], function(src) {
		  var pos = new google.maps.LatLng(point[1], point[2]);

	  	bounds.extend(pos);

		  new google.maps.Marker({
		  	position: pos,
			  map: map,
			  icon: src
		  });
		});
	});

	// map.fitBounds(bounds);
}

var generateIconCache = {};

function generateIcon(number, callback) {
  if (generateIconCache[number] !== undefined) {
    callback(generateIconCache[number]);
  }

  var fontSize = 16,
    imageWidth = imageHeight = 35;

  if (number >= 1000) {
    fontSize = 10;
    imageWidth = imageHeight = 55;
  } else if (number < 1000 && number > 100) {
    fontSize = 14;
    imageWidth = imageHeight = 45;
  }

  var svg = d3.select(document.createElement('div')).append('svg')
    .attr('viewBox', '0 0 54.4 54.4')
    .append('g')

  var circles = svg.append('circle')
    .attr('cx', '27.2')
    .attr('cy', '27.2')
    .attr('r', '21.2')
    .style('fill', '#2063C6');

  var path = svg.append('path')
    .attr('d', 'M27.2,0C12.2,0,0,12.2,0,27.2s12.2,27.2,27.2,27.2s27.2-12.2,27.2-27.2S42.2,0,27.2,0z M6,27.2 C6,15.5,15.5,6,27.2,6s21.2,9.5,21.2,21.2c0,11.7-9.5,21.2-21.2,21.2S6,38.9,6,27.2z')
    .attr('fill', '#FFFFFF');

  var text = svg.append('text')
    .attr('dx', 27)
    .attr('dy', 32)
    .attr('text-anchor', 'middle')
    .attr('style', 'font-size:' + fontSize + 'px; fill: #FFFFFF; font-family: Arial, Verdana; font-weight: bold')
    .text(number);

  var svgNode = svg.node().parentNode.cloneNode(true),
    image = new Image();

  d3.select(svgNode).select('clippath').remove();

  var xmlSource = (new XMLSerializer()).serializeToString(svgNode);

  image.onload = (function(imageWidth, imageHeight) {
    var canvas = document.createElement('canvas'),
      context = canvas.getContext('2d'),
      dataURL;

    d3.select(canvas)
      .attr('width', imageWidth)
      .attr('height', imageHeight);

    context.drawImage(image, 0, 0, imageWidth, imageHeight);

    dataURL = canvas.toDataURL();
    generateIconCache[number] = dataURL;

    callback(dataURL);
  }).bind(this, imageWidth, imageHeight);

  image.src = 'data:image/svg+xml;base64,' + btoa(encodeURIComponent(xmlSource).replace(/%([0-9A-F]{2})/g, function(match, p1) {
    return String.fromCharCode('0x' + p1);
  }));
}
<|endoftext|>


<commit_before>!!function(window) {
window.mic = mic

function mic(cb, config) {
    errors = {
        COMPATIBILITY: new Error('[mic] Compatibility Error: requires getUserMedia and AudioContext'),
        PERMISSION: new Error('[mic] Permission Error: requires user audio permissions'),
    }

    config = config || { workerPath: 'recorder/recorderWorker.js' }

    // Compatibility check
    if (!(navigator.getUserMedia ||
          (navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia))) {
        return cb(errors.COMPATIBILITY)
    }
    if (!(window.AudioContext ||
          (window.AudioContext = window.webkitAudioContext))) {
        return cb(errors.COMPATIBILITY)
    }

    // Audio setup
    var context = new AudioContext()

    // Permission
    navigator.getUserMedia({audio: true}, onUserMediaSuccess, onUserMediaFailure)

    function onUserMediaSuccess(stream) { cb(new Mic(stream)) }
    function onUserMediaFailure() { cb(errors.Permission) }

    // Mic
    function Mic(stream) {
        this.input = context.createMediaStreamSource(stream)
        this.recorder = new Recorder(this.input, config)
        this.source
        this.tracking = -1
        this.recording = false
    }

    // Recording functions
    Mic.prototype.record = function record() {
        if (this.recording) this.recorder.stop()
        this.recorder.clear()
        this.recorder.record()
        this.buffer

        this.recording = true
        this.tracking = -1
    }

    Mic.prototype.stop = function stop() {
        this.recorder.stop()
        this.recording = false

        var that = this
        this.recorder.getBuffer(function(buffers) {
            var buffer = that.buffer = context.createBuffer(2, buffers[0].length, context.sampleRate)
            buffer.getChannelData(0).set(buffers[0])
            buffer.getChannelData(1).set(buffers[1])

            that.tracking = 0
        })
    }

    // Playback functions
    Mic.prototype.play = function play(when) {
        if (this.tracking < 0) throw new Error('No buffer to play')

        var source = this.source = context.createBufferSource()
        source.buffer = this.buffer
        source.connect(context.destination)

        this.tracking = arguments.length ? when : this.tracking
        if (this.tracking > source.buffer.duration) this.tracking = 0

        var that = this
        source.onended = function(e) {
            that.tracking = 0
        }

        source.start(0, this.tracking)
        source.startTime = context.currentTime
    }

    Mic.prototype.pause = function pause() {
        var source = this.source
        if (!source) return

        var that = this
        source.onended = function(e) {
            that.tracking += context.currentTime - source.startTime
        }

        source.stop()
    }

    // Download functions
    Mic.prototype.exportWAV = function exportWAV(cb, type) {
        this.recorder.exportWAV(cb, type)
    }

    Mic.prototype.download = function download(filename) {
        this.recorder.exportWAV(function(blob) {
            Recorder.forceDownload(blob, filename)
        })
    }
}
}(window)
<commit_msg>(example) inline<commit_after>!!function(window) {
window.mic = mic

/* Example:
 * var microphone
 *
 * mic(function(m) {
 *  microphone = m
 *  m.record()
 * // Wait a few seconds
 *  m.stop()
 *  m.play()
 *  m.exportWAV(function(blob) {
 *      $.post('/db', blob)
 *  })
 */

function mic(cb, config) {
    errors = {
        COMPATIBILITY: new Error('[mic] Compatibility Error: requires getUserMedia and AudioContext'),
        PERMISSION: new Error('[mic] Permission Error: requires user audio permissions'),
    }

    config = config || { workerPath: 'recorder/recorderWorker.js' }

    // Compatibility check
    if (!(navigator.getUserMedia ||
          (navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia))) {
        return cb(errors.COMPATIBILITY)
    }
    if (!(window.AudioContext ||
          (window.AudioContext = window.webkitAudioContext))) {
        return cb(errors.COMPATIBILITY)
    }

    // Audio setup
    var context = new AudioContext()

    // Permission
    navigator.getUserMedia({audio: true}, onUserMediaSuccess, onUserMediaFailure)

    function onUserMediaSuccess(stream) { cb(new Mic(stream)) }
    function onUserMediaFailure() { cb(errors.Permission) }

    // Mic
    function Mic(stream) {
        this.input = context.createMediaStreamSource(stream)
        this.recorder = new Recorder(this.input, config)
        this.source
        this.tracking = -1
        this.recording = false
    }

    // Recording functions
    Mic.prototype.record = function record() {
        if (this.recording) this.recorder.stop()
        this.recorder.clear()
        this.recorder.record()
        this.buffer

        this.recording = true
        this.tracking = -1
    }

    Mic.prototype.stop = function stop() {
        this.recorder.stop()
        this.recording = false

        var that = this
        this.recorder.getBuffer(function(buffers) {
            var buffer = that.buffer = context.createBuffer(2, buffers[0].length, context.sampleRate)
            buffer.getChannelData(0).set(buffers[0])
            buffer.getChannelData(1).set(buffers[1])

            that.tracking = 0
        })
    }

    // Playback functions
    Mic.prototype.play = function play(when) {
        if (this.tracking < 0) throw new Error('No buffer to play')

        var source = this.source = context.createBufferSource()
        source.buffer = this.buffer
        source.connect(context.destination)

        this.tracking = arguments.length ? when : this.tracking
        if (this.tracking > source.buffer.duration) this.tracking = 0

        var that = this
        source.onended = function(e) {
            that.tracking = 0
        }

        source.start(0, this.tracking)
        source.startTime = context.currentTime
    }

    Mic.prototype.pause = function pause() {
        var source = this.source
        if (!source) return

        var that = this
        source.onended = function(e) {
            that.tracking += context.currentTime - source.startTime
        }

        source.stop()
    }

    // Download functions
    Mic.prototype.exportWAV = function exportWAV(cb, type) {
        this.recorder.exportWAV(cb, type)
    }

    Mic.prototype.download = function download(filename) {
        this.recorder.exportWAV(function(blob) {
            Recorder.forceDownload(blob, filename)
        })
    }
}
}(window)
<|endoftext|>


<commit_before>var canvas = document.getElementById("renderCanvas");
var engine = new BABYLON.Engine(canvas, true);
var scene;
var camera;
var light;

var initScene = function ()
{
	var scene = new BABYLON.Scene(engine);
	scene.clearColor = new BABYLON.Color3(0, 0, 0.2);
	return scene;
};

var initCamera = function ()
{
	var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(-20, 10, -30), scene);
	camera.setTarget(BABYLON.Vector3.Zero());
	camera.attachControl(canvas, false);
	return camera;
};

var initLight = function ()
{
	var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
	light.intensity = .5;
	var d1 = new BABYLON.DirectionalLight("dir", new BABYLON.Vector3(1, -1, -2), scene);
	d1.position = new BABYLON.Vector3(-300,300,600);
	return light;
};

var createLane = function (id, position)
{
	var lane = BABYLON.Mesh.CreateBox("lane"+id, 1, scene);
	lane.scaling.y = 0.2;
	lane.scaling.x = 1;
	lane.scaling.z = 20;

	lane.position.x = position;
	lane.position.y = 8;
	lane.rotation.x = Math.PI / -3;
};

Tree = function() {
    // Call the super class BABYLON.Mesh
    BABYLON.Mesh.call(this, "tree", scene);
    // ...
};

var createScene = function ()
{

scene = initScene();
camera  = initCamera();
light = initLight();

/***********************************************************/
// Fog
//    var box = new BABYLON.Mesh(name, scene);
//    var vertexData = BABYLON.VertexData.CreateBox(10);
//    vertexData.applyToMesh(box, false);
//    box.material = new BABYLON.StandardMaterial("ground", scene);
//    box.material.diffuseColor = BABYLON.Color3.FromInts(193, 181, 151);
//    box.material.specularColor = BABYLON.Color3.Black();
//    box.scaling.y = 0.1;
//
    var materialSphere1 = new BABYLON.StandardMaterial("texture1", scene);
    materialSphere1.wireframe = true;
//    box.material = materialSphere1;
//
//    var positions = box.getVerticesData(BABYLON.VertexBuffer.PositionKind);
//    console.log(positions);
//    var indices = box.getIndices();
//    var numberOfPoints = positions.length/3;
//    var v3 = BABYLON.Vector3;
//    var max = [];
//    var i = 0;
//    positions[i] += 20;
//    positions[i+1] += 1;
//    positions[i+2] += 25;
//
//    box.setVerticesData(BABYLON.VertexBuffer.PositionKind, positions);
//    var normals = [];
//    BABYLON.VertexData.ComputeNormals(positions, indices, normals);
//    box.setVerticesData(BABYLON.VertexBuffer.NormalKind, normals);
//    console.log(positions);

        var pos = [0, 20, 0];

    var ground = BABYLON.Mesh.CreateGround("ground", 100, 100, 100, scene);
    ground.material = materialSphere1;

    var positions = ground.getVerticesData("position");
    var numberPoints = positions.length;

    for (var i = 0; i < numberPoints; i+=3)
    {
        if (positions[i] == pos[0] && positions[i+2] == pos[2] )
        {
			for (var y = 0; y < 20; y++)
			{

				positions[i - y * 3 + 1] = 10 + 10 * Math.cos( Math.PI / pos[1] * y );
				positions[i + y * 3 + 1] = 10 + 10 * Math.cos( Math.PI / pos[1] * y );

//				for(var j = 0; j < 20; j++)
//				{
//					var h = pos[1] - (y+j);
//					if (h > 0)
//					{
//						positions[i - y * 3 + 1 + 101 *3 * (j+1)] = 10 + 10 * Math.cos( Math.PI / 20 * y );
//						positions[i + y * 3 + 1 + 101 *3 * (j+1)] = 10 + 10 * Math.cos( Math.PI / 20 * y );
//					}
//				}
			}
        }
    }
    ground.setVerticesData(BABYLON.VertexBuffer.PositionKind, positions);

// scene.fogMode = BABYLON.Scene.FOGMODE_EXP2;
// scene.fogDensity = 0.003;
// scene.fogColor = new BABYLON.Color3(0.8,0.83,0.8);

// // Ground
// var ground = BABYLON.Mesh.CreateGround("ground", 100, 100, 1, scene);
// ground.material = new BABYLON.StandardMaterial("ground", scene);
// ground.material.diffuseColor = BABYLON.Color3.FromInts(193, 181, 151);
// ground.material.specularColor = BABYLON.Color3.Black();

/***********************************************************/
return scene;
};

var scene = createScene();
engine.runRenderLoop(function () {
	scene.render();
});

// Resize
window.addEventListener("resize", function () {
	engine.resize();
});

/*

for (var i = 0; i < numberPoints; i+=3)
{
    if (positions[i] == pos[0] && positions[i+2] == pos[2] )
    {
		for ( var deg = 0; deg < 180; deg++ )
		{
			for (var dist = 0; dist < 20; dist++)
			{
				var x = dist * Math.cos(deg);
				var y = dist * Math.sin(deg);
				console.log("x:"+x);
				positions[i - x * 101 * 3 + y + 1] = 10 + 10 * Math.cos( Math.PI / pos[1] * dist );
				positions[i + x * 101 * 3 + y + 1] = 10 + 10 * Math.cos( Math.PI / pos[1] * dist );
				positions[i - dist * 3 + 1 + 101 * 3 * x + y] = 10 + 10 * Math.cos( Math.PI / pos[1] * dist );
				positions[i + dist * 3 + 1 + 101 * 3 * x + y] = 10 + 10 * Math.cos( Math.PI / pos[1] * dist );
		//	var box = BABYLON.Mesh.CreateBox("box", 1.0, scene);
		//	box.position.x = x;
		//box.position.z = y;
				console.log("-------");
			}
		}

			//positions[i - y * 3 + 1] = 10 + 10 * Math.cos( Math.PI / pos[1] * y );
			//positions[i + y * 3 + 1] = 10 + 10 * Math.cos( Math.PI / pos[1] * y );

    }
}
*/

<commit_msg>moutain done !<commit_after>var canvas = document.getElementById("renderCanvas");
var engine = new BABYLON.Engine(canvas, true);
var scene;
var camera;
var light;
var ground;

var initScene = function ()
{
	var scene = new BABYLON.Scene(engine);
	scene.clearColor = new BABYLON.Color3(0, 0, 0.2);
	return scene;
};

var initCamera = function ()
{
	var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(-50, 50, -80), scene);
	camera.setTarget(BABYLON.Vector3.Zero());
	camera.attachControl(canvas, false);
	return camera;
};

var initLight = function ()
{
	var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
	light.intensity = .7;
	var d1 = new BABYLON.DirectionalLight("dir", new BABYLON.Vector3(1, -1, -2), scene);
	d1.position = new BABYLON.Vector3(-300,300,600);
	return light;
};

var createMountain = function ( positions, vertexPoint, mapDiv )
{
	for (var i = 0; i < positions.length; i+=3)
	{
	    if ( positions[i] == vertexPoint[0] && positions[i+2] == vertexPoint[2] )
	    {

			for ( var deg = 0; deg < 360; deg+= 0.1 )
			{
				for (var dist = 0; dist < vertexPoint[1]; dist+= 0.1)
				{
					var x = Math.round(dist * Math.cos(Math.PI * deg / 180));
					var z = Math.round(dist * Math.sin(Math.PI * deg / 180));

					var tabIndex = i + x *(mapDiv+1)*3 + z*3 + 1;

					var ymid = vertexPoint[1]/2;
					var ampl = vertexPoint[1]/2;

					var heigh = ymid + ampl * Math.cos( Math.PI / vertexPoint[1] * dist );

					if (positions[tabIndex] < heigh)
						positions[tabIndex] =  heigh;
				}
			}
	    }
	}
	return positions;
};

var createScene = function ()
{

scene = initScene();
camera  = initCamera();
light = initLight();

/***********************************************************/
// Fog
//    var box = new BABYLON.Mesh(name, scene);
//    var vertexData = BABYLON.VertexData.CreateBox(10);
//    vertexData.applyToMesh(box, false);
var colorMaterial = new BABYLON.StandardMaterial("ground", scene);
colorMaterial.diffuseColor = BABYLON.Color3.FromInts(193, 181, 151);
colorMaterial.specularColor = BABYLON.Color3.Black();

var waterColor = new BABYLON.StandardMaterial("ground", scene);
waterColor.diffuseColor = BABYLON.Color3.FromInts(70, 130, 180);
waterColor.specularColor = BABYLON.Color3.Black();

var wireMaterial = new BABYLON.StandardMaterial("texture1", scene);
wireMaterial.wireframe = true;
//    box.scaling.y = 0.1;
//
// // Ground
// var ground = BABYLON.Mesh.CreateGround("ground", 100, 100, 1, scene);
// ground.material = new BABYLON.StandardMaterial("ground", scene);
// ground.material.diffuseColor = BABYLON.Color3.FromInts(193, 181, 151);
// ground.material.specularColor = BABYLON.Color3.Black();

var mapSize = [100, 100, 100];
var mountain1 = [10, 20, -10];
var mountain2 = [20, 20, 0];

ground = BABYLON.Mesh.CreateGround("ground", mapSize[0], mapSize[1], mapSize[2], scene);
// ground.material = wireMaterial;
ground.material = colorMaterial;

var positions = ground.getVerticesData("position");
positions = createMountain(positions, mountain1, mapSize[2]);

positions = createMountain(positions, mountain2, mapSize[2]);
ground.setVerticesData(BABYLON.VertexBuffer.PositionKind, positions);

ground.convertToFlatShadedMesh();

var water = BABYLON.Mesh.CreateGround("water", mapSize[0], mapSize[1], mapSize[2], scene);
water.material = waterColor;

water.position.y = 5;
/***********************************************************/
return scene;
};

var scene = createScene();
engine.runRenderLoop(function () {
	scene.render();
});

// Resize
window.addEventListener("resize", function () {
	engine.resize();
});

/*

for (var i = 0; i < numberPoints; i+=3)
{
    if (positions[i] == pos[0] && positions[i+2] == pos[2] )
    {
		for ( var deg = 0; deg < 180; deg++ )
		{
			for (var dist = 0; dist < 20; dist++)
			{
				var x = dist * Math.cos(deg);
				var y = dist * Math.sin(deg);
				console.log("x:"+x);
				positions[i - x * 101 * 3 + y + 1] = 10 + 10 * Math.cos( Math.PI / pos[1] * dist );
				positions[i + x * 101 * 3 + y + 1] = 10 + 10 * Math.cos( Math.PI / pos[1] * dist );
				positions[i - dist * 3 + 1 + 101 * 3 * x + y] = 10 + 10 * Math.cos( Math.PI / pos[1] * dist );
				positions[i + dist * 3 + 1 + 101 * 3 * x + y] = 10 + 10 * Math.cos( Math.PI / pos[1] * dist );
		//	var box = BABYLON.Mesh.CreateBox("box", 1.0, scene);
		//	box.position.x = x;
		//box.position.z = y;
				console.log("-------");
			}
		}

			//positions[i - y * 3 + 1] = 10 + 10 * Math.cos( Math.PI / pos[1] * y );
			//positions[i + y * 3 + 1] = 10 + 10 * Math.cos( Math.PI / pos[1] * y );

    }
}
*/

<|endoftext|>


<commit_before>M.wrap('github/jillix/table/v0.0.1/table.js', function (require, module, exports) {

function createTemplates (schema) {

    // create headers and rows
    var columns = {
        headers: '
',
        rows: '
'
    };

    for (var i = 0; i < schema.length; ++i) {
        columns.headers += '' + schema[i].label + '	';
        columns.rows += '{' + schema[i].prop + '}	';
    }

    columns.headers += '
';
    columns.rows += '
';

    return columns;
}

function routeHandler (event, keys, separator) {
    var self = this;

    // create route path
    var path = location.pathname;
    for (var i = 0, value; i < keys.length; ++i) {

        value = self.path(keys[i], event.item);

        if (typeof value !== 'undefined') {
            path += (value instanceof Array ? value[0] : value) + (separator || '');
        }
    }
    // route
    self.route(path);
}

function setItem (event) {
    this.item = event.item;
}

function load (state, modelData) {
    var self = this;

    // reset current item
    self.currentItem = null;

    // state can't be emitted before the view is ready
    if (!self.item || !self.head) {
        return;
    }

    if (!state.view) {
        return console.error('[table: ' + 'No info to fetch view.]');
    }

    // reset headers
    if (self.head.dom) {
        self.head.dom.innerHTML = '';
    }

    // reset items
    if (self.item.dom) {
        self.item.dom.innerHTML = '';
    }

    // load view from url
    self.view(state.view, function (err, view) {

        if (err || !view) {
            return console.error('[table: ' + (err ? err.toString() : 'No view found.') + ']');
        }

        // create templates from view config
        var templates = createTemplates(view.config.columns);

        // set header template
        self.head.set(templates.headers, 'thead', self.layout.dom);

        // set items template
        view.set(templates.rows, 'tbody', self.layout.dom);

        view.req({m: 'find', d: view.config.req}, function (err, data) {

            if (err) {
                return console.error('[table: ' + err.toString() + ']');
            }

            // render title
            self.title.render([{title: state.view}]);

            // render head
            self.head.render();
        });
    });
}

function init () {
    var self = this;
    var config = self.mono.config.data;

    // append route handler
    self.routeHandler = routeHandler;

    // append item handler
    self.setItem = setItem;
    self.on('getItem', function (callback) {
        callback(null, self.item);
    });

    // init view
    if (config && config.layout) {

        self.view(config.layout, function (err, layout) {

            if (err) {
                return console.error(err);
            }

            // save view instance
            self.layout = layout;

            if (self.layout) {

                // render layout view
                self.layout.render();

                // load controller
                var count = 0;
                var handler = function (err) {

                    if (err) {
                        return self.emit('ready', err);
                    }

                    if (++count === 3) {

                        //add click to create button
                        var create = config.create;
                        $(create).on('click', function () {
                            self.route(location.pathname + 'new/');
                        });

                        // state handler
                        self.load = load;

                        self.emit('ready');
                    }
                };

                // create title view
                self.view({to: '.tableTitle', in: self.layout.dom, html: '
{title}
'}, function (err, view) {
                    self.title = view;
                    handler(err);
                });

                // create head view
                self.view(function(err, view) {
                    self.head = view;
                    handler(err);
                });

                // create item view
                self.view(function(err, view) {
                    self.item = view;
                    handler(err);
                });
            }
        });
    }
}

module.exports = init;

return module;

});
<commit_msg>updated module to new configs<commit_after>Z.wrap('github/jillix/table/v0.0.1/table.js', function (require, module, exports) {

function createTemplates (schema) {

    // create headers and rows
    var columns = {
        headers: '
',
        rows: '
'
    };

    for (var i = 0; i < schema.length; ++i) {
        columns.headers += '' + schema[i].label + '	';
        columns.rows += '{' + schema[i].prop + '}	';
    }

    columns.headers += '
';
    columns.rows += '
';

    return columns;
}

// emit route on itme dom event
function itemAction (event) {
    var self = this;
    var item = self.model.data[event.index];

    if (self.view.item.config.route && item) {

        var match = self.view.item.config.route.match(/{([^}]+)}/g);
        var url = self.view.item.config.route;

        for (var i = 0, value; i < match.length; ++i) {

            // get value from object
            value = self._path(match[i].replace('{', '').replace('}', ''), item);

            url = url.replace(match[i], value);
        }

        self.route(url);
    }
}

function load (state, viewInfo) {
    var self = this;

    // reset current item
    self.currentItem = null;

    if (!self.view.item && !viewInfo) {
        return console.error('[table: ' + 'No item view.]');
    }

    // reset headers
    if (self.view.head.dom) {
        self.view.head.dom.innerHTML = '';
    }

    // TODO fetch view with view info or render direct on self.view.item
    // TODO handle title
    // self.view.title.render([{title: self.view.item.config.title}]);

    if (viewInfo) {
        // TODO fetch view from server
    } else {
        // mongodb model request
        self.model.req({m: 'find', d: self.view.item.config.req || {}}, function (err, data) {

            // create templates from view config
            var templates = createTemplates(self.view.item.config.columns);

            // set header template
            self.view.head.set(templates.headers, 'thead', self.view.layout.dom);

            self.view.head.render();
            self.view.item.render(data);
        });
    }
}

function init (config, ready) {
    var self = this;

    // append load handlers
    self.load = load;
    self.itemAction = itemAction;

    // render layout
    if (self.view && self.view.layout) {
        self.view.layout.render();
    }

    // a table can have only one model
    if (self.model) {
        for (var model in self.model) {
            self.model = self.model[model]
            break;
        }
    }

    // get an empty view instance for the table headers
    self._load('V', {}, function (err, view) {

        self.view.head = view;

        console.log('table:', self._name);
        ready();
    });
}

module.exports = init;

return module;

});
<|endoftext|>


<commit_before>/*
  Table v0.1
  Adam Schwartz

  Based on:
  SortTable version 2
  Stuart Langridge, http://www.kryogenix.org/code/browser/Table/, 7th April 2007
*/

Table = {
  numberRegExp: /^-?[$]?[\d,.]+%?$/,

  makeSortable: function(table) {
    var c, r, tHeadRow;

    if (table.tHead.rows.length !== 1) return;

    tHeadRow = table.tHead.rows[0].cells;

    for (c = 0; c < tHeadRow.length; c++) {
      if (tHeadRow[c].getAttribute('data-sort') === 'false') continue;

      tHeadRow[c].sortFunction = Table.guessSortFunctionFromColumn(table, c);

      tHeadRow[c].columnIndex = c;
      tHeadRow[c].tBody = table.tBodies[0];

      tHeadRow[c].addEventListener('click', function(e) {
        var col, rows, rowArray;

        if (this.getAttribute('data-sorted') === 'true') {
          Table.reverse(this.tBody);

          if (this.getAttribute('data-sorted-reverse') !== 'true') {
            this.setAttribute('data-sorted-reverse', 'true');
          } else {
            this.setAttribute('data-sorted-reverse', 'false');
          }

          return;
        }

        tHeadRow = this.parentNode;

        Array.prototype.slice.call(tHeadRow.childNodes).forEach(function(cell) {
          if (cell.nodeType == 1) {
            cell.setAttribute('data-sorted', 'false');
            cell.setAttribute('data-sorted-reverse', 'false');
          }
        });

        this.setAttribute('data-sorted', 'true');

        rowArray = [];

        col = this.columnIndex;
        rows = this.tBody.rows;

        for (r = 0; r < rows.length; r++) {
          rowArray[rowArray.length] = [Table.getCellValue(rows[r].cells[col]), rows[r]];
        }

        rowArray.sort(this.sortFunction);

        var fragment = document.createDocumentFragment();

        for (r = 0; r < rowArray.length; r++) {
          fragment.appendChild(rowArray[r][1].cloneNode(true));
        }

        this.tBody.innerHTML = '';
        this.tBody.appendChild(fragment);
      });
    }
  },

  guessSortFunctionFromColumn: function(table, column) {
    var i, text, sortFn;

    sortFn = Table.sortAlpha;

    for (i = 0; i < table.tBodies[0].rows.length; i++) {
      text = Table.getCellValue(table.tBodies[0].rows[i].cells[column]);

      if (text !== '' && text.match(Table.numberRegExp)) {
        return Table.sortNumeric;
      }
    }

    return sortFn;
  },

  getCellValue: function(node) {
    if (!node) return '';

    if (node.getAttribute('data-value') !== null) {
      return node.getAttribute('data-value');
    }

    return node.innerText.replace(/^\s+|\s+$/g, '');
  },

  reverse: function(tBody) {
    var r, fragment;

    fragment = document.createDocumentFragment();

    for (r = tBody.rows.length - 1; r >= 0; r--) {
      fragment.appendChild(tBody.rows[r].cloneNode(true));
    }

    tBody.innerHTML = '';
    tBody.appendChild(fragment);
  },

  sortNumeric: function(a, b) {
    var aa = parseFloat(a[0].replace(/[^0-9.-]/g, '')),
        bb = parseFloat(b[0].replace(/[^0-9.-]/g, ''))
    ;
    if (isNaN(aa)) aa = 0;
    if (isNaN(bb)) bb = 0;
    return aa - bb;
  },

  sortAlpha: function(a, b) {
    var aa = a[0].toLowerCase(),
        bb = b[0].toLowerCase()
    ;
    if (aa === bb) return 0;
    if (aa < bb) return -1;
    return 1;
  }
};<commit_msg>Use textContent if innerText isn't available<commit_after>/*
  Table v0.1
  Adam Schwartz

  Based on:
  SortTable version 2
  Stuart Langridge, http://www.kryogenix.org/code/browser/Table/, 7th April 2007
*/

Table = {
  numberRegExp: /^-?[$]?[\d,.]+%?$/,

  makeSortable: function(table) {
    var c, r, tHeadRow;

    if (table.tHead.rows.length !== 1) return;

    tHeadRow = table.tHead.rows[0].cells;

    for (c = 0; c < tHeadRow.length; c++) {
      if (tHeadRow[c].getAttribute('data-sort') === 'false') continue;

      tHeadRow[c].sortFunction = Table.guessSortFunctionFromColumn(table, c);

      tHeadRow[c].columnIndex = c;
      tHeadRow[c].tBody = table.tBodies[0];

      tHeadRow[c].addEventListener('click', function(e) {
        var col, rows, rowArray;

        if (this.getAttribute('data-sorted') === 'true') {
          Table.reverse(this.tBody);

          if (this.getAttribute('data-sorted-reverse') !== 'true') {
            this.setAttribute('data-sorted-reverse', 'true');
          } else {
            this.setAttribute('data-sorted-reverse', 'false');
          }

          return;
        }

        tHeadRow = this.parentNode;

        Array.prototype.slice.call(tHeadRow.childNodes).forEach(function(cell) {
          if (cell.nodeType == 1) {
            cell.setAttribute('data-sorted', 'false');
            cell.setAttribute('data-sorted-reverse', 'false');
          }
        });

        this.setAttribute('data-sorted', 'true');

        rowArray = [];

        col = this.columnIndex;
        rows = this.tBody.rows;

        for (r = 0; r < rows.length; r++) {
          rowArray[rowArray.length] = [Table.getCellValue(rows[r].cells[col]), rows[r]];
        }

        rowArray.sort(this.sortFunction);

        var fragment = document.createDocumentFragment();

        for (r = 0; r < rowArray.length; r++) {
          fragment.appendChild(rowArray[r][1].cloneNode(true));
        }

        this.tBody.innerHTML = '';
        this.tBody.appendChild(fragment);
      });
    }
  },

  guessSortFunctionFromColumn: function(table, column) {
    var i, text, sortFn;

    sortFn = Table.sortAlpha;

    for (i = 0; i < table.tBodies[0].rows.length; i++) {
      text = Table.getCellValue(table.tBodies[0].rows[i].cells[column]);

      if (text !== '' && text.match(Table.numberRegExp)) {
        return Table.sortNumeric;
      }
    }

    return sortFn;
  },

  getCellValue: function(node) {
    if (!node) return '';

    if (node.getAttribute('data-value') !== null) {
      return node.getAttribute('data-value');
    }

    if (typeof node.innerText != 'undefined') {
      return node.innerText.replace(/^\s+|\s+$/g, '');
    }

    return node.textContent.replace(/^\s+|\s+$/g, '');
  },

  reverse: function(tBody) {
    var r, fragment;

    fragment = document.createDocumentFragment();

    for (r = tBody.rows.length - 1; r >= 0; r--) {
      fragment.appendChild(tBody.rows[r].cloneNode(true));
    }

    tBody.innerHTML = '';
    tBody.appendChild(fragment);
  },

  sortNumeric: function(a, b) {
    var aa = parseFloat(a[0].replace(/[^0-9.-]/g, '')),
        bb = parseFloat(b[0].replace(/[^0-9.-]/g, ''))
    ;
    if (isNaN(aa)) aa = 0;
    if (isNaN(bb)) bb = 0;
    return aa - bb;
  },

  sortAlpha: function(a, b) {
    var aa = a[0].toLowerCase(),
        bb = b[0].toLowerCase()
    ;
    if (aa === bb) return 0;
    if (aa < bb) return -1;
    return 1;
  }
};<|endoftext|>


<commit_before>//const topics = ["hackathons", "facebook", "food"];
//const friends = ["Henry", "Emma"];
//const ignore_friends = ["James"];
let topics = [];
let friends = [];
let ignore_friends = [];

chrome.storage.sync.get(['ignore_friends', 'topics', 'friends'], function(items) {
    if(typeof items.topics !== 'undefined') topics = items.topics;
    if(typeof items.friends !== 'undefined') friends = items.friends;
    if(typeof items.ignore_friends !== 'undefined') ignore_friends = items.ignore_friends;
})

$(document).on('click', '._4qba'/*'._5f0v._4wzs'*/, function(e) {
    const messages = $('[aria-label="Messages"]').eq(0);
    const messageList = messages.children('[id^="js_"]').eq(0);
    // console.log(topics);
    // console.log(friends);
    // console.log(ignore_friends);
    // scrape through your messages for important messages
    const sendData = {
        messages: [],
        use: [],
    }
    for (const i in messageList.children()) {
        const child = messageList.children().eq(i);
        if (child.prop('tagName') === 'DIV' && !child.prop('class')) {
            const sender = child.find('h5');
            const senderName = sender.eq(0).prop("innerText");
            // found a messsage chunk, iterate through to get individual messages
            const childMessages = child.find('.clearfix');
            // const childMessages = child.find('[class="_3oh- _58nk"]');
            for (let m = 0; m < childMessages.length; m++){
                const div = childMessages.eq(m);
                const span = div.find('[class="_3oh- _58nk"]').eq(0);
                const string = span.prop('innerText');
                // span is the element, string contains the actual message string
                // messageStrings.push(string);

                // modify the div
                sendData.messages.push(div);
                if (important(string, senderName)) {
                    span.css('background-color', 'yellow');
                    sendData.use.push(true);
                } else {
                    sendData.use.push(false);
                }
            }
            // child.css('background-color', 'red');
        } else if (child.prop('tagName') === 'H4') {
            console.log("New time");
            child.css('background-color', 'blue');
        } else {
            child.css('background-color', 'orange');
        }
    };

    popup(sendData);

});

function important(text, sender){
    if (!text){
        return false;
    }
    text = text.toLowerCase();
    if (friends.indexOf(sender)> -1){
        return true;
    }
    if (ignore_friends.indexOf(sender) > -1){
        return false;
    }
    for (const topic of topics){
        if (text.includes(topic)){
          return true;
        }
    }
    return false;
}

function popup(data) {
    const messages = data.messages;
    const use = data.use;

    // var bmdiv = document.createElement('div');
    // bmdiv.setAttribute('id', 'myDiv');

    // var str = bmdiv.innerHTML = str;

    $("body").append(`

                                    Hello World

                                <button class="_3quh _30yy _2t_ _5ixy" tabindex="0">

                                        Done

                                </button>

                            hello world

`
    );
    // document.getElementsByClassName('_3ixn')[0].innerHTML += '

Settings
<button class="_3quh _30yy _2t_ _5ixy" tabindex="0">Done</button>

Account

Emma Young

Sounds

<input type="checkbox" value="on">Enabled

Notifications

<input type="checkbox" value="on">Desktop notifications enabled

Blocking

Manage on Facebook

Emoji

';

    // make the popup display
}<commit_msg>Modal closes<commit_after>//const topics = ["hackathons", "facebook", "food"];
//const friends = ["Henry", "Emma"];
//const ignore_friends = ["James"];
let topics = [];
let friends = [];
let ignore_friends = [];

chrome.storage.sync.get(['ignore_friends', 'topics', 'friends'], function(items) {
    if(typeof items.topics !== 'undefined') topics = items.topics;
    if(typeof items.friends !== 'undefined') friends = items.friends;
    if(typeof items.ignore_friends !== 'undefined') ignore_friends = items.ignore_friends;
})

$(document).on('click', '._4qba'/*'._5f0v._4wzs'*/, function(e) {
    const messages = $('[aria-label="Messages"]').eq(0);
    const messageList = messages.children('[id^="js_"]').eq(0);
    // console.log(topics);
    // console.log(friends);
    // console.log(ignore_friends);
    // scrape through your messages for important messages
    const sendData = {
        messages: [],
        use: [],
    }
    for (const i in messageList.children()) {
        const child = messageList.children().eq(i);
        if (child.prop('tagName') === 'DIV' && !child.prop('class')) {
            const sender = child.find('h5');
            const senderName = sender.eq(0).prop("innerText");
            // found a messsage chunk, iterate through to get individual messages
            const childMessages = child.find('.clearfix');
            // const childMessages = child.find('[class="_3oh- _58nk"]');
            for (let m = 0; m < childMessages.length; m++){
                const div = childMessages.eq(m);
                const span = div.find('[class="_3oh- _58nk"]').eq(0);
                const string = span.prop('innerText');
                // span is the element, string contains the actual message string
                // messageStrings.push(string);

                // modify the div
                sendData.messages.push(div);
                if (important(string, senderName)) {
                    span.css('background-color', 'yellow');
                    sendData.use.push(true);
                } else {
                    sendData.use.push(false);
                }
            }
            // child.css('background-color', 'red');
        } else if (child.prop('tagName') === 'H4') {
            console.log("New time");
            child.css('background-color', 'blue');
        } else {
            child.css('background-color', 'orange');
        }
    };

    popup(sendData);

});

function important(text, sender){
    if (!text){
        return false;
    }
    text = text.toLowerCase();
    if (friends.indexOf(sender)> -1){
        return true;
    }
    if (ignore_friends.indexOf(sender) > -1){
        return false;
    }
    for (const topic of topics){
        if (text.includes(topic)){
          return true;
        }
    }
    return false;
}

function popup(data) {
    const messages = data.messages;
    const use = data.use;

    // var bmdiv = document.createElement('div');
    // bmdiv.setAttribute('id', 'myDiv');

    // var str = bmdiv.innerHTML = str;

    $("body").append(`

                                    Hello World

                                <button class="_3quh _30yy _2t_ _5ixy" tabindex="0">

                                        Done

                                </button>

                            hello world

`
    );
    $('body').on('click', '#closeModal', function() {
        $('#wholeModal').remove();
    });
    $('body').on('click', '._3ixn', function() {
        $('#wholeModal').remove();
    });
}<|endoftext|>


<commit_before>module.export = {
	updateURL: "http://www.nfl.com/liveupdate/scorestrip/scorestrip.json"
}<commit_msg>update nfl url export<commit_after>exports.updateURL: "http://www.nfl.com/liveupdate/scorestrip/scorestrip.json";<|endoftext|>


<commit_before>"use strict";

// try to use div instead:
/*
function objNew(x, y, imgPath, imgAlt) {
  var ret = {};
  var tempImg = document.createElement("img");
  tempImg.src = imgPath;
  tempImg.onLoad = function() {
    // set width & height here
  }
  ret.x = x;
  ret.y = y;
  ret.width = tempImg.width;
  ret.height = tempImg.height;
  alert(ret.width + " " + ret.height);
  ret.div = document.createElement("div"); // use div tag instead of img so image is not selectable
  ret.div.style.backgroundImage = "url('" + imgPath + "')";
  ret.div.style.position = "fixed";
  if (ret.width > 0 && ret.height > 0) {
    ret.div.style.width = ret.width + "px"; // get width & height from temporary image object
    ret.div.style.height = ret.height + "px";
  }
  else {
    ret.div.appendChild(document.createTextNode(imgAlt)); // set alternate text if image not loaded
  }
  document.getElementById("draw").appendChild(ret.div);
  return ret;
}
*/

function objNew(imgPath, imgAlt, x, y) {
  var ret = {};
  ret.x = x;
  ret.y = y;
  ret.img = document.createElement("img");
  ret.img.src = imgPath;
  ret.img.alt = imgAlt;
  ret.img.style.position = "fixed";
  getDrawDiv().appendChild(ret.img);
  return ret;
}

function objDraw(obj) {
  if (obj.x + obj.img.width > viewX && obj.x < viewX + getWindowWidth()
      && obj.y + obj.img.height > viewY && obj.y < viewY + getWindowHeight()) {
    obj.img.style.left = (obj.x - viewX) + "px";
    obj.img.style.top = (obj.y - viewY) + "px";
    obj.img.style.display = "";
  }
  else {
    obj.img.style.display = "none";
  }
}

function getDrawDiv() {
  return document.getElementById("draw");
}
<commit_msg>use z-index<commit_after>"use strict";

// try to use div instead:
/*
function objNew(x, y, imgPath, imgAlt) {
  var ret = {};
  var tempImg = document.createElement("img");
  tempImg.src = imgPath;
  tempImg.onLoad = function() {
    // set width & height here
  }
  ret.x = x;
  ret.y = y;
  ret.width = tempImg.width;
  ret.height = tempImg.height;
  alert(ret.width + " " + ret.height);
  ret.div = document.createElement("div"); // use div tag instead of img so image is not selectable
  ret.div.style.backgroundImage = "url('" + imgPath + "')";
  ret.div.style.position = "fixed";
  if (ret.width > 0 && ret.height > 0) {
    ret.div.style.width = ret.width + "px"; // get width & height from temporary image object
    ret.div.style.height = ret.height + "px";
  }
  else {
    ret.div.appendChild(document.createTextNode(imgAlt)); // set alternate text if image not loaded
  }
  document.getElementById("draw").appendChild(ret.div);
  return ret;
}
*/

function objNew(imgPath, imgAlt, x, y) {
  var ret = {};
  ret.x = x;
  ret.y = y;
  ret.img = document.createElement("img");
  ret.img.src = imgPath;
  ret.img.alt = imgAlt;
  ret.img.style.position = "fixed";
  getDrawDiv().appendChild(ret.img);
  return ret;
}

function objDraw(obj) {
  if (obj.x + obj.img.width > viewX && obj.x < viewX + getWindowWidth()
      && obj.y + obj.img.height > viewY && obj.y < viewY + getWindowHeight()) {
    obj.img.style.left = (obj.x - viewX) + "px";
    obj.img.style.top = (obj.y - viewY) + "px";
    obj.img.style.zIndex = Math.floor(obj.y);
    obj.img.style.display = "";
  }
  else {
    obj.img.style.display = "none";
  }
}

function getDrawDiv() {
  return document.getElementById("draw");
}
<|endoftext|>


<commit_before><commit_msg>implemented Three.js and added CSS3DRenderer<commit_after>// Eheeey! Welcome to POP.js

var POP = function(params){
    var that = this;
    that.configs = {};
    that.three = {};
    that.container = (params && params.container) || document.body;

    that.init = function(){
        that.three.sceneGL = new THREE.Scene();
        that.three.sceneCSS = new THREE.Scene();

        // -- Setting up the camera -- //
        that.three.camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1000000 );
        that.three.camera.position.z = 0;

        // -- Defining the WebGL and CSS3D Renderers -- //
        var rendererCSS = new THREE.CSS3DRenderer();
        rendererCSS.setSize(window.innerWidth, window.innerHeight);
        rendererCSS.domElement.id = 'rendererCSS';

        var rendererGL = new THREE.WebGLRenderer({
            alpha: true,
            antialias: true
        });
        rendererGL.setClearColor(0x00ff00, 0.0);
        rendererGL.domElement.id = 'rendererGL';

        rendererGL.setSize(window.innerWidth, window.innerHeight);
        rendererCSS.domElement.appendChild(rendererGL.domElement);

        that.container.appendChild(rendererCSS.domElement);

        that.three.rendererGL = rendererGL;
        that.three.rendererCSS = rendererCSS;

        that.addPopElements();
        that.animate();
    };
    that.addPopElements = function(){
        var that = this,
            popElements = document.querySelectorAll('.pop-element');

        for( var i=0; i < popElements.length; i++ ){
            that.addHtml({
                x: popElements[i].getAttribute('x') || '0',
                y: popElements[i].getAttribute('y') || '0',
                z: popElements[i].getAttribute('z') || '0',
                content: popElements[i]
            });
        }
    };
    that.animate = function(){
        requestAnimationFrame(that.animate);

        that.three.rendererGL.render(that.three.sceneGL, that.three.camera);
        that.three.rendererCSS.render(that.three.sceneCSS, that.three.camera);
    };
    that.init();
};

POP.prototype.addHtml = function(params){
    var that = this,
        htmlObject = new THREE.CSS3DObject(params.content);

	htmlObject.position.z = params.z || 0;
	htmlObject.position.y = params.y || 0;
	htmlObject.position.x = params.x || 0;

	// -- Adding the HTML Content to scene -- //
	that.three.sceneCSS.add(htmlObject);
};
POP.prototype.add3dObject = function(params) {
    // -- This function supports .obj, .js, .collada model formats -- //
    var that = this;
};
<|endoftext|>


<commit_before>/*! Tappy! - a lightweight normalized tap event. Copyright 2013 @scottjehl, Filament Group, Inc. Licensed MIT */
(function( w, $, undefined ){

	var tap = function( $els ){
		return $els.each(function(){

			var $el = $( this ),
				lastE,
				resetTimer,
				lastScroll,
				scrollTolerance = 15,
				href;

			function trigger( e ){
				e.preventDefault();
				$( e.target ).trigger( "tap", [ e ] );
			}

			function start( e ){
				lastScroll = w.document.body.scrollTop;
				if( $el.is( "a" ) ){
					// set href to null hash during tap. this prevents the address bar from dropping down in iOS
					href = $el[ 0 ].href;
					$el[ 0 ].href = "#";
				}
			}

			function end( e ){

				e.preventDefault();

				// this part prevents a double callback from touch and mouse on the same tap
				if( lastE && lastE !== e.type ){
					return false;
				}

				lastE = e.type;
				clearTimeout( resetTimer );
				resetTimer = setTimeout( function(){
					lastE = null;
				}, 1000 );

				// if a scroll happened between touchstart and touchend
				if( e.type === "touchend" && Math.abs( w.document.body.scrollTop - lastScroll ) > scrollTolerance ){
					return false;
				}

				// set href back
				if( href ){
					$el[ 0 ].href = href;
				}
				href = null;

				trigger( e );
			}

			$el
				.bind( "touchstart", start )
				.bind( "touchend", end )
				.bind( "click", end );
		});
	};

	// monkeybind
	var oldBind = $.fn.bind;
	$.fn.bind = function( evt, callback ){
		if( evt === "tap" ){
			tap( this );
		}
		return oldBind.apply( this, [evt, callback] );
	};

}( this, jQuery ));<commit_msg>allow tap to be passed in the same bind as other event names<commit_after>/*! Tappy! - a lightweight normalized tap event. Copyright 2013 @scottjehl, Filament Group, Inc. Licensed MIT */
(function( w, $, undefined ){

	var tap = function( $els ){
		return $els.each(function(){

			var $el = $( this ),
				lastE,
				resetTimer,
				lastScroll,
				scrollTolerance = 15,
				href;

			function trigger( e ){
				e.preventDefault();
				$( e.target ).trigger( "tap", [ e ] );
			}

			function start( e ){
				lastScroll = w.document.body.scrollTop;
				if( $el.is( "a" ) ){
					// set href to null hash during tap. this prevents the address bar from dropping down in iOS
					href = $el[ 0 ].href;
					$el[ 0 ].href = "#";
				}
			}

			function end( e ){

				e.preventDefault();

				// this part prevents a double callback from touch and mouse on the same tap
				if( lastE && lastE !== e.type ){
					return false;
				}

				lastE = e.type;
				clearTimeout( resetTimer );
				resetTimer = setTimeout( function(){
					lastE = null;
				}, 1000 );

				// if a scroll happened between touchstart and touchend
				if( e.type === "touchend" && Math.abs( w.document.body.scrollTop - lastScroll ) > scrollTolerance ){
					return false;
				}

				// set href back
				if( href ){
					$el[ 0 ].href = href;
				}
				href = null;

				trigger( e );
			}

			$el
				.bind( "touchstart", start )
				.bind( "touchend", end )
				.bind( "click", end );
		});
	};

	// monkeybind
	var oldBind = $.fn.bind;
	$.fn.bind = function( evt, callback ){
		if( /(^| )tap( |$)/.test( evt ) ){
			tap( this );
		}
		return oldBind.apply( this, [evt, callback] );
	};

}( this, jQuery ));<|endoftext|>


<commit_before>var youtube = require('youtube-api');
var fs = require('fs');

function playlistInfoRecursive(playlistId, callStackSize, pageToken, currentItems, callback) {
  youtube.playlistItems.list({
    part: 'snippet',
    pageToken: pageToken,
    maxResults: 50,
    playlistId: playlistId,
  }, function(err, data) {
    if (err) return console.log('error: ' + err);

    for (var x in data.items) {
      currentItems.push(data.items[x].snippet);
    }

    if (data.nextPageToken) {
      playlistInfoRecursive(playlistId, callStackSize + 1, data.nextPageToken, currentItems, callback);
    } else {
      callback(currentItems);
    }

  });
}

exports.playlistInfo = function(apiKey, playlistId, done) {

  youtube.authenticate({
    type: 'key',
    key: apiKey,
  });

  playlistInfoRecursive(playlistId, 0, null, [], done);
};

// pullPlayList("playlist id here", "name of mp3 here");
<commit_msg>Update run.js (#1)<commit_after>var youtube = require('youtube-api');
var fs = require('fs');

function playlistInfoRecursive(playlistId, callStackSize, pageToken, currentItems, callback) {
  youtube.playlistItems.list({
    part: 'snippet',
    pageToken: pageToken,
    maxResults: 50,
    playlistId: playlistId,
  }, function(err, data) {
    if (err) callback({error: err}); return;

    for (var x in data.items) {
      currentItems.push(data.items[x].snippet);
    }

    if (data.nextPageToken) {
      playlistInfoRecursive(playlistId, callStackSize + 1, data.nextPageToken, currentItems, callback);
    } else {
      callback(currentItems);
    }

  });
}

exports.playlistInfo = function(apiKey, playlistId, done) {

  youtube.authenticate({
    type: 'key',
    key: apiKey,
  });

  playlistInfoRecursive(playlistId, 0, null, [], done);
};

// pullPlayList("playlist id here", "name of mp3 here");
<|endoftext|>


<commit_before>//Third party modules
var util = require('util');
//Application modules
var recipeFinder = require('./lib/RecipeFinder');

if (process.argv.length < 4) {
    console.log('Usage: node ' + process.argv[1] + ' Recipes-JSON-File Fridge-CSV-File-Name');
    process.exit(1);
}

var recipesFilePath = process.argv[2];
var fridgeFilePath = process.argv[3];

recipeFinder.run(recipesFilePath, fridgeFilePath, function(err, result){
    if (result) {
        console.log('Found recipe:', util.inspect(result.recipe, {showHidden: true, depth: null}));
    } else {
        console.log('Order Takeout');

    }

});
<commit_msg>Added comments on run.js<commit_after>//Third party modules
var util = require('util');
//Application modules
var recipeFinder = require('./lib/RecipeFinder');

if (process.argv.length < 4) {
    console.log('Usage: node ' + process.argv[1] + ' Recipes-JSON-File Fridge-CSV-File-Name');
    process.exit(1);
}

var recipesFilePath = process.argv[2];
var fridgeFilePath = process.argv[3];

//The run function of recipeFinder module will load data from the two files and return results
// through the callback function.
recipeFinder.run(recipesFilePath, fridgeFilePath, function(err, result){
    if (result) {
        console.log('Found recipe:', util.inspect(result.recipe, {showHidden: true, depth: null}));
    } else {
        console.log('Order Takeout');

    }

});
<|endoftext|>


<commit_before>"use strict";
// chess board
//var str = "", rowFlag = true, size = 8;
//for (var i = 1; i <= size; i++) {
//  for (var j = 1; j <= size; j++) {
//    if (j % 2 === 0) {
//      str += (rowFlag ? "#" : " ");
//    } else {
//      str += (rowFlag ? " " : "#");
//    }
//  }
//  str += "\n";
//  rowFlag = !rowFlag;
//}
//console.log(str);

/* CH3 FXNS */
// find minimum of 2 values
//function getMin(x, y) {
//  if (x < y) {
//    var min = x;
//  } else {
//    min = y;
//  }
//  return min;
//}
//console.log(getMin(35, 24));

// evenness
// recursive fxns must have a return value in all branches or will return undefined...
//var isEven = function evenness(x) {
//  if (x < 0 ) {
//    x = -1 * x;
//  }
//  if (x > 1) {
//    return isEven(x - 2);
//  } else if (x < 1) {
//    return true;
//  } else {
//    return false;
//  }
//};
//console.log(isEven(2532));

// bean counting
//var charCount = function beanCount(str, char) {
//  var cnt = 0;
//  for (var i = 0; i < str.length; i++) {
//    if (str[i] === char) {
//      cnt += 1;
//    }
//  }
//  return cnt;
//};
//console.log(charCount("BBC", "B"));
//console.log(charCount("kakkerlak", "k"));

/* CH4 DATA */
// range fxn
//var range = function rangeFxn(start, end, step) {
//  step = step || 1;
//  var arr = [];
//  if (start < end && step < 0) return undefined;
//  for (var i = start; ((step > 0) ? i <= end : i >= end); i += step) {
//    arr.push(i);
//  }
//  return arr;
//};
//console.log("1-10: ",range(1,10));
//console.log("5-2 neg step: ",range(5,2,-1));
//console.log("1-10, 2 step: ",range(1,10,2));

// sum a array of nums
//var sum = function sumFxn(arr) {
//  var sum = 0;
//  for (var i = 0; i < arr.length; i++) {
//    sum += arr[i];
//  }
//  return sum;
//};
//console.log("sum of range 1-10: ",sum(range(1,10)));

// reverse array
//var alpha = "abcdefghijklmnopqrstuvwxyz";
//var myArr = alpha.split("");
//var myNArr = alpha.split("");
//console.log("arrays: ",myArr,"\n",myNArr);
//function reverseIp(arr) {
//  var lenHlf = Math.floor(arr.length / 2), len = arr.length;
//  for (var i = 0; i < lenHlf; i++) {
//    var tmp = arr[i];
//    arr[i] = arr[arr.length - 1 - i];
//    arr[arr.length - 1 - i] = tmp;
//  }
//}
//
//// return new array that is reverse of the array passed
//var reverse = function reverseFxn(arr) {
//  var newArr = [], len = arr.length;
//  for (var i = 0; i < len; i++) {
//    newArr[i] = arr.pop();
//  }
//  return newArr;
//};
//
//reverseIp(myNArr);
//console.log("new reversed arr: ",reverse(myArr));
//console.log("old myNArr reversed in place: ",myNArr);

// lists
var arrayToList = function arr2L(arr) {
  var list = {}, inArr = arr;
  for (var i = inArr.length; i > 0; i--) {
    list = {value: inArr.pop(), rest: list};
  }
  console.log(list);
  return list;
}
var newList = arrayToList([1,2,3,4,"cheese","grits","sanctions",8]);

var listToArray = function l2Arr(listObj) {
  var arr = [], inObj = listObj;
  if (inObj.rest !== null) {
    while (Object.keys(inObj.rest).length !== 0 && inObj.rest.constructor === Object) {
      arr.push(inObj.value);
      inObj = inObj.rest;
    }
  } else {

  }
  console.log(arr);
  return arr;
}

var newArr = listToArray({
  value: 1, rest: {
    value: 2, rest: {
      value: 3, rest: null
    }
}});<commit_msg>removed if statement and solved issue with ternary inside of the while loop. final value pushed after exiting while loop<commit_after>"use strict";
// chess board
//var str = "", rowFlag = true, size = 8;
//for (var i = 1; i <= size; i++) {
//  for (var j = 1; j <= size; j++) {
//    if (j % 2 === 0) {
//      str += (rowFlag ? "#" : " ");
//    } else {
//      str += (rowFlag ? " " : "#");
//    }
//  }
//  str += "\n";
//  rowFlag = !rowFlag;
//}
//console.log(str);

/* CH3 FXNS */
// find minimum of 2 values
//function getMin(x, y) {
//  if (x < y) {
//    var min = x;
//  } else {
//    min = y;
//  }
//  return min;
//}
//console.log(getMin(35, 24));

// evenness
// recursive fxns must have a return value in all branches or will return undefined...
//var isEven = function evenness(x) {
//  if (x < 0 ) {
//    x = -1 * x;
//  }
//  if (x > 1) {
//    return isEven(x - 2);
//  } else if (x < 1) {
//    return true;
//  } else {
//    return false;
//  }
//};
//console.log(isEven(2532));

// bean counting
//var charCount = function beanCount(str, char) {
//  var cnt = 0;
//  for (var i = 0; i < str.length; i++) {
//    if (str[i] === char) {
//      cnt += 1;
//    }
//  }
//  return cnt;
//};
//console.log(charCount("BBC", "B"));
//console.log(charCount("kakkerlak", "k"));

/* CH4 DATA */
// range fxn
//var range = function rangeFxn(start, end, step) {
//  step = step || 1;
//  var arr = [];
//  if (start < end && step < 0) return undefined;
//  for (var i = start; ((step > 0) ? i <= end : i >= end); i += step) {
//    arr.push(i);
//  }
//  return arr;
//};
//console.log("1-10: ",range(1,10));
//console.log("5-2 neg step: ",range(5,2,-1));
//console.log("1-10, 2 step: ",range(1,10,2));

// sum a array of nums
//var sum = function sumFxn(arr) {
//  var sum = 0;
//  for (var i = 0; i < arr.length; i++) {
//    sum += arr[i];
//  }
//  return sum;
//};
//console.log("sum of range 1-10: ",sum(range(1,10)));

// reverse array
//var alpha = "abcdefghijklmnopqrstuvwxyz";
//var myArr = alpha.split("");
//var myNArr = alpha.split("");
//console.log("arrays: ",myArr,"\n",myNArr);
//function reverseIp(arr) {
//  var lenHlf = Math.floor(arr.length / 2), len = arr.length;
//  for (var i = 0; i < lenHlf; i++) {
//    var tmp = arr[i];
//    arr[i] = arr[arr.length - 1 - i];
//    arr[arr.length - 1 - i] = tmp;
//  }
//}
//
//// return new array that is reverse of the array passed
//var reverse = function reverseFxn(arr) {
//  var newArr = [], len = arr.length;
//  for (var i = 0; i < len; i++) {
//    newArr[i] = arr.pop();
//  }
//  return newArr;
//};
//
//reverseIp(myNArr);
//console.log("new reversed arr: ",reverse(myArr));
//console.log("old myNArr reversed in place: ",myNArr);

// lists
var arrayToList = function arr2L(arr) {
  var list = {}, inArr = arr;
  for (var i = inArr.length; i > 0; i--) {
    list = {value: inArr.pop(), rest: list};
  }
  console.log(list);
  return list;
}
var newList = arrayToList([1,2,3,4,"cheese","grits","sanctions",8]);

var listToArray = function l2Arr(listObj) {
  var arr = [], inObj = listObj;
  while ( (inObj.rest !== null ? (Object.keys(inObj.rest).length !== 0 && inObj.rest.constructor === Object) : false) ) {
    arr.push(inObj.value);
    inObj = inObj.rest;
  }
  arr.push(inObj.value);
  console.log(arr);
  return arr;
}
var myObj = {
  value: 1, rest: {
    value: 2, rest: {
      value: 3, rest: null
    }}};
var newArr = listToArray(myObj);<|endoftext|>