<commit_before>import hash from 'hash-sum'
import ee from 'event-emitter'
import resolveStyles from 'flint-radium/lib/resolve-styles'
import React from 'react'
import ReactDOM from 'react-dom'
import raf from 'raf'
import equal from 'deep-equal'
import clone from 'clone'
import Bluebird, { Promise } from 'bluebird'

import './lib/bluebirdErrorHandle'

import 'reapp-object-assign'
import './shim/root'
import './shim/flintMap'
import './shim/on'
import './shim/partial'

import reportError from './lib/reportError'
import arrayDiff from './lib/arrayDiff'
import createElement from './tag/createElement'
import Wrapper from './views/Wrapper'
import ErrorDefinedTwice from './views/ErrorDefinedTwice'
import NotFound from './views/NotFound'
import Main from './views/Main'

Promise.longStackTraces()

// GLOBALS
root._bluebird = Bluebird // for imported modules to use
root.on = on
root.Promise = Promise
root.module = {}
root.fetchJSON = (...args) => fetch(...args).then(res => res.json())
root.onerror = reportError

const uuid = () => Math.floor(Math.random() * 1000000)
const runEvents = (queue, name) =>
  queue && queue[name] && queue[name].length && queue[name].forEach(e => e())

function safeRun(prefix, fn) {
  if (process.env.production) fn()
  else {
    try { fn() }
    catch(e) {
      const { name, message, stack } = e
      console.log('Error in', prefix)
      reportError({ name, message, stack })
      throw e
    }
  }
}

function run(browserNode, userOpts, afterRenderCb) {
  const opts = Object.assign({
    namespace: {},
    entry: 'Main'
  }, userOpts)

  // either on window or namespace
  if (opts.namespace !== root && opts.app)
    root[opts.app] = opts.namespace

  const render = () => {
    const run = () => {
      const MainComponent = getComponent('Main') || Main;

      if (!browserNode) {
        Flint.renderedToString = React.renderToString(<MainComponent />)
        afterRenderCb && afterRenderCb(Flint.renderedToString)
      }
      else {
        ReactDOM.render(<MainComponent />, document.getElementById(browserNode))
      }

      Flint.firstRender = false
      emitter.emit('afterRender')
    }

    if (Flint.preloaders.length) {
      const preloaders = Flint.preloaders.map(loader => loader())
      Promise.all(preloaders).then(run)
    }
    else {
      run()
    }
  }

  // exported tracks previous exports so we can overwrite
  let exported = {}
  const assignToGlobal = (name, val) => {
    if (!exported[name] && typeof root[name] != 'undefined')
      throw `You're attempting to define a global that is already defined:
          ${name} = ${JSON.stringify(root[name])}`

    exported[name] = true
    root[name] = val
  }

  const removeComponent = key => {
    delete Flint.views[key]
    delete opts.namespace[key]
  }

  const setComponent = (key, val) => (opts.namespace[key] = val)
  const getComponent = (key) => opts.namespace[key]
  const emitter = ee({})

  function propsHash(obj) {
    return hash(obj)
  }

  let Flint = {
    views: {},
    lastWorkingView: {},
    // async functions needed before loading app
    preloaders: [],
    render,
    // internal events
    on(name, cb) { emitter.on(name, cb) },
    // map of views in various files
    viewCache: {},
    // current build up of running hot insertion
    viewsInFile: {},
    // current file that is running
    currentHotFile: null,
    // if a file updates but view doesnt change,
    // we update its render to pick up changed variables in the file
    currentRender: {},
    // track first render
    firstRender: true,
    // for use in jsx
    debug: () => {
      debugger
    },

    file(file, run) {
      Flint.viewsInFile[file] = []
      Flint.currentHotFile = file

      // run view, get exports
      let fileExports = {}
      run(fileExports)
      Flint.setExports(fileExports)

      const cached = Flint.viewCache[file] || []
      const views = Flint.viewsInFile[file]

      // remove views that werent made
      const removed = arrayDiff(cached, views)
      removed.map(removeComponent)

      Flint.currentHotFile = null
      Flint.viewCache[file] = Flint.viewsInFile[file]

      // avoid tons of renders on start
      if (Flint.firstRender) return

      raf(() => {
        Flint.isLoadingFile = true
        render()
        Flint.isLoadingFile = false

        // its been updated
        Object.keys(Flint.views).forEach(key => {
          Flint.views[key].needsUpdate = false
        })
      })
    },

    deleteFile(name) {
      const weirdName = `/${name}`
      Flint.viewsInFile[weirdName].map(removeComponent)
      delete Flint.viewsInFile[weirdName]
      delete Flint.viewCache[weirdName]
      render()
      debugger
    },

    // stores { path: { name: val } } for use in view.get()
    getCache: {},
    propsHashes: {},

    makeReactComponent(name, component, options = {}) {
      const el = createElement(name)

      const spec = {
        displayName: name,
        name,
        el,
        Flint,

        childContextTypes: {
          path: React.PropTypes.string
        },

        contextTypes: {
          path: React.PropTypes.string
        },

        getChildContext() {
          // no need for paths/cache in production
          if (process.env.production)
            return {}

          let propsPath

          // get the props hash, but lets cache it so its not a ton of work
          if (options.changed === true) {
            this.propsPath = propsHash(this.props)
            Flint.propsHashes[this.context.path] = this.propsPath
            options.changed = 2
          }
          else if (!this.propsPath) {
            this.propsPath = (
              Flint.propsHashes[this.context.path] ||
              propsHash(this.props)
            )
          }

          return {
            path: (this.context.path || '') + name + '$' + this.propsPath
          }
        },

        shouldUpdate() {
          return (
            this.didMount && !this.isUpdating &&
            !this.isPaused && !this.firstRender
          )
        },

        set(name, val) {
          if (!process.env.production) {
            Flint.getCache[this.path] = Flint.getCache[this.path] || {}
            Flint.getCache[this.path][name] = val
          }

          if (this.shouldUpdate())
            this.forceUpdate()
        },

        get(name, val) {
          if (process.env.production)
            return val

          // if hot reloaded but not changed
          if (options.unchanged) {
            if (Flint.getCache[this.path])
              return Flint.getCache[this.path][name]
            else
              return val
          }
          else {
            // on first get, we may not have even set
            if (!Flint.getCache[this.path]) Flint.getCache[this.path] = {}
            if (typeof Flint.getCache[this.path][name] == 'undefined')
              Flint.getCache[this.path][name] = val

            return val
          }
        },

        // LIFECYCLES

        getInitialState() {
          if (name == 'Main')
            Flint.mainView = this

          this.path = (this.context.path || '') + name

          if (!options.unchanged)
            delete Flint.getCache[this.path]

          this.firstRender = true
          this.styles = { _static: {} }
          this.events = {
            mount: null, unmount: null,
            update: null, props: null
          }

          const viewOn = (scope, name, cb) => {
            // check if they defined their own scope
            if (name && typeof name == 'string')
              return on(scope, name, cb)
            else
              return on(this, scope, name)
          }

          // cache original render
          const flintRender = this.render
          component(this, viewOn)

          // reset original render, cache view render
          this.viewRender = this.render
          this.render = flintRender

          return null
        },

        componentWillReceiveProps(nextProps) {
          this.props = nextProps
          runEvents(this.events, 'props')
        },

        componentDidMount() {
          this.didMount = true
          runEvents(this.events, 'mount')
        },

        componentWillUnmount() {
          this.didMount = false
          runEvents(this.events, 'unmount')
        },

        componentWillMount() {
          // componentWillUpdate only runs after first render
          runEvents(this.events, 'update')
        },

        componentWillUpdate() {
          this.isUpdating = true
          runEvents(this.events, 'update')
        },

        componentDidUpdate() {
          this.isUpdating = false
        },

        // FLINT HELPERS

        // helpers for controlling re-renders
        pause() { this.isPaused = true },
        resume() { this.isPaused = false },

        // helpers for context
        childContext(obj) {
          if (!obj) return

          Object.keys(obj).forEach(key => {
            this.constructor.childContextTypes[key] =
              React.PropTypes[typeof obj[key]]
          })

          this.getChildContext = () => obj
        },

        render() {
          let els
          const render = this.viewRender
          this.firstRender = false

          // safeRun(`${name}.render()`, () => {
            els = render()
          // })

          const wrapperStyle = this.styles && this.styles.$
          const __disableWrapper = wrapperStyle ? wrapperStyle() === false : false
          const withProps = React.cloneElement(els, { __disableWrapper });
          const styled = els && resolveStyles(this, withProps)
          return styled
        }
      }

      return React.createClass(spec);
    },

    getView(name, parentName) {
      let result

      // View.SubView
      const subName = `${parentName}.${name}`
      if (Flint.views[subName])
        result = Flint.views[subName].component

      // regular view
      else if (Flint.views[name])
        result = Flint.views[name].component;

      // wrapper
      else if (/Flint\.[\.a-zA-Z0-9]*Wrapper/.test(name))
        result = Wrapper

      // global views
      else if (opts.namespace[name])
        result = namespaceView

      else
        result = NotFound(name)

       return result
    },

    /*
      hash is the build systems hash of the view contents
        used for detecting changed views
    */
    view(name, hash, component) {
      // Flint.viewsInFile[Flint.currentHotFile].push(name)

      function setView(name, Component) {
        Flint.views[name] = Flint.makeView(hash, Component)
        setComponent(name, Component)
        if (Flint.firstRun) return
      }

      // if new
      if (Flint.views[name] == undefined) {
        let Component = Flint.makeReactComponent(name, component, { hash, changed: true });
        setView(name, Component)
        Flint.lastWorkingView[name] = Flint.views[name].component
        return
      }

      // not new

      // if defined twice during first run
      if (Flint.firstRun) {
        console.error('Defined a view twice!', name, hash)
        setComponent(name, ErrorDefinedTwice(name))
        return
      }

      // if unchanged
      if (Flint.views[name].hash == hash) {
        let Component = Flint.makeReactComponent(name, component, { hash, unchanged: true });
        setView(name, Component)
        return
      }

      // start with a success and an error will fire before next frame
      if (root._DT)
        root._DT.emitter.emit('runtime:success')

      let viewRanSuccessfully = true

      // recover from bad views
      window.onerror = (...args) => {
        viewRanSuccessfully = false

        if (Flint.lastWorkingView[name]) {
          setView(name, Flint.lastWorkingView[name])
          render()
        }
        else {
          setView(name, ErrorDefinedTwice(name))
          render()
        }
      }

      Flint.on('afterRender', () => {
        if (viewRanSuccessfully)
          Flint.lastWorkingView[name] = Flint.views[name].component
      })

      let flintComponent = Flint.makeReactComponent(name, component, { changed: true })
      setView(name, flintComponent)

      // this resets tool errors
      window.onViewLoaded()
    },

    makeView(hash, component) {
      return { hash, component, needsUpdate: true };
    },

    getStyle(id, name) {
      return Flint.styles && Flint.styles[id][name]
    },

    // export globals
    setExports(_exports) {
      if (!_exports) return
      const names = Object.keys(_exports)

      if (names.length) {
        names.forEach(name => {
          if (name === 'default') {
            Object.keys(_exports.default).forEach(key => {
              assignToGlobal(key, _exports.default[key])
            })
          }

          assignToGlobal(name, _exports[name])
        })
      }
    }
  }

  // shim root view
  opts.namespace.view = {
    update: () => {},
    el: createElement('_'),
    Flint
  }

  // set flint onto namespace
  opts.namespace.Flint = Flint;

  return Flint;
}

export default run
<commit_msg>no more global views<commit_after>import hash from 'hash-sum'
import ee from 'event-emitter'
import resolveStyles from 'flint-radium/lib/resolve-styles'
import React from 'react'
import ReactDOM from 'react-dom'
import raf from 'raf'
import equal from 'deep-equal'
import clone from 'clone'
import Bluebird, { Promise } from 'bluebird'

import './lib/bluebirdErrorHandle'

import 'reapp-object-assign'
import './shim/root'
import './shim/flintMap'
import './shim/on'
import './shim/partial'

import reportError from './lib/reportError'
import arrayDiff from './lib/arrayDiff'
import createElement from './tag/createElement'
import Wrapper from './views/Wrapper'
import ErrorDefinedTwice from './views/ErrorDefinedTwice'
import NotFound from './views/NotFound'
import Main from './views/Main'

Promise.longStackTraces()

// GLOBALS
root._bluebird = Bluebird // for imported modules to use
root.on = on
root.Promise = Promise
root.module = {}
root.fetchJSON = (...args) => fetch(...args).then(res => res.json())
root.onerror = reportError

const uuid = () => Math.floor(Math.random() * 1000000)
const runEvents = (queue, name) =>
  queue && queue[name] && queue[name].length && queue[name].forEach(e => e())

function safeRun(prefix, fn) {
  if (process.env.production) fn()
  else {
    try { fn() }
    catch(e) {
      const { name, message, stack } = e
      console.log('Error in', prefix)
      reportError({ name, message, stack })
      throw e
    }
  }
}

function run(browserNode, userOpts, afterRenderCb) {
  const opts = Object.assign({
    namespace: {},
    entry: 'Main'
  }, userOpts)

  // either on window or namespace
  if (opts.namespace !== root && opts.app)
    root[opts.app] = opts.namespace

  const render = () => {
    const run = () => {
      const MainComponent = getComponent('Main') || Main;

      if (!browserNode) {
        Flint.renderedToString = React.renderToString(<MainComponent />)
        afterRenderCb && afterRenderCb(Flint.renderedToString)
      }
      else {
        ReactDOM.render(<MainComponent />, document.getElementById(browserNode))
      }

      Flint.firstRender = false
      emitter.emit('afterRender')
    }

    if (Flint.preloaders.length) {
      const preloaders = Flint.preloaders.map(loader => loader())
      Promise.all(preloaders).then(run)
    }
    else {
      run()
    }
  }

  // exported tracks previous exports so we can overwrite
  let exported = {}
  const assignToGlobal = (name, val) => {
    if (!exported[name] && typeof root[name] != 'undefined')
      throw `You're attempting to define a global that is already defined:
          ${name} = ${JSON.stringify(root[name])}`

    exported[name] = true
    root[name] = val
  }

  const removeComponent = key => {
    delete Flint.views[key]
    delete opts.namespace[key]
  }

  const setComponent = (key, val) => (opts.namespace[key] = val)
  const getComponent = (key) => opts.namespace[key]
  const emitter = ee({})

  function propsHash(obj) {
    return hash(obj)
  }

  let Flint = {
    views: {},
    lastWorkingView: {},
    // async functions needed before loading app
    preloaders: [],
    render,
    // internal events
    on(name, cb) { emitter.on(name, cb) },
    // map of views in various files
    viewCache: {},
    // current build up of running hot insertion
    viewsInFile: {},
    // current file that is running
    currentHotFile: null,
    // if a file updates but view doesnt change,
    // we update its render to pick up changed variables in the file
    currentRender: {},
    // track first render
    firstRender: true,
    // for use in jsx
    debug: () => {
      debugger
    },

    file(file, run) {
      Flint.viewsInFile[file] = []
      Flint.currentHotFile = file

      // run view, get exports
      let fileExports = {}
      run(fileExports)
      Flint.setExports(fileExports)

      const cached = Flint.viewCache[file] || []
      const views = Flint.viewsInFile[file]

      // remove views that werent made
      const removed = arrayDiff(cached, views)
      removed.map(removeComponent)

      Flint.currentHotFile = null
      Flint.viewCache[file] = Flint.viewsInFile[file]

      // avoid tons of renders on start
      if (Flint.firstRender) return

      raf(() => {
        Flint.isLoadingFile = true
        render()
        Flint.isLoadingFile = false

        // its been updated
        Object.keys(Flint.views).forEach(key => {
          Flint.views[key].needsUpdate = false
        })
      })
    },

    deleteFile(name) {
      const weirdName = `/${name}`
      Flint.viewsInFile[weirdName].map(removeComponent)
      delete Flint.viewsInFile[weirdName]
      delete Flint.viewCache[weirdName]
      render()
      debugger
    },

    // stores { path: { name: val } } for use in view.get()
    getCache: {},
    propsHashes: {},

    makeReactComponent(name, component, options = {}) {
      const el = createElement(name)

      const spec = {
        displayName: name,
        name,
        el,
        Flint,

        childContextTypes: {
          path: React.PropTypes.string
        },

        contextTypes: {
          path: React.PropTypes.string
        },

        getChildContext() {
          // no need for paths/cache in production
          if (process.env.production)
            return {}

          let propsPath

          // get the props hash, but lets cache it so its not a ton of work
          if (options.changed === true) {
            this.propsPath = propsHash(this.props)
            Flint.propsHashes[this.context.path] = this.propsPath
            options.changed = 2
          }
          else if (!this.propsPath) {
            this.propsPath = (
              Flint.propsHashes[this.context.path] ||
              propsHash(this.props)
            )
          }

          return {
            path: (this.context.path || '') + name + '$' + this.propsPath
          }
        },

        shouldUpdate() {
          return (
            this.didMount && !this.isUpdating &&
            !this.isPaused && !this.firstRender
          )
        },

        set(name, val) {
          if (!process.env.production) {
            Flint.getCache[this.path] = Flint.getCache[this.path] || {}
            Flint.getCache[this.path][name] = val
          }

          if (this.shouldUpdate())
            this.forceUpdate()
        },

        get(name, val) {
          if (process.env.production)
            return val

          // if hot reloaded but not changed
          if (options.unchanged) {
            if (Flint.getCache[this.path])
              return Flint.getCache[this.path][name]
            else
              return val
          }
          else {
            // on first get, we may not have even set
            if (!Flint.getCache[this.path]) Flint.getCache[this.path] = {}
            if (typeof Flint.getCache[this.path][name] == 'undefined')
              Flint.getCache[this.path][name] = val

            return val
          }
        },

        // LIFECYCLES

        getInitialState() {
          if (name == 'Main')
            Flint.mainView = this

          this.path = (this.context.path || '') + name

          if (!options.unchanged)
            delete Flint.getCache[this.path]

          this.firstRender = true
          this.styles = { _static: {} }
          this.events = {
            mount: null, unmount: null,
            update: null, props: null
          }

          const viewOn = (scope, name, cb) => {
            // check if they defined their own scope
            if (name && typeof name == 'string')
              return on(scope, name, cb)
            else
              return on(this, scope, name)
          }

          // cache original render
          const flintRender = this.render
          component(this, viewOn)

          // reset original render, cache view render
          this.viewRender = this.render
          this.render = flintRender

          return null
        },

        componentWillReceiveProps(nextProps) {
          this.props = nextProps
          runEvents(this.events, 'props')
        },

        componentDidMount() {
          this.didMount = true
          runEvents(this.events, 'mount')
        },

        componentWillUnmount() {
          this.didMount = false
          runEvents(this.events, 'unmount')
        },

        componentWillMount() {
          // componentWillUpdate only runs after first render
          runEvents(this.events, 'update')
        },

        componentWillUpdate() {
          this.isUpdating = true
          runEvents(this.events, 'update')
        },

        componentDidUpdate() {
          this.isUpdating = false
        },

        // FLINT HELPERS

        // helpers for controlling re-renders
        pause() { this.isPaused = true },
        resume() { this.isPaused = false },

        // helpers for context
        childContext(obj) {
          if (!obj) return

          Object.keys(obj).forEach(key => {
            this.constructor.childContextTypes[key] =
              React.PropTypes[typeof obj[key]]
          })

          this.getChildContext = () => obj
        },

        render() {
          let els
          const render = this.viewRender
          this.firstRender = false

          // safeRun(`${name}.render()`, () => {
            els = render()
          // })

          const wrapperStyle = this.styles && this.styles.$
          const __disableWrapper = wrapperStyle ? wrapperStyle() === false : false
          const withProps = React.cloneElement(els, { __disableWrapper });
          const styled = els && resolveStyles(this, withProps)
          return styled
        }
      }

      return React.createClass(spec);
    },

    getView(name, parentName) {
      let result

      // View.SubView
      const subName = `${parentName}.${name}`
      if (Flint.views[subName])
        result = Flint.views[subName].component

      // regular view
      else if (Flint.views[name])
        result = Flint.views[name].component

      // wrapper
      else if (/Flint\.[\.a-zA-Z0-9]*Wrapper/.test(name))
        result = Wrapper

      else
        result = NotFound(name)

       return result
    },

    /*
      hash is the build systems hash of the view contents
        used for detecting changed views
    */
    view(name, hash, component) {
      // Flint.viewsInFile[Flint.currentHotFile].push(name)

      function setView(name, Component) {
        Flint.views[name] = Flint.makeView(hash, Component)
        setComponent(name, Component)
        if (Flint.firstRun) return
      }

      // if new
      if (Flint.views[name] == undefined) {
        let Component = Flint.makeReactComponent(name, component, { hash, changed: true });
        setView(name, Component)
        Flint.lastWorkingView[name] = Flint.views[name].component
        return
      }

      // not new

      // if defined twice during first run
      if (Flint.firstRun) {
        console.error('Defined a view twice!', name, hash)
        setComponent(name, ErrorDefinedTwice(name))
        return
      }

      // if unchanged
      if (Flint.views[name].hash == hash) {
        let Component = Flint.makeReactComponent(name, component, { hash, unchanged: true });
        setView(name, Component)
        return
      }

      // start with a success and an error will fire before next frame
      if (root._DT)
        root._DT.emitter.emit('runtime:success')

      let viewRanSuccessfully = true

      // recover from bad views
      window.onerror = (...args) => {
        viewRanSuccessfully = false

        if (Flint.lastWorkingView[name]) {
          setView(name, Flint.lastWorkingView[name])
          render()
        }
        else {
          setView(name, ErrorDefinedTwice(name))
          render()
        }
      }

      Flint.on('afterRender', () => {
        if (viewRanSuccessfully)
          Flint.lastWorkingView[name] = Flint.views[name].component
      })

      let flintComponent = Flint.makeReactComponent(name, component, { changed: true })
      setView(name, flintComponent)

      // this resets tool errors
      window.onViewLoaded()
    },

    makeView(hash, component) {
      return { hash, component, needsUpdate: true };
    },

    getStyle(id, name) {
      return Flint.styles && Flint.styles[id][name]
    },

    // export globals
    setExports(_exports) {
      if (!_exports) return
      const names = Object.keys(_exports)

      if (names.length) {
        names.forEach(name => {
          if (name === 'default') {
            Object.keys(_exports.default).forEach(key => {
              assignToGlobal(key, _exports.default[key])
            })
          }

          assignToGlobal(name, _exports[name])
        })
      }
    }
  }

  // shim root view
  opts.namespace.view = {
    update: () => {},
    el: createElement('_'),
    Flint
  }

  // set flint onto namespace
  opts.namespace.Flint = Flint;

  return Flint;
}

export default run
<|endoftext|>


<commit_before>module.exports = [
  {name: 'The Gitmaster', alias: 'gitmaster', blurb:'We made a game.', href:'https://thegitmaster.herokuapp.com/', image:'https://imgur.com/MuCW4BM.jpg'},
  {name: 'EDA cheatsheet', alias: 'cheatsheet', blurb:'Toggle!', href:'https://eda-cheatsheet.herokuapp.com/', image:'https://imgur.com/DIi6DOB.jpg'},
  {name: 'CLOCK', alias: 'clock', blurb:'Tells the time.', image:'http://i.imgur.com/2WYjdQt.jpg'},
  {name: 'Jukebox', alias: 'jukebox', blurb:'Can search and create playlists.', image:'http://i.imgur.com/2WYjdQt.jpg'},
  {name: 'KanyeRest', alias: 'kanye', blurb:'Simple use of a RESTful API.', image:'http://i.imgur.com/2WYjdQt.jpg'},
  {name: 'Calculator', alias: 'calculator', blurb:'Numbery buttons.', image:'http://i.imgur.com/2WYjdQt.jpg'},
  {name: 'Minesweeper', alias: 'minesweeper', blurb:'Simple version of the game.', image:'http://i.imgur.com/2WYjdQt.jpg'},
  {name: 'Tic Tac Toe', alias: 'tictactoe', blurb:'Classic.', image:'http://i.imgur.com/2WYjdQt.jpg'}
]
<commit_msg>Secure image link<commit_after>module.exports = [
  {name: 'The Gitmaster', alias: 'gitmaster', blurb:'We made a game.', href:'https://thegitmaster.herokuapp.com/', image:'https://imgur.com/MuCW4BM.jpg'},
  {name: 'EDA cheatsheet', alias: 'cheatsheet', blurb:'Toggle!', href:'https://eda-cheatsheet.herokuapp.com/', image:'https://imgur.com/DIi6DOB.jpg'},
  {name: 'CLOCK', alias: 'clock', blurb:'Tells the time.', image:'http://i.imgur.com/2WYjdQt.jpg'},
  {name: 'Jukebox', alias: 'jukebox', blurb:'Can search and create playlists.', image:'https://i.imgur.com/2WYjdQt.jpg'},
  {name: 'KanyeRest', alias: 'kanye', blurb:'Simple use of a RESTful API.', image:'https://i.imgur.com/2WYjdQt.jpg'},
  {name: 'Calculator', alias: 'calculator', blurb:'Numbery buttons.', image:'https://i.imgur.com/2WYjdQt.jpg'},
  {name: 'Minesweeper', alias: 'minesweeper', blurb:'Simple version of the game.', image:'https://i.imgur.com/2WYjdQt.jpg'},
  {name: 'Tic Tac Toe', alias: 'tictactoe', blurb:'Classic.', image:'https://i.imgur.com/2WYjdQt.jpg'}
]
<|endoftext|>


<commit_before>setTimeout(loadButton, 2000);

var opossum_clicked = false;
var video_id = window.location.href.split('/watch?v=')[1];

/**
 * Loads the button onto the page.
 */
function loadButton() {
  console.log('loading button');
  var menuContainer = document.getElementById('menu-container');
  var header = document.getElementsByTagName('ytd-video-primary-info-renderer')[0];

  if (!header) {
    console.warn('No header text detected.');
    return;
  }

  var button = document.createElement('button');
  button.textContent = 'COOL BUTTON';
  button.setAttribute('id', 'opossum');

  console.log('Loading button...');
  header.insertBefore(button, header.children[0]);
  $('#meta-contents').append('

');

  $('#opossum').click(function() {
    opossum_clicked = !opossum_clicked;

    if (opossum_clicked) {
      injectText(getSummary());
    } else {
      injectText("");
    }
  });
};

/**
 * Gets summary of currently playing video.
 */
function getSummary() {
  // TODO: Get summary of video currently playing.
  console.log('Retrieving summary...');
  var oSummary = '';
  $.ajax({
    method: 'POST',
    url: '/' + video_id,
    data: video_id,
    dataType: 'text',
    success: function(data) {
      console.log('Summary retrieved!');
      oSummary = data;
    }
  });
  return oSummary || "Hello. Here is some sample text.";
}

/**
 * Injects summary text into view.
 */
function injectText(htmlText) {
  if (htmlText) {
    htmlText += '

';
  }
  $('#opossum_text').html(htmlText);
}
<commit_msg>Minor changes to render<commit_after>// Waits for page to load. Temporary hack bc YT uses
// asynchronous loading and idk how to do this lol
setTimeout(loadButton, 2000);

// Whether the video has been clicked?
var opossum_clicked = false; // TODO: Show as already saved after checking db
var video_id = window.location.href.split('/watch?v=')[1];

/**
 * Loads the button onto the page.
 */
function loadButton() {
  console.log('loading button');
  var menuContainer = document.getElementById('menu-container');
  var header = document.getElementsByTagName('ytd-video-primary-info-renderer')[0];

  if (!header) {
    console.warn('No header text detected.');
    return;
  }

  var button = document.createElement('button');
  button.textContent = 'COOL BUTTON';
  button.setAttribute('id', 'opossum');

  console.log('Loading button...');
  header.insertBefore(button, header.children[0]);
  $('#meta-contents').append('

');

  $('#opossum').click(function() {
    opossum_clicked = !opossum_clicked;

    if (opossum_clicked) {
      injectText(getSummary());
    } else {
      injectText("");
    }
  });
};

/**
 * Gets summary of currently playing video.
 */
function getSummary() {
  console.log('Retrieving summary...');
  var oSummary = '';
  $.ajax({
    method: 'POST',
    url: '/' + video_id,
    data: video_id,
    dataType: 'text',
    success: function(data) {
      console.log('Summary retrieved!');
      oSummary = data;
    }
  });
  return oSummary || "Hello. Here is some sample text.";
}

/**
 * Injects summary text into view.
 */
function injectText(htmlText) {
  if (htmlText) {
    htmlText += '

';
  }
  $('#opossum_text').html(htmlText);
}
<|endoftext|>


<commit_before>var SimpleParser = Editor.Parser = (function() {
//  function tokenizeDummy(source) {
//    while (!source.endOfLine()) source.next();
//    return "text";
//  }
  var tokenizeSimple = (function() {

    var urlRe = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)\.(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?[^\s\(\)\[\]\."'{}]/;
    var urlRe = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?((?:[a-z0-9](?:[a-z0-9\-]{0,61}[a-z0-9])+\.)+[a-z]{2,6}|[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})(:[0-9]{1,4})?(\/[\w#!~:.?+=&%@!\-\/]*)?/i;
    //                                 (user:passwrd@)?((?:no "-"     (?:                              )+ .)+[tld no "-" ])(:port      )?(/ | /(path               ))?
    //var urlRe = /^(\()((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]+)(\))|(\[)((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]+)(\])|(\{)((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]+)(\})|(<|&(?:lt|#60|#x3c);)((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]+)(>|&(?:gt|#62|#x3e);)|((?:^|[^=\s'"\]])\s*['"]?|[^=\s]\s+)(\b(?:ht|f)tps?:\/\/[a-z0-9\-._~!$'()*+,;=:\/?#[\]@%]+(?:(?!&(?:gt|#0*62|#x0*3e);|&(?:amp|apos|quot|#0*3[49]|#x0*2[27]);[.!&',:?;]?(?:[^a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]|$))&[a-z0-9\-._~!$'()*+,;=:\/?#[\]@%]*)*[a-z0-9\-_~$()*+=\/#[\]@%])/i;
    // from http://jmrware.com/articles/2010/linkifyurl/linkify.html
    function urlInfo(urlMatch) {
        var urlinfo = {
            full: urlMatch[0],
            protocol: urlMatch[1],
            userpass: urlMatch[2],
            domain: urlMatch[3],
            port: urlMatch[4],
            path: urlMatch[5]
        };
        return urlinfo;
    }
    function normal(source, setState) {
      var ch = source.peek();
      var url;
      if (source.endOfLine()) {
          source.next();
          return "whitespace";
      }
      url = source.lookAheadRegex(urlRe, true)
      if (url) {
          //console.log("found a link:");
          //console.log(urlInfo(url));
          return "sn-link";
      }

      while(!url && !source.endOfLine()) {
        source.nextWhileMatches(/[^h\n\s]/);
        if (!source.endOfLine()) {
            url = source.lookAheadRegex(urlRe, false);
            if (url)
                return "text";
            else {
                source.next();
            }
        } else
            return "text";
      }
      return "text";
    }

    return function(source, startState) {
      return tokenizer(source, startState || normal);
    };
  })();

  function parseSimple(source) {
    function indentTo(n) {return function() {return n;}}
    source = tokenizeSimple(source);
    var space = 0;

    var iter = {
      next: function() {
        var tok = source.next();
        if (tok.type == "whitespace") {
          if (tok.value == "\n") tok.indentation = indentTo(space);
          else space = tok.value.length;
        }
        return tok;
      },
      copy: function() {
        var _space = space;
        return function(_source) {
          space = _space;
          source = tokenizeSimple(_source);
          return iter;
        };
      }
    };
    return iter;
  }
  return {make: parseSimple};
})();
<commit_msg>fix for http://t.foo<commit_after>var SimpleParser = Editor.Parser = (function() {
//  function tokenizeDummy(source) {
//    while (!source.endOfLine()) source.next();
//    return "text";
//  }
  var tokenizeSimple = (function() {

    var urlRe = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)\.(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?[^\s\(\)\[\]\."'{}]/;
    var urlRe = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?((?:[a-z0-9]?(?:[a-z0-9\-]{0,61}[a-z0-9])+\.)+[a-z]{2,6}|[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})(:[0-9]{1,4})?(\/[\w#!~:.?+=&%@!\-\/]*)?/i;
    //                                 (user:passwrd@)?((?:no "-"     (?:                              )+ .)+[tld no "-" ])(:port      )?(/ | /(path               ))?
    //var urlRe = /^(\()((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]+)(\))|(\[)((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]+)(\])|(\{)((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]+)(\})|(<|&(?:lt|#60|#x3c);)((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]+)(>|&(?:gt|#62|#x3e);)|((?:^|[^=\s'"\]])\s*['"]?|[^=\s]\s+)(\b(?:ht|f)tps?:\/\/[a-z0-9\-._~!$'()*+,;=:\/?#[\]@%]+(?:(?!&(?:gt|#0*62|#x0*3e);|&(?:amp|apos|quot|#0*3[49]|#x0*2[27]);[.!&',:?;]?(?:[^a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]|$))&[a-z0-9\-._~!$'()*+,;=:\/?#[\]@%]*)*[a-z0-9\-_~$()*+=\/#[\]@%])/i;
    // from http://jmrware.com/articles/2010/linkifyurl/linkify.html
    function urlInfo(urlMatch) {
        var urlinfo = {
            full: urlMatch[0],
            protocol: urlMatch[1],
            userpass: urlMatch[2],
            domain: urlMatch[3],
            port: urlMatch[4],
            path: urlMatch[5]
        };
        return urlinfo;
    }
    function normal(source, setState) {
      var ch = source.peek();
      var url;
      if (source.endOfLine()) {
          source.next();
          return "whitespace";
      }
      url = source.lookAheadRegex(urlRe, true)
      if (url) {
          //console.log("found a link:");
          //console.log(urlInfo(url));
          return "sn-link";
      }

      while(!url && !source.endOfLine()) {
        source.nextWhileMatches(/[^h\n\s]/);
        if (!source.endOfLine()) {
            url = source.lookAheadRegex(urlRe, false);
            if (url)
                return "text";
            else {
                source.next();
            }
        } else
            return "text";
      }
      return "text";
    }

    return function(source, startState) {
      return tokenizer(source, startState || normal);
    };
  })();

  function parseSimple(source) {
    function indentTo(n) {return function() {return n;}}
    source = tokenizeSimple(source);
    var space = 0;

    var iter = {
      next: function() {
        var tok = source.next();
        if (tok.type == "whitespace") {
          if (tok.value == "\n") tok.indentation = indentTo(space);
          else space = tok.value.length;
        }
        return tok;
      },
      copy: function() {
        var _space = space;
        return function(_source) {
          space = _space;
          source = tokenizeSimple(_source);
          return iter;
        };
      }
    };
    return iter;
  }
  return {make: parseSimple};
})();
<|endoftext|>


<commit_before>function Controller() {
  this.user = null;
  this.rocket = null;
  this.view = null;
  this.interval = null;
}

Controller.prototype = {

  start: function(){
    this.user = new User();

    this.rocket = new Rocket();
    this.view = new View(this.user,this.rocket);
    this.bindEvents();
    this.pressingUp = false; //new var to track rocket's upward acceleration, used to stop gravity's impact while accellerating
    this.gameWon = false;
    this.gameLost = false;
    this.lose_y = 490;
    this.win_x1 = 150;
    this.win_x2 = 310;
    this.win_y1 = 405;
    this.win_y2 = 460;
  },

  bindEvents: function(){
    $(document).on("keydown",this.keypress.bind(this));
    $(document).on("keyup",this.keyrelease.bind(this)); //event listener is keyup, calls our keyrelease function
    $(this.view.logInButtonSelector).on("click", this.logInButton.bind(this));
    $(this.view.startButtonSelector).on("click", this.startButton.bind(this));
    $(this.view.stopButtonSelector).on("click", this.stopButton.bind(this))
  },

  logInButton: function(e) {
    e.preventDefault();
     // this.view.logInButton();
     console.log("log in button function in controller")
     console.log(this.user)
     var logInUrl = $(this.view.logInButtonSelector).closest('form').attr("action");
     this.user.logIn(logInUrl);
       },

  keypress: function(e) {
    if(e.keyCode == 37) {
      this.rocket.moveLeft();
    }
    if(e.keyCode == 39) {
      this.rocket.moveRight();
    }
    if(e.keyCode == 38) {
      this.pressingUp = true; //if pressing up key, rocket accelerates up i.e. true
      this.rocket.moveUp();
    }
    if(e.keyCode == 40) {
      this.rocket.moveDown();
    }
    this.view.updateRocketPosition();
  },

  keyrelease: function(e) {
    if(e.keyCode == 38) {
      this.pressingUp = false;
    };
  },

  gameLoop: function(e) {
    this.gravity();
    this.checkLose();
    this.checkWin();
  },
  checkLose: function() {
    console.log("loser loser", this);
    console.log(this.rocket.y, this.lose_y, (this.rocket.y > this.lose_y))
    if(this.rocket.y > this.lose_y) {
      this.gameLost = true;
      this.endGame();
    }
  },
  checkWin: function() {
    console.log("winner winner", this);
    var check_x = (this.rocket.x > this.win_x1) && (this.rocket.x < this.win_x2);
    var check_y = (this.rocket.y > this.win_y1) && (this.rocket.y > this.win_y2);
    console.log(check_x, check_y, (check_x && check_y))
    if(check_x && check_y) {
      this.gameWon = true;
      this.endGame();
    }
  },
  endGame: function(){
    if(this.gameWon) {
      console.log("You won");
      this.user.points += 100;
      this.user.updatePoints();
      this.view.showWin();
      this.checkLevel();

      console.log(this.user.points);
    } else if(this.gameLost) {
      console.log("You lost");
      this.view.showLose();
    };
    clearInterval(this.interval);
    $(document).off();
    //$(document).off("keydown",this.keypress.bind(this));
    //$(document).off("keyup",this.keyrelease.bind(this));
  },
  gravity: function() {
    console.log("I'm free falling!", this);
    if(!this.pressingUp){
      this.rocket.moveDown(); //if keyup has happened, gravity moves it down
    };
    this.view.updateRocketPosition();
  },

  startButton: function(e) {
    this.view.startButton();
    this.interval = setInterval(this.gameLoop.bind(this),150);
  },
  stopButton: function(e) {
    this.rocket.resetLocation;
    clearInterval(this.interval);
    this.view.updateRocketPosition();
  },

  checkLevel: function() {

  }

  // gameDone: function (e){
  //   $("keypress").unbind("keydown");
  // }
};

<commit_msg>toggle pause button<commit_after>function Controller() {
  this.user = null;
  this.rocket = null;
  this.view = null;
  this.interval = null;
  this.pause = false;
}

Controller.prototype = {

  start: function(){
    this.user = new User();

    this.rocket = new Rocket();
    this.view = new View(this.user,this.rocket);
    this.bindEvents();
    this.pressingUp = false; //new var to track rocket's upward acceleration, used to stop gravity's impact while accellerating
    this.gameWon = false;
    this.gameLost = false;
    this.lose_y = 490;
    this.win_x1 = 150;
    this.win_x2 = 310;
    this.win_y1 = 405;
    this.win_y2 = 460;
  },

  bindEvents: function(){
    $(document).on("keydown",this.keypress.bind(this));
    $(document).on("keyup",this.keyrelease.bind(this)); //event listener is keyup, calls our keyrelease function
    $(this.view.logInButtonSelector).on("click", this.logInButton.bind(this));
    $(this.view.startButtonSelector).on("click", this.startButton.bind(this));
    $(this.view.stopButtonSelector).on("click", this.stopButton.bind(this))
  },

  logInButton: function(e) {
    e.preventDefault();
     // this.view.logInButton();
     console.log("log in button function in controller")
     console.log(this.user)
     var logInUrl = $(this.view.logInButtonSelector).closest('form').attr("action");
     this.user.logIn(logInUrl);
       },

  keypress: function(e) {
    if(e.keyCode == 37) {
      this.rocket.moveLeft();
    }
    if(e.keyCode == 39) {
      this.rocket.moveRight();
    }
    if(e.keyCode == 38) {
      this.pressingUp = true; //if pressing up key, rocket accelerates up i.e. true
      this.rocket.moveUp();
    }
    if(e.keyCode == 40) {
      this.rocket.moveDown();
    }
    this.view.updateRocketPosition();
  },

  keyrelease: function(e) {
    if(e.keyCode == 38) {
      this.pressingUp = false;
    };
  },

  gameLoop: function(e) {
    this.gravity();
    this.checkLose();
    this.checkWin();
  },
  checkLose: function() {
    console.log("loser loser", this);
    console.log(this.rocket.y, this.lose_y, (this.rocket.y > this.lose_y))
    if(this.rocket.y > this.lose_y) {
      this.gameLost = true;
      this.endGame();
    }
  },
  checkWin: function() {
    console.log("winner winner", this);
    var check_x = (this.rocket.x > this.win_x1) && (this.rocket.x < this.win_x2);
    var check_y = (this.rocket.y > this.win_y1) && (this.rocket.y > this.win_y2);
    console.log(check_x, check_y, (check_x && check_y))
    if(check_x && check_y) {
      this.gameWon = true;
      this.endGame();
    }
  },
  endGame: function(){
    if(this.gameWon) {
      console.log("You won");
      this.user.points += 100;
      this.user.updatePoints();
      this.view.showWin();
      this.checkLevel();

      console.log(this.user.points);
    } else if(this.gameLost) {
      console.log("You lost");
      this.view.showLose();
    };
    clearInterval(this.interval);
    $(document).off();
    //$(document).off("keydown",this.keypress.bind(this));
    //$(document).off("keyup",this.keyrelease.bind(this));
  },
  gravity: function() {
    console.log("I'm free falling!", this);
    if(!this.pressingUp){
      this.rocket.moveDown(); //if keyup has happened, gravity moves it down
    };
    this.view.updateRocketPosition();
  },

  startButton: function(e) {
    this.view.startButton();
    this.interval = setInterval(this.gameLoop.bind(this),150);
  },
  stopButton: function(e) {
    if ( this.pause === false){
    this.rocket.resetLocation;
    clearInterval(this.interval);
    this.view.updateRocketPosition();
    this.pause = true;
     } else {
      this.interval = setInterval(this.gameLoop.bind(this),150);
      this.pause = false;
     }

  },

  checkLevel: function() {

  }

  // gameDone: function (e){
  //   $("keypress").unbind("keydown");
  // }
};

<|endoftext|>


<commit_before>/*
 * firefly.js
 * Copyright (C) 2016 thegrumpydictator@gmail.com
 *
 * This software may be modified and distributed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International License.
 *
 * See the LICENSE file for details.
 */
/** global: moment, accountingConfig, dateRangeConfig, accounting, currencySymbol, mon_decimal_point, frac_digits, showFullList, showOnlyTop, mon_thousands_sep */

$(function () {
    "use strict";

    configAccounting(currencySymbol);

    // on submit of form, disable any button in form:
    $('form.form-horizontal').on('submit',function() {
        $('button[type="submit"]').prop('disabled',true);
    });

    $.ajaxSetup({
                    headers: {
                        'X-CSRF-Token': $('meta[name="_token"]').attr('content')
                    }
                });

    // when you click on a currency, this happens:
    $('.currency-option').on('click', currencySelect);

    var ranges = {};
    ranges[dateRangeConfig.currentPeriod] = [moment(dateRangeConfig.ranges.current[0]), moment(dateRangeConfig.ranges.current[1])];
    ranges[dateRangeConfig.previousPeriod] = [moment(dateRangeConfig.ranges.previous[0]), moment(dateRangeConfig.ranges.previous[1])];
    ranges[dateRangeConfig.nextPeriod] = [moment(dateRangeConfig.ranges.next[0]), moment(dateRangeConfig.ranges.next[1])];

    // range for everything:
    ranges[dateRangeConfig.everything] = [dateRangeConfig.firstDate, moment()];

    // build the data range:
    $('#daterange').text(dateRangeConfig.linkTitle).daterangepicker(
        {
            ranges: ranges,
            opens: 'left',
            locale: {
                applyLabel: dateRangeConfig.applyLabel,
                cancelLabel: dateRangeConfig.cancelLabel,
                fromLabel: dateRangeConfig.fromLabel,
                toLabel: dateRangeConfig.toLabel,
                weekLabel: 'W',
                customRangeLabel: dateRangeConfig.customRangeLabel,
                daysOfWeek: moment.weekdaysMin(),
                monthNames: moment.monthsShort(),
                firstDay: moment.localeData()._week.dow
            },
            format: 'YYYY-MM-DD',
            startDate: dateRangeConfig.startDate,
            endDate: dateRangeConfig.endDate
        },
        function (start, end, label) {

            // send post.
            $.post(dateRangeConfig.URL, {
                start: start.format('YYYY-MM-DD'),
                end: end.format('YYYY-MM-DD'),
                label: label
            }).done(function () {
                window.location.reload(true);
            }).fail(function () {
                alert('Could not change date range');
            });
        }
    );

    // trigger list thing
    listLengthInitial();

});

function currencySelect(e) {
    "use strict";
    // clicked on
    var target = $(e.target); // target is the <A> tag.

    // name of the field in question:
    var name = target.data('name');

    // id of menu button (used later on):
    var menuID = 'currency_dropdown_' + name;

    // the hidden input with the actual value of the selected currency:
    var hiddenInputName = 'amount_currency_id_' + target.data('name');

    // span with the current selection (next to the caret):
    var spanId = 'currency_select_symbol_' + target.data('name');

    // the selected currency symbol:
    var symbol = target.data('symbol');

    // id of the selected currency.
    var id = target.data('id');

    // update the hidden input:
    $('input[name="' + hiddenInputName + '"]').val(id);

    // update the symbol:
    $('#' + spanId).text(symbol);

    // close the menu (hack hack)
    $('#' + menuID).dropdown('toggle');

    return false;
}

function configAccounting(customCurrency) {

// Settings object that controls default parameters for library methods:
    accounting.settings = {
        currency: {
            symbol: customCurrency,   // default currency symbol is '$'
            format: accountingConfig, // controls output: %s = symbol, %v = value/number (can be object: see below)
            decimal: mon_decimal_point,  // decimal point separator
            thousand: mon_thousands_sep,  // thousands separator
            precision: frac_digits   // decimal places
        },
        number: {
            precision: 0,  // default precision on numbers is 0
            thousand: ",",
            decimal: "."
        }
    };
}

function listLengthInitial() {
    "use strict";
    $('.overListLength').hide();
    $('.listLengthTrigger').unbind('click').click(triggerList)
}

function triggerList(e) {
    "use strict";
    var link = $(e.target);
    var table = link.parent().parent().parent().parent();
    if (table.attr('data-hidden') === 'no') {
        // hide all elements, return false.
        table.find('.overListLength').hide();
        table.attr('data-hidden', 'yes');
        link.text(showFullList);
        return false;
    }
    // show all, return false
    table.find('.overListLength').show();
    table.attr('data-hidden', 'no');
    link.text(showOnlyTop);

    return false;
}<commit_msg>Remove references to date range thing.<commit_after>/*
 * firefly.js
 * Copyright (C) 2016 thegrumpydictator@gmail.com
 *
 * This software may be modified and distributed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International License.
 *
 * See the LICENSE file for details.
 */
/** global: moment, accountingConfig, accounting, currencySymbol, mon_decimal_point, frac_digits, showFullList, showOnlyTop, mon_thousands_sep */

$(function () {
    "use strict";

    configAccounting(currencySymbol);

    // on submit of form, disable any button in form:
    $('form.form-horizontal').on('submit',function() {
        $('button[type="submit"]').prop('disabled',true);
    });

    $.ajaxSetup({
                    headers: {
                        'X-CSRF-Token': $('meta[name="_token"]').attr('content')
                    }
                });

    // when you click on a currency, this happens:
    $('.currency-option').on('click', currencySelect);

    // build the data range:
    $('#daterange').text(dateRangeConfig.linkTitle).daterangepicker(
        {
            ranges: ranges,
            opens: 'left',
            locale: {
                applyLabel: dateRangeConfig.applyLabel,
                cancelLabel: dateRangeConfig.cancelLabel,
                fromLabel: dateRangeConfig.fromLabel,
                toLabel: dateRangeConfig.toLabel,
                weekLabel: 'W',
                customRangeLabel: dateRangeConfig.customRangeLabel,
                daysOfWeek: moment.weekdaysMin(),
                monthNames: moment.monthsShort(),
                firstDay: moment.localeData()._week.dow
            },
            format: 'YYYY-MM-DD',
            startDate: dateRangeConfig.startDate,
            endDate: dateRangeConfig.endDate
        },
        function (start, end, label) {

            // send post.
            $.post(dateRangeConfig.URL, {
                start: start.format('YYYY-MM-DD'),
                end: end.format('YYYY-MM-DD'),
                label: label
            }).done(function () {
                window.location.reload(true);
            }).fail(function () {
                alert('Could not change date range');
            });
        }
    );

    // trigger list thing
    listLengthInitial();

});

function currencySelect(e) {
    "use strict";
    // clicked on
    var target = $(e.target); // target is the <A> tag.

    // name of the field in question:
    var name = target.data('name');

    // id of menu button (used later on):
    var menuID = 'currency_dropdown_' + name;

    // the hidden input with the actual value of the selected currency:
    var hiddenInputName = 'amount_currency_id_' + target.data('name');

    // span with the current selection (next to the caret):
    var spanId = 'currency_select_symbol_' + target.data('name');

    // the selected currency symbol:
    var symbol = target.data('symbol');

    // id of the selected currency.
    var id = target.data('id');

    // update the hidden input:
    $('input[name="' + hiddenInputName + '"]').val(id);

    // update the symbol:
    $('#' + spanId).text(symbol);

    // close the menu (hack hack)
    $('#' + menuID).dropdown('toggle');

    return false;
}

function configAccounting(customCurrency) {

// Settings object that controls default parameters for library methods:
    accounting.settings = {
        currency: {
            symbol: customCurrency,   // default currency symbol is '$'
            format: accountingConfig, // controls output: %s = symbol, %v = value/number (can be object: see below)
            decimal: mon_decimal_point,  // decimal point separator
            thousand: mon_thousands_sep,  // thousands separator
            precision: frac_digits   // decimal places
        },
        number: {
            precision: 0,  // default precision on numbers is 0
            thousand: ",",
            decimal: "."
        }
    };
}

function listLengthInitial() {
    "use strict";
    $('.overListLength').hide();
    $('.listLengthTrigger').unbind('click').click(triggerList)
}

function triggerList(e) {
    "use strict";
    var link = $(e.target);
    var table = link.parent().parent().parent().parent();
    if (table.attr('data-hidden') === 'no') {
        // hide all elements, return false.
        table.find('.overListLength').hide();
        table.attr('data-hidden', 'yes');
        link.text(showFullList);
        return false;
    }
    // show all, return false
    table.find('.overListLength').show();
    table.attr('data-hidden', 'no');
    link.text(showOnlyTop);

    return false;
}<|endoftext|>


<commit_before>$(document).ready(function() {
  var challengeName = typeof challengeName !== undefined ? challengeName : 'Untitled';
  if (challengeName) {
    ga('send', 'event',  'Challenge', 'load', challengeName);
  }

  $(document).ready(function() {
    if (typeof editor !== 'undefined') {
      $('#reset-button').on('click', resetEditor);
    }
  });

  var CSRF_HEADER = 'X-CSRF-Token';

  var setCSRFToken = function(securityToken) {
    jQuery.ajaxPrefilter(function(options, _, xhr) {
      if (!xhr.crossDomain) {
        xhr.setRequestHeader(CSRF_HEADER, securityToken);
      }
    });
  };

  setCSRFToken($('meta[name="csrf-token"]').attr('content'));

  $('.checklist-element').each(function() {
    var checklistElementId = $(this).attr('id');
    if(!!localStorage[checklistElementId]) {
      $(this).children().children('li').addClass('faded');
      $(this).children().children('input').trigger('click');
    }
  });

  $('.start-challenge').on('click', function() {
    $(this).parent().remove();
    $('.challenge-content')
      .removeClass('hidden-element')
      .addClass('animated fadeInDown');
  });

  $('.challenge-list-checkbox').on('change', function() {
    var checkboxId = $(this).parent().parent().attr('id');
    if ($(this).is(":checked")) {
      $(this).parent().siblings().children().addClass('faded');
      if (!localStorage || !localStorage[checkboxId]) {
        localStorage[checkboxId] = true;
      }
    }
    if (!$(this).is(":checked")) {
      $(this).parent().siblings().children().removeClass('faded');
      if (localStorage[checkboxId]) {
        localStorage.removeItem(checkboxId);
      }
    }
  });

  $("img").error(function () {
    $(this).unbind("error").attr("src", "https://s3.amazonaws.com/freecodecamp/camper-image-placeholder.png");
  });

  function reBindModals(){

      $('#i-want-help').unbind('click');
      $('#i-want-help').on('click', function() {
          $('#help-modal').modal('hide');
          var editorValue = editor.getValue();
          var currentLocation = window.location.href;
          $.post(
              '/get-help',
              {
                  payload: {
                      code: editorValue,
                      challenge: currentLocation
                  }
              },
              function(res) {
                  if (res) {
                      window.open('https://gitter.im/FreeCodeCamp/Help', '_blank')
                  }
              }
          );
      });

      $('#i-want-help-editorless').unbind('click');
      $('#i-want-help-editorless').on('click', function() {
          $('#help-editorless-modal').modal('hide');
          var currentLocation = window.location.href;
          $.post(
              '/get-help',
              {
                  payload: {
                      challenge: currentLocation
                  }
              },
              function(res) {
                  if (res) {
                      window.open('https://gitter.im/FreeCodeCamp/Help', '_blank')
                  }
              }
          );
      });

      $('#report-issue').unbind('click');
      $('#report-issue').on('click', function() {
          $('#issue-modal').modal('hide');
          window.open('https://github.com/freecodecamp/freecodecamp/issues/new?&body=Challenge '+ window.location.href +' has an issue. Please describe how to reproduce it, and include links to screenshots if possible.', '_blank')
      });

      $('#i-want-help').unbind('click');
      $('#i-want-to-pair').on('click', function() {
          $('#pair-modal').modal('hide');
          var currentLocation = window.location.href;
          $.post(
              '/get-pair',
              {
                  payload: {
                      challenge: currentLocation
                  }
              },
              function(res) {
                  if (res) {
                      window.open('https://gitter.im/FreeCodeCamp/LetsPair', '_blank')
                  }
              }
          );
      });

      $('#completed-courseware').unbind('click');
      $('#completed-courseware').on('click', function() {
          $('#complete-courseware-dialog').modal('show');
      });

      $('#completed-courseware-editorless').unbind('click');
      $('#completed-courseware-editorless').on('click', function() {
          $('#complete-courseware-editorless-dialog').modal('show');
      });

      $('#trigger-pair-modal').unbind('click');
      $('#trigger-pair-modal').on('click', function() {
          $('#pair-modal').modal('show');
      });

      $('#trigger-reset-modal').unbind('click');
      $('#trigger-reset-modal').on('click', function() {
          $('#reset-modal').modal('show');
      });

      $('#trigger-help-modal').unbind('click');
      $('#trigger-help-modal').on('click', function() {
          $('#help-modal').modal('show');
      });

      $('#trigger-issue-modal').unbind('click');
      $('#trigger-issue-modal').on('click', function() {
          $('#issue-modal').modal('show');
      });

      $('#completed-zipline-or-basejump').unbind('click');
      $('#completed-zipline-or-basejump').on('click', function() {
          $('#complete-zipline-or-basejump-dialog').modal('show');
      });

      $('#complete-courseware-dialog').on('hidden.bs.modal', function() {
          editor.focus();
      });

      $('#complete-zipline-or-basejump').on('hidden.bs.modal', function() {
          editor.focus();
      });
  };

    $(window).resize(function(){
        reBindModals();
    });

    reBindModals();

  var challengeTypes = {
    'HTML_CSS_JQ': '0',
    'JAVASCRIPT': '1',
    'VIDEO': '2',
    'ZIPLINE': '3',
    'BASEJUMP': '4',
    'BONFIRE': '5'
  };
  $('#next-courseware-button').on('click', function() {
    $('#next-courseware-button').unbind('click');
    if ($('.signup-btn-nav').length < 1) {
      switch (challengeType) {
        case challengeTypes.HTML_CSS_JQ:
        case challengeTypes.JAVASCRIPT:
        case challengeTypes.VIDEO:
          $.post(
            '/completed-challenge/',
            {
              challengeInfo: {
                challengeId: challenge_Id,
                challengeName: challenge_Name
              }
            }).success(
            function(res) {
              if (res) {
                window.location.href = '/challenges/next-challenge';
              }
            }).fail(
            function() {
              window.location.href="/challenges";
            }
          );
          break;
        case challengeTypes.ZIPLINE:
          var didCompleteWith = $('#completed-with').val() || null;
          var publicURL = $('#public-url').val() || null;
          $.post(
            '/completed-zipline-or-basejump/',
            {
              challengeInfo: {
                challengeId: challenge_Id,
                challengeName: challenge_Name,
                completedWith: didCompleteWith,
                publicURL: publicURL,
                challengeType: challengeType
              }
            }).success(
            function() {
              window.location.href = '/challenges/next-challenge';
            }).fail(
            function() {
              window.location.href = '/challenges';
            });
          break;
        case challengeTypes.BASEJUMP:
          var didCompleteWith = $('#completed-with').val() || null;
          var publicURL = $('#public-url').val() || null;
          var githubURL = $('#github-url').val() || null;
          $.post(
            '/completed-zipline-or-basejump/',
            {
              challengeInfo: {
                challengeId: challenge_Id,
                challengeName: challenge_Name,
                completedWith: didCompleteWith,
                publicURL: publicURL,
                githubURL: githubURL,
                challengeType: challengeType,
                verified: false
              }
            }).success(function() {
              window.location.href = '/challenges/next-challenge';
            }).fail(function() {
              window.location.replace(window.location.href);
            });
          break;
        case challengeTypes.BONFIRE:
          window.location.href = '/challenges/next-challenge';
        default:
          break;
      }
    }
  });

  $('.next-challenge-button').on('click', function() {
    l = location.pathname.split('/');
    window.location = '/challenges/' + (parseInt(l[l.length - 1]) + 1);
  });

  // Bonfire instructions functions
  $('#more-info').on('click', function() {
    ga('send', 'event',  'Challenge', 'more-info', challengeName);
    $('#brief-instructions').hide();
    $('#long-instructions').show().removeClass('hide');

  });
  $('#less-info').on('click', function() {
    $('#brief-instructions').show();
    $('#long-instructions').hide();
  });

  function upvoteHandler(e) {
    e.preventDefault();
    var upvoteBtn = this;
    var id = upvoteBtn.id;
    var upVotes = $(upvoteBtn).data().upVotes;
    var username = typeof username !== 'undefined' ? username : '';
    var alreadyUpvoted = false;
    for (var i = 0; i < upVotes.length; i++) {
      if (upVotes[i].upVotedBy === username) {
        alreadyUpvoted = true;
        break;
      }
    }
    if (!alreadyUpvoted) {
      $.post('/stories/upvote', { id: id })
        .fail(function(xhr, textStatus, errorThrown) {
          $(upvoteBtn).bind('click', upvoteHandler);
        })
        .done(function(data, textStatus, xhr) {
          $(upvoteBtn).text('Upvoted!').addClass('disabled');

          $('#storyRank').text(data.rank + " points");
        });
    }
  };
  $('#story-list').on('click', 'button.btn-upvote', upvoteHandler);

  var storySubmitButtonHandler = function storySubmitButtonHandler() {

    var link = $('#story-url').val();
    var headline = $('#story-title').val();
    var description = $('#description-box').val();

    $('#story-submit').unbind('click');
    $.post('/stories/',
      {
        data: {
          link: link,
          headline: headline,
          timePosted: Date.now(),
          description: description,
          storyMetaDescription: storyMetaDescription,
          rank: 1,
          image: storyImage
        }
      })
      .fail(function (xhr, textStatus, errorThrown) {
        $('#story-submit').bind('click', storySubmitButtonHandler);
      })
      .done(function(data, textStatus, xhr) {
        window.location = '/stories/' + data.storyLink;
      });
  };

  $('#story-submit').on('click', storySubmitButtonHandler);
    //fakeiphone positioning hotfix
    if($('.iphone-position').html() !==undefined || $('.iphone').html() !== undefined){
        var startIphonePosition = parseInt($('.iphone-position').css('top').replace('px', ''));
        var startIphone = parseInt($('.iphone').css('top').replace('px', ''));
        $(window).on('scroll', function(){
            if((($('.courseware-height').height() + $('.courseware-height').offset().top)-$(window).scrollTop()-$('.iphone-position').height()) <= 0){
                $('.iphone-position').css('top', startIphonePosition+(($('.courseware-height').height() + $('.courseware-height').offset().top)-$(window).scrollTop()-$('.iphone-position').height()));
                $('.iphone').css('top', startIphonePosition+(($('.courseware-height').height() + $('.courseware-height').offset().top)-$(window).scrollTop()-$('.iphone-position').height())+120);
            }
            else{
                $('.iphone-position').css('top', startIphonePosition);
                $('.iphone').css('top', startIphone);
            }
        });
    }
   if($('.scroll-locker').html() != undefined){
        function lockTop(){
            if ($(window).width() >= 990) {
                if($('.editorScrollDiv').html() !== 'undefined'){
                    var magiVal = $(window).height()-($('.navbar').height()+$('.footer').height());
                    if(magiVal < 0){
                        magiVal = 0;
                    }
                    $('.editorScrollDiv').css("height", (magiVal-85) + "px");
                }
                magiVal = $(window).height()-($('.navbar').height()+$('.footer').height());
                if(magiVal < 0){
                    magiVal = 0;
                }

                $('.scroll-locker').css("min-height", $('.editorScrollDiv').height()).css("height",magiVal-185);
            }
            else {
                $('.editorScrollDiv').css("max-height", 500 + "px");
                $('.scroll-locker').css('position', 'inherit').css('top', 'inherit').css('width', '100%').css('max-height', '85%');
            }
        }
        if ($('.scroll-locker').html()){
            lockTop();
            $(window).on('resize', function(){
              lockTop();
            });
            $(window).on('scroll', function() {
              lockTop();
            });
        }
    }
});

function defCheck(a){
    if(a !== 'undefined'){return(true);}else{return(false);}
}

var profileValidation = angular.module('profileValidation',
  ['ui.bootstrap']);
profileValidation.controller('profileValidationController', ['$scope', '$http',
  function($scope, $http) {
    $http.get('/account/api').success(function(data) {
      $scope.user = data.user;
      $scope.user.username = $scope.user.username ? $scope.user.username.toLowerCase() : undefined;
      $scope.storedUsername = data.user.username;
      $scope.storedEmail = data.user.email;
      $scope.user.email = $scope.user.email ? $scope.user.email.toLowerCase() : undefined;
      $scope.user.twitterHandle = $scope.user.twitterHandle ? $scope.user.twitterHandle.toLowerCase() : undefined;
      $scope.asyncComplete = true;
    });
  }
]);

profileValidation.controller('pairedWithController', ['$scope',
  function($scope) {
    $scope.existingUser = null;
  }
]);

profileValidation.controller('emailSignUpController', ['$scope',
  function($scope) {

  }
]);

profileValidation.controller('emailSignInController', ['$scope',
  function($scope) {

  }
]);

profileValidation.controller('URLSubmitController', ['$scope',
  function($scope) {

  }
]);

profileValidation.controller('nonprofitFormController', ['$scope',
  function($scope) {

  }
]);

profileValidation.controller('doneWithFirst100HoursFormController', ['$scope',
  function($scope) {

  }
]);

profileValidation.controller('submitStoryController', ['$scope',
  function($scope) {

  }
]);

profileValidation.directive('uniqueUsername', ['$http', function($http) {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function (scope, element, attrs, ngModel) {
      element.bind("keyup", function (event) {
        ngModel.$setValidity('unique', true);
        var username = element.val();
        if (username) {
          var config = { params: { username: username } };
          $http
            .get('/api/users/exists', config)
            .success(function (result) {
              if (username === scope.storedUsername) {
                ngModel.$setValidity('unique', true);
              } else if (result.exists) {
                ngModel.$setValidity('unique', false);
              }
            });
        }
      });
    }
  };
}]);

profileValidation.directive('existingUsername',
  ['$http', function($http) {
    return {
      restrict: 'A',
      require: 'ngModel',
      link: function (scope, element, attrs, ngModel) {
        element.bind('keyup', function (event) {
          if (element.val().length > 0) {
            ngModel.$setValidity('exists', false);
          } else {
            element.removeClass('ng-dirty');
            ngModel.$setPristine();
          }
          var username = element.val();
          if (username) {
            var config = { params: { username: username } };
            $http
              .get('/api/users/exists', config)
              .success(function(result) {
                ngModel.$setValidity('exists', result.exists);
              });
          }
        });
      }
    };
  }]);

profileValidation.directive('uniqueEmail', ['$http', function($http) {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function getUnique (scope, element, attrs, ngModel) {
      element.bind("keyup", function (event) {
        ngModel.$setValidity('unique', true);
        var email = element.val();
        if (email) {
          var config = { params: { email: email } };
          $http
            .get('/api/users/exists', config)
            .success(function(result) {
              if (email === scope.storedEmail) {
                ngModel.$setValidity('unique', true);
              } else if (result.exists) {
                ngModel.$setValidity('unique', false);
              }
            });
        };
      });
    }
  }
}]);
<commit_msg>Revert "Revert "attempt to fix challenge submit part two""<commit_after>$(document).ready(function() {
  var challengeName = typeof challengeName !== undefined ? challengeName : 'Untitled';
  if (challengeName) {
    ga('send', 'event',  'Challenge', 'load', challengeName);
  }

  $(document).ready(function() {
    if (typeof editor !== 'undefined') {
      $('#reset-button').on('click', resetEditor);
    }
  });

  var CSRF_HEADER = 'X-CSRF-Token';

  var setCSRFToken = function(securityToken) {
    jQuery.ajaxPrefilter(function(options, _, xhr) {
      if (!xhr.crossDomain) {
        xhr.setRequestHeader(CSRF_HEADER, securityToken);
      }
    });
  };

  setCSRFToken($('meta[name="csrf-token"]').attr('content'));

  $('.checklist-element').each(function() {
    var checklistElementId = $(this).attr('id');
    if(!!localStorage[checklistElementId]) {
      $(this).children().children('li').addClass('faded');
      $(this).children().children('input').trigger('click');
    }
  });

  $('.start-challenge').on('click', function() {
    $(this).parent().remove();
    $('.challenge-content')
      .removeClass('hidden-element')
      .addClass('animated fadeInDown');
  });

  $('.challenge-list-checkbox').on('change', function() {
    var checkboxId = $(this).parent().parent().attr('id');
    if ($(this).is(":checked")) {
      $(this).parent().siblings().children().addClass('faded');
      if (!localStorage || !localStorage[checkboxId]) {
        localStorage[checkboxId] = true;
      }
    }
    if (!$(this).is(":checked")) {
      $(this).parent().siblings().children().removeClass('faded');
      if (localStorage[checkboxId]) {
        localStorage.removeItem(checkboxId);
      }
    }
  });

  $("img").error(function () {
    $(this).unbind("error").attr("src", "https://s3.amazonaws.com/freecodecamp/camper-image-placeholder.png");
  });

  function reBindModals(){

      $('#i-want-help').unbind('click');
      $('#i-want-help').on('click', function() {
          $('#help-modal').modal('hide');
          var editorValue = editor.getValue();
          var currentLocation = window.location.href;
          $.post(
              '/get-help',
              {
                  payload: {
                      code: editorValue,
                      challenge: currentLocation
                  }
              },
              function(res) {
                  if (res) {
                      window.open('https://gitter.im/FreeCodeCamp/Help', '_blank')
                  }
              }
          );
      });

      $('#i-want-help-editorless').unbind('click');
      $('#i-want-help-editorless').on('click', function() {
          $('#help-editorless-modal').modal('hide');
          var currentLocation = window.location.href;
          $.post(
              '/get-help',
              {
                  payload: {
                      challenge: currentLocation
                  }
              },
              function(res) {
                  if (res) {
                      window.open('https://gitter.im/FreeCodeCamp/Help', '_blank')
                  }
              }
          );
      });

      $('#report-issue').unbind('click');
      $('#report-issue').on('click', function() {
          $('#issue-modal').modal('hide');
          window.open('https://github.com/freecodecamp/freecodecamp/issues/new?&body=Challenge '+ window.location.href +' has an issue. Please describe how to reproduce it, and include links to screenshots if possible.', '_blank')
      });

      $('#i-want-help').unbind('click');
      $('#i-want-to-pair').on('click', function() {
          $('#pair-modal').modal('hide');
          var currentLocation = window.location.href;
          $.post(
              '/get-pair',
              {
                  payload: {
                      challenge: currentLocation
                  }
              },
              function(res) {
                  if (res) {
                      window.open('https://gitter.im/FreeCodeCamp/LetsPair', '_blank')
                  }
              }
          );
      });

      $('#completed-courseware').unbind('click');
      $('#completed-courseware').on('click', function() {
          $('#complete-courseware-dialog').modal('show');
      });

      $('#completed-courseware-editorless').unbind('click');
      $('#completed-courseware-editorless').on('click', function() {
          $('#complete-courseware-editorless-dialog').modal('show');
      });

      $('#trigger-pair-modal').unbind('click');
      $('#trigger-pair-modal').on('click', function() {
          $('#pair-modal').modal('show');
      });

      $('#trigger-reset-modal').unbind('click');
      $('#trigger-reset-modal').on('click', function() {
          $('#reset-modal').modal('show');
      });

      $('#trigger-help-modal').unbind('click');
      $('#trigger-help-modal').on('click', function() {
          $('#help-modal').modal('show');
      });

      $('#trigger-issue-modal').unbind('click');
      $('#trigger-issue-modal').on('click', function() {
          $('#issue-modal').modal('show');
      });

      $('#completed-zipline-or-basejump').unbind('click');
      $('#completed-zipline-or-basejump').on('click', function() {
          $('#complete-zipline-or-basejump-dialog').modal('show');
      });

      $('#next-courseware-button').unbind('click');
      $('#next-courseware-button').on('click', function() {
          $('#next-courseware-button').unbind('click');
          if ($('.signup-btn-nav').length < 1) {
              switch (challengeType) {
                  case challengeTypes.HTML_CSS_JQ:
                  case challengeTypes.JAVASCRIPT:
                  case challengeTypes.VIDEO:
                      $.post(
                          '/completed-challenge/',
                          {
                              challengeInfo: {
                                  challengeId: challenge_Id,
                                  challengeName: challenge_Name
                              }
                          }).success(
                          function(res) {
                              if (res) {
                                  window.location.href = '/challenges/next-challenge';
                              }
                          }).fail(
                          function() {
                              window.location.href="/challenges";
                          }
                      );
                      break;
                  case challengeTypes.ZIPLINE:
                      var didCompleteWith = $('#completed-with').val() || null;
                      var publicURL = $('#public-url').val() || null;
                      $.post(
                          '/completed-zipline-or-basejump/',
                          {
                              challengeInfo: {
                                  challengeId: challenge_Id,
                                  challengeName: challenge_Name,
                                  completedWith: didCompleteWith,
                                  publicURL: publicURL,
                                  challengeType: challengeType
                              }
                          }).success(
                          function() {
                              window.location.href = '/challenges/next-challenge';
                          }).fail(
                          function() {
                              window.location.href = '/challenges';
                          });
                      break;
                  case challengeTypes.BASEJUMP:
                      var didCompleteWith = $('#completed-with').val() || null;
                      var publicURL = $('#public-url').val() || null;
                      var githubURL = $('#github-url').val() || null;
                      $.post(
                          '/completed-zipline-or-basejump/',
                          {
                              challengeInfo: {
                                  challengeId: challenge_Id,
                                  challengeName: challenge_Name,
                                  completedWith: didCompleteWith,
                                  publicURL: publicURL,
                                  githubURL: githubURL,
                                  challengeType: challengeType,
                                  verified: false
                              }
                          }).success(function() {
                              window.location.href = '/challenges/next-challenge';
                          }).fail(function() {
                              window.location.replace(window.location.href);
                          });
                      break;
                  case challengeTypes.BONFIRE:
                      window.location.href = '/challenges/next-challenge';
                  default:
                      break;
              }
          }
      });

      $('.next-challenge-button').unbind('click');
      $('.next-challenge-button').on('click', function() {
          l = location.pathname.split('/');
          window.location = '/challenges/' + (parseInt(l[l.length - 1]) + 1);
      });

      // Bonfire instructions functions
      $('#more-info').unbind('click');
      $('#more-info').on('click', function() {
          ga('send', 'event',  'Challenge', 'more-info', challengeName);
          $('#brief-instructions').hide();
          $('#long-instructions').show().removeClass('hide');

      });
      $('#less-info').unbind('click');
      $('#less-info').on('click', function() {
          $('#brief-instructions').show();
          $('#long-instructions').hide();
      });

      $('#complete-courseware-dialog').on('hidden.bs.modal', function() {
          editor.focus();
      });

      $('#complete-zipline-or-basejump').on('hidden.bs.modal', function() {
          editor.focus();
      });
  };

    $(window).resize(function(){
        reBindModals();
    });

    reBindModals();

  var challengeTypes = {
    'HTML_CSS_JQ': '0',
    'JAVASCRIPT': '1',
    'VIDEO': '2',
    'ZIPLINE': '3',
    'BASEJUMP': '4',
    'BONFIRE': '5'
  };

  function upvoteHandler(e) {
    e.preventDefault();
    var upvoteBtn = this;
    var id = upvoteBtn.id;
    var upVotes = $(upvoteBtn).data().upVotes;
    var username = typeof username !== 'undefined' ? username : '';
    var alreadyUpvoted = false;
    for (var i = 0; i < upVotes.length; i++) {
      if (upVotes[i].upVotedBy === username) {
        alreadyUpvoted = true;
        break;
      }
    }
    if (!alreadyUpvoted) {
      $.post('/stories/upvote', { id: id })
        .fail(function(xhr, textStatus, errorThrown) {
          $(upvoteBtn).bind('click', upvoteHandler);
        })
        .done(function(data, textStatus, xhr) {
          $(upvoteBtn).text('Upvoted!').addClass('disabled');

          $('#storyRank').text(data.rank + " points");
        });
    }
  };
  $('#story-list').on('click', 'button.btn-upvote', upvoteHandler);

  var storySubmitButtonHandler = function storySubmitButtonHandler() {

    var link = $('#story-url').val();
    var headline = $('#story-title').val();
    var description = $('#description-box').val();

    $('#story-submit').unbind('click');
    $.post('/stories/',
      {
        data: {
          link: link,
          headline: headline,
          timePosted: Date.now(),
          description: description,
          storyMetaDescription: storyMetaDescription,
          rank: 1,
          image: storyImage
        }
      })
      .fail(function (xhr, textStatus, errorThrown) {
        $('#story-submit').bind('click', storySubmitButtonHandler);
      })
      .done(function(data, textStatus, xhr) {
        window.location = '/stories/' + data.storyLink;
      });
  };

  $('#story-submit').on('click', storySubmitButtonHandler);
    //fakeiphone positioning hotfix
    if($('.iphone-position').html() !==undefined || $('.iphone').html() !== undefined){
        var startIphonePosition = parseInt($('.iphone-position').css('top').replace('px', ''));
        var startIphone = parseInt($('.iphone').css('top').replace('px', ''));
        $(window).on('scroll', function(){
            if((($('.courseware-height').height() + $('.courseware-height').offset().top)-$(window).scrollTop()-$('.iphone-position').height()) <= 0){
                $('.iphone-position').css('top', startIphonePosition+(($('.courseware-height').height() + $('.courseware-height').offset().top)-$(window).scrollTop()-$('.iphone-position').height()));
                $('.iphone').css('top', startIphonePosition+(($('.courseware-height').height() + $('.courseware-height').offset().top)-$(window).scrollTop()-$('.iphone-position').height())+120);
            }
            else{
                $('.iphone-position').css('top', startIphonePosition);
                $('.iphone').css('top', startIphone);
            }
        });
    }
   if($('.scroll-locker').html() != undefined){
        function lockTop(){
            if ($(window).width() >= 990) {
                if($('.editorScrollDiv').html() !== 'undefined'){
                    var magiVal = $(window).height()-($('.navbar').height()+$('.footer').height());
                    if(magiVal < 0){
                        magiVal = 0;
                    }
                    $('.editorScrollDiv').css("height", (magiVal-85) + "px");
                }
                magiVal = $(window).height()-($('.navbar').height()+$('.footer').height());
                if(magiVal < 0){
                    magiVal = 0;
                }

                $('.scroll-locker').css("min-height", $('.editorScrollDiv').height()).css("height",magiVal-185);
            }
            else {
                $('.editorScrollDiv').css("max-height", 500 + "px");
                $('.scroll-locker').css('position', 'inherit').css('top', 'inherit').css('width', '100%').css('max-height', '85%');
            }
        }
        if ($('.scroll-locker').html()){
            lockTop();
            $(window).on('resize', function(){
              lockTop();
            });
            $(window).on('scroll', function() {
              lockTop();
            });
        }
    }
});

function defCheck(a){
    if(a !== 'undefined'){return(true);}else{return(false);}
}

var profileValidation = angular.module('profileValidation',
  ['ui.bootstrap']);
profileValidation.controller('profileValidationController', ['$scope', '$http',
  function($scope, $http) {
    $http.get('/account/api').success(function(data) {
      $scope.user = data.user;
      $scope.user.username = $scope.user.username ? $scope.user.username.toLowerCase() : undefined;
      $scope.storedUsername = data.user.username;
      $scope.storedEmail = data.user.email;
      $scope.user.email = $scope.user.email ? $scope.user.email.toLowerCase() : undefined;
      $scope.user.twitterHandle = $scope.user.twitterHandle ? $scope.user.twitterHandle.toLowerCase() : undefined;
      $scope.asyncComplete = true;
    });
  }
]);

profileValidation.controller('pairedWithController', ['$scope',
  function($scope) {
    $scope.existingUser = null;
  }
]);

profileValidation.controller('emailSignUpController', ['$scope',
  function($scope) {

  }
]);

profileValidation.controller('emailSignInController', ['$scope',
  function($scope) {

  }
]);

profileValidation.controller('URLSubmitController', ['$scope',
  function($scope) {

  }
]);

profileValidation.controller('nonprofitFormController', ['$scope',
  function($scope) {

  }
]);

profileValidation.controller('doneWithFirst100HoursFormController', ['$scope',
  function($scope) {

  }
]);

profileValidation.controller('submitStoryController', ['$scope',
  function($scope) {

  }
]);

profileValidation.directive('uniqueUsername', ['$http', function($http) {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function (scope, element, attrs, ngModel) {
      element.bind("keyup", function (event) {
        ngModel.$setValidity('unique', true);
        var username = element.val();
        if (username) {
          var config = { params: { username: username } };
          $http
            .get('/api/users/exists', config)
            .success(function (result) {
              if (username === scope.storedUsername) {
                ngModel.$setValidity('unique', true);
              } else if (result.exists) {
                ngModel.$setValidity('unique', false);
              }
            });
        }
      });
    }
  };
}]);

profileValidation.directive('existingUsername',
  ['$http', function($http) {
    return {
      restrict: 'A',
      require: 'ngModel',
      link: function (scope, element, attrs, ngModel) {
        element.bind('keyup', function (event) {
          if (element.val().length > 0) {
            ngModel.$setValidity('exists', false);
          } else {
            element.removeClass('ng-dirty');
            ngModel.$setPristine();
          }
          var username = element.val();
          if (username) {
            var config = { params: { username: username } };
            $http
              .get('/api/users/exists', config)
              .success(function(result) {
                ngModel.$setValidity('exists', result.exists);
              });
          }
        });
      }
    };
  }]);

profileValidation.directive('uniqueEmail', ['$http', function($http) {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function getUnique (scope, element, attrs, ngModel) {
      element.bind("keyup", function (event) {
        ngModel.$setValidity('unique', true);
        var email = element.val();
        if (email) {
          var config = { params: { email: email } };
          $http
            .get('/api/users/exists', config)
            .success(function(result) {
              if (email === scope.storedEmail) {
                ngModel.$setValidity('unique', true);
              } else if (result.exists) {
                ngModel.$setValidity('unique', false);
              }
            });
        };
      });
    }
  }
}]);
<|endoftext|>


<commit_before>(function($) {
    "use strict";

    var isFullscreen = false,
        $el,
        $wrapper,
        $editor,
        $index = -1,
        $icon,
        $overlay,
        transitionDuration = 300,
        settings = {
            overlay: true,
            maxWidth: '',
            maxHeight: ''
        };
    var methods = {

        init: function(opts) {

            settings = settings || {};
            $.extend(true, settings, settings);
            $.extend(true, settings, opts);
            $index++;
            $el = $(this);
            var id = $(this).attr('id');
            console.log(id);
            var content =
                '

';
            var $wrapper = $(content).insertAfter(this);
            $editor = $editor || [];
            $editor.push($wrapper.find('#tx-editor'+ id));
            $icon = $editor[$index].find('#tx-icon' + id);
            $editor[$index].append($el);

            $el.css({
                'width': '100%',
                'height': '100%',
				'resize': 'none'
            });

            // ESC = closes the fullscreen mode
            $(window).on("keyup.txeditor", function(e) {
                if (e.keyCode == 27) {
                    isFullscreen ? methods.minimize() : '';
                }
            });

            // fullscreen icon click event
            $icon.on('click.txeditor.icon', function(e) {
                console.log(this);
                var index = $(this).attr('index');
                e.preventDefault();
                methods[isFullscreen ? "minimize" : "expand"](index);
            });
            return this;
        },

        showOverlay: function() {
            $('
').appendTo('body')
                .fadeTo(0, 1)
                .click(function() {
                    methods.minimize();
                });
            return this;
        },

        removeOverlay: function() {
            var $overlay = $('.tx-editor-overlay');
            if ($overlay.length) {
                $overlay.fadeTo(0, 0, function() {
                    $(this).remove();
                });
            }
            return this;
        },

        expand: function(i) {
            settings.maxWidth ? $editor.css('max-width', settings.maxWidth) :
                '';
            settings.maxHeight ? $editor.css('max-height', settings.maxHeight) :
                '';
            if (settings.overlay) {
                methods.showOverlay();
            }

            $(window).on('resize.txeditor', function() {
                relocate($editor);
            });

            $editor[i].addClass('expanded');
            transitions(i);

            return this;
        },

        minimize: function(i) {

            $(window).off('resize.txeditor', relocate($editor[i]))
            $editor[i].removeClass('expanded')
                .css({
                    'max-width': 'none',
                    'max-height': 'none'
                });
            if (settings.overlay) {
                methods.removeOverlay();
            }
            transitions(i);

            return this;
        },

        destroy: function() {

            methods.removeOverlay();
            $wrapper.insertBefore($el);
            $wrapper.remove();

            $(window).off('keyup.txeditor')
                .off('resize.txeditor');

            return this;
        },
    };

    var transitions = function (i) {
			relocate($editor[i]);
            if (isFullscreen) {
				$el.focus();
				isFullscreen = false;
            } else {
				$el.focus();
				$editor[i].css('opacity', 1);
				isFullscreen = true;
            }

            return;
    };

    function relocate(el) {

        var yPos = 0 | ((($(window).height() - el.height()) / 2));
        var xPos = 0 | (($(window).width() - el.width()) / 2);
        el.css({
            'top': yPos,
            'left': xPos
        });

    }

    $.fn.textareafullscreen = function(method) {
        $.extend(methods, transitions);
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(
                arguments, 1));
        } else if (typeof method === 'object' || !method) {
            return methods.init.apply(this, arguments);
        } else {
            $.error('Method ' + method +
                ' does not exist on jQuery.textareafullscreen');
        }
    };

})(jQuery);
<commit_msg>complete ESC func<commit_after>(function($) {
    "use strict";

    var isFullscreen = false,
        $el,
        $wrapper,
        $editor,
        $index = -1,
        $current = 0,
        $icon,
        $overlay,
        settings = {
            overlay: true,
            maxWidth: '',
            maxHeight: ''
        };
    var methods = {
        init: function(opts) {
            settings = settings || {};
            $.extend(true, settings, settings);
            $.extend(true, settings, opts);
            $index++;
            $el = $(this);
            var id = $(this).attr('id');
            var content =
                '

';
            var $wrapper = $(content).insertAfter(this);
            $editor = $editor || [];
            $editor.push($wrapper.find('#tx-editor'+ id));
            $icon = $editor[$index].find('#tx-icon' + id);
            $editor[$index].append($el);

            $el.css({
                'width': '100%',
                'height': '100%',
				'resize': 'none'
            });

            // ESC 关闭全屏
            $(window).on("keyup.txeditor", function(e) {
                if (e.keyCode == 27) {
                    isFullscreen ? methods.minimize($current) : '';
                }
            });

            // fullscreen icon click event
            $icon.on('click.txeditor.icon', function(e) {
                var index = $(this).attr('index');
                e.preventDefault();
                methods[isFullscreen ? "minimize" : "expand"](index);
            });
            return this;
        },

        showOverlay: function() {
            $('
').appendTo('body')
                .fadeTo(0, 1)
                .click(function() {
                    methods.minimize();
                });
            return this;
        },

        removeOverlay: function() {
            var $overlay = $('.tx-editor-overlay');
            if ($overlay.length) {
                $overlay.fadeTo(0, 0, function() {
                    $(this).remove();
                });
            }
            return this;
        },

        expand: function(i) {
            $current = i;
            settings.maxWidth ? $editor.css('max-width', settings.maxWidth) :
                '';
            settings.maxHeight ? $editor.css('max-height', settings.maxHeight) :
                '';
            if (settings.overlay) {
                methods.showOverlay();
            }

            $(window).on('resize.txeditor', function() {
                relocate($editor);
            });

            $editor[i].addClass('expanded');
            transitions(i);

            return this;
        },

        minimize: function(i) {

            $(window).off('resize.txeditor', relocate($editor[i]))
            $editor[i].removeClass('expanded')
                .css({
                    'max-width': 'none',
                    'max-height': 'none'
                });
            if (settings.overlay) {
                methods.removeOverlay();
            }
            transitions(i);

            return this;
        },

        destroy: function() {

            methods.removeOverlay();
            $wrapper.insertBefore($el);
            $wrapper.remove();

            $(window).off('keyup.txeditor')
                .off('resize.txeditor');

            return this;
        },
    };

    var transitions = function (i) {
			relocate($editor[i]);
            if (isFullscreen) {
				$el.focus();
				isFullscreen = false;
            } else {
				$el.focus();
				$editor[i].css('opacity', 1);
				isFullscreen = true;
            }

            return;
    };

    function relocate(el) {

        var yPos = 0 | ((($(window).height() - el.height()) / 2));
        var xPos = 0 | (($(window).width() - el.width()) / 2);
        el.css({
            'top': yPos,
            'left': xPos
        });

    }

    $.fn.textareafullscreen = function(method) {
        $.extend(methods, transitions);
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(
                arguments, 1));
        } else if (typeof method === 'object' || !method) {
            return methods.init.apply(this, arguments);
        } else {
            $.error('Method ' + method +
                ' does not exist on jQuery.textareafullscreen');
        }
    };

})(jQuery);
<|endoftext|>