<commit_before>import React, { Component } from 'react'
import {
  StyleSheet,
  View,
  Linking,
  ActivityIndicator,
} from 'react-native'
import Button from 'react-native-button'
import { responsiveFontSize } from 'react-native-responsive-dimensions'
import SafariView from 'react-native-safari-view'
import { Navigation } from 'react-native-navigation'

class Login extends Component {
  constructor(props) {
    super(props)
    this.state = {
      loading: false,
      authUrl: '',
    }
    this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this))
    this._handleOpenURL = this._handleOpenURL.bind(this)
    this._connectToPocket = this._connectToPocket.bind(this)
  }

  componentDidMount() {
    // After authorization, Pocket site will redirect with the custom URL Scheme.
    // Linking receives the event and pass the process to handler.
    Linking.addEventListener('url', this._handleOpenURL)
  }

  _handleOpenURL(event) {
    // No longer listen to Linking event.
    Linking.removeEventListener('url', this._handleOpenURL)
    // Pass the process to action.
    this.props.actions.doAfterRedirect(event.url)
  }

  onNavigatorEvent(event) {
    // After this modal has disappeared, open Pocket auth page.
    switch(event.id) {
      case 'willDisappear':
        this._safari(this.state.authUrl)
        break
    }
  }

  _safari(authUrl) {
    console.tron.tmp('authUrl', authUrl)
    SafariView.isAvailable()
      .then(SafariView.show({
        url: authUrl
      }))
      .catch(err => {
        // Fallback WebView code for iOS 8 and earlier
        console.tron.error(err)
      });
  }

  async _connectToPocket() {
    this.setState({ loading: true })
    const authUrl = await this.props.actions.getPocketAuthUrl()
    this.setState({ authUrl })
    // Trigger NavigatorEvent.
    // because SafariView is not working on Modal.
    Navigation.dismissAllModals({
      animationType: 'slide-down'
    })
  }

  render() {
    const { actions } = this.props
    const indicator = this.state.loading ? <ActivityIndicator /> : null
    return (
      <View style={styles.container}>
        <Button
          onPress={this._connectToPocket}
          style={styles.btn}
          disabled={this.state.loading}
        >
          Connect to Pocket
        </Button>
        { indicator }
     </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'stretch',
    backgroundColor: '#F5FCFF',
  },
  btn: {
    padding: 10,
    fontSize: responsiveFontSize(3),
  },
})

import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import * as allActions from '../actions/allActions'

export default connect(
  (state) => ({
  }),
  (dispatch) => ({
    actions: bindActionCreators(allActions, dispatch),
  })
)(Login)
<commit_msg>:+1: Login screen appears from bottom<commit_after>import React, { Component } from 'react'
import {
  StyleSheet,
  View,
  Linking,
  ActivityIndicator,
} from 'react-native'
import Button from 'react-native-button'
import { responsiveFontSize } from 'react-native-responsive-dimensions'
import SafariView from 'react-native-safari-view'
import { Navigation } from 'react-native-navigation'

class Login extends Component {
  constructor(props) {
    super(props)
    this.state = {
      loading: false,
      authUrl: '',
    }
    this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this))
    this._handleOpenURL = this._handleOpenURL.bind(this)
    this._connectToPocket = this._connectToPocket.bind(this)
  }

  componentDidMount() {
    // After authorization, Pocket site will redirect with the custom URL Scheme.
    // Linking receives the event and pass the process to handler.
    Linking.addEventListener('url', this._handleOpenURL)
  }

  _handleOpenURL(event) {
    // No longer listen to Linking event.
    Linking.removeEventListener('url', this._handleOpenURL)
    // Pass the process to action.
    this.props.actions.doAfterRedirect(event.url)
  }

  onNavigatorEvent(event) {
    // After this modal has disappeared, open Pocket auth page.
    switch(event.id) {
      case 'willDisappear':
        this._safari(this.state.authUrl)
        break
    }
  }

  _safari(authUrl) {
    console.tron.tmp('authUrl', authUrl)
    SafariView.isAvailable()
      .then(SafariView.show({
        url: authUrl,
        fromBottom: true
      }))
      .catch(err => {
        // Fallback WebView code for iOS 8 and earlier
        console.tron.error(err)
      });
  }

  async _connectToPocket() {
    this.setState({ loading: true })
    const authUrl = await this.props.actions.getPocketAuthUrl()
    this.setState({ authUrl })
    // Trigger NavigatorEvent.
    // because SafariView is not working on Modal.
    Navigation.dismissAllModals({
      animationType: 'slide-down'
    })
  }

  render() {
    const { actions } = this.props
    const indicator = this.state.loading ? <ActivityIndicator /> : null
    return (
      <View style={styles.container}>
        <Button
          onPress={this._connectToPocket}
          style={styles.btn}
          disabled={this.state.loading}
        >
          Connect to Pocket
        </Button>
        { indicator }
     </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'stretch',
    backgroundColor: '#F5FCFF',
  },
  btn: {
    padding: 10,
    fontSize: responsiveFontSize(3),
  },
})

import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import * as allActions from '../actions/allActions'

export default connect(
  (state) => ({
  }),
  (dispatch) => ({
    actions: bindActionCreators(allActions, dispatch),
  })
)(Login)
<|endoftext|>


<commit_before>/** section: wysihat
 *  class WysiHat.AdvancedToolbar
**/
WysiHat.AdvancedToolbar = Class.create((function() {
  /**
   *  new WysiHat.AdvancedToolbar(editor)
   *  - editor (WysiHat.Editor): the editor object that you want to attach to
   *
   *  Creates a toolbar element above the editor. The WysiHat.AdvancedToolbar object
   *  has many helper methods to easily add buttons to the toolbar.
   *
   *  This toolbar class is not required for the Editor object to function.
   *  It is merely a set of helper methods to get you started and to build
   *  on top of. If you are going to use this class in your application,
   *  it is highly recommended that you subclass it and override methods
   *  to add custom functionality.
  **/
  function initialize(editor) {
    this.editor = editor;
    this.element = this.createToolbarElement();
  }

  /**
   *  WysiHat.AdvancedToolbar#createToolbarElement() -> Element
   *
   *  Creates a toolbar container element and inserts it right above the
   *  original textarea element. The element is a div with the class
   *  'editor_toolbar'.
   *
   *  You can override this method to customize the element attributes and
   *  insert position. Be sure to return the element after it has been
   *  inserted.
  **/
  function createToolbarElement() {
    var toolbar = new Element('div', { 'class': 'editor_toolbar' });
    this.editor.insert({before: toolbar});
    return toolbar;
  }

  /**
   *  WysiHat.AdvancedToolbar#addButtonSet(set) -> undefined
   *  - set (Array): The set array contains nested arrays that hold the
   *  button options, and handler.
   *
   *  Adds a button set to the toolbar.
  **/
  function addButtonSet(set) {
    var toolbar = this;
    $A(set).each(function(button){
      toolbar.addButton(button);
    });
  }

  /**
   *  WysiHat.AdvancedToolbar#addButton(options[, handler]) -> undefined
   *  - options (Hash): Required options hash
   *  - handler (Function): Function to bind to the button
   *
   *  The options hash accepts two required keys, name and label. The label
   *  value is used as the link's inner text. The name value is set to the
   *  link's class and is used to check the button state. However the name
   *  may be omitted if the name and label are the same. In that case, the
   *  label will be down cased to make the name value. So a "Bold" label
   *  will default to "bold" name.
   *
   *  The second optional handler argument will be used if no handler
   *  function is supplied in the options hash.
   *
   *  toolbar.addButton({
   *    name: 'bold', label: "Bold" }, function(editor) {
   *      editor.boldSelection();
   *  });
   *
   *  Would create a link,
   *  "Bold"
  **/
  function addButton(options, handler) {
    options = $H(options);

    if (!options.get('name'))
      options.set('name', options.get('label').toLowerCase());
    var name = options.get('name');

    var button = this.createButtonElement(this.element, options);

    var handler = this.buttonHandler(name, options);
    this.observeButtonClick(button, handler);

    var handler = this.buttonStateHandler(name, options);
    this.observeStateChanges(button, name, handler);
  }

  /**
   *  WysiHat.AdvancedToolbar#addSelectbox(options[, handler]) -> undefined
   *  - options (Hash): Required options hash
   *  - handler (Function): Function to bind to the options
   *
   *  The options hash accepts two required keys, name and options. The name
   *  value is set to the selectboxes' class. The options array will be used
   *  as the options for the selectbox.
   *
   *  The second optional handler argument will be used if no handler
   *  function is supplied in the options hash.
   *
   *  toolbar.addSelectbox({
   *    name: 'fontname',
   *    options: [
   *      'Times',
   *      'Georgia',
   *      'Arial'
   *    ]
   *  })
   *
   *  Would create a selectbox,
   *  "<select class="fontname">
   *    <option id="times">Times</option>
   *    <option id="georgia">Georgia</option>
   *    <option id="arial">Arial</option>
   *  </select>"
  **/
  function addSelectbox(options, handler) {
    options = $H(options);

    var name = options.get('name');

    var selectbox = this.createSelectboxElement(this.element, options) ;

    var handler = this.selectboxHandler(name, options);
    this.observeOptionSelect(selectbox, handler);

    var handler = this.selectboxStateHandler(name, options);
    this.observeStateChangesSelectbox(handler);
  }

  /**
   *  WysiHat.AdvancedToolbar#createButtonElement(toolbar, options) -> Element
   *  - toolbar (Element): Toolbar element created by createToolbarElement
   *  - options (Hash): Options hash that pass from addButton
   *
   *  Creates individual button elements and inserts them into the toolbar
   *  container. The default elements are 'a' tags with a 'button' class.
   *
   *  You can override this method to customize the element attributes and
   *  insert positions. Be sure to return the element after it has been
   *  inserted.
  **/
  function createButtonElement(toolbar, options) {
    var button = new Element('a', {
      'class': 'button', 'href': '#'
    });
    button.update('' + options.get('label') + '');
    button.addClassName(options.get('name'));

    toolbar.appendChild(button);

    return button;
  }

  /**
   *  WysiHat.AdvancedToolbar#createSelectboxElement(toolbar, options) -> Element
   *  - toolbar (Element): Toolbar element created by createToolbarElement
   *  - options (Hash): Options hash that pass from addButton
   *
   *  Creates a selectbox element and inserts it into the toolbar container.
  **/
  function createSelectboxElement(toolbar, options) {
    var selectbox = Element('select', {
      'class': options.get('name')
    });
    options.get('options').each(function(option){
      element = Element('option', {
        'id' : option.toLowerCase()
      });
      element.update(option);
      selectbox.appendChild(element);
    });

    toolbar.appendChild(selectbox);

    return selectbox;
  }

  /**
   *  WysiHat.AdvancedToolbar#buttonHandler(name, options) -> Function
   *  - name (String): Name of button command: 'bold', 'italic'
   *  - options (Hash): Options hash that pass from addButton
   *
   *  Returns the button handler function to bind to the buttons onclick
   *  event. It checks the options for a 'handler' attribute otherwise it
   *  defaults to a function that calls execCommand with the button name.
  **/
  function buttonHandler(name, options) {
    if (options.handler)
      return options.handler;
    else if (options.get('handler'))
      return options.get('handler');
    else
      return function(editor) { editor.execCommand(name); };
  }

  /**
   *  WysiHat.AdvancedToolbar#selectboxHandler(name, options) -> Function
   *  - name (String): Name of select command: 'fontname', 'fontsize'
   *  - options (Hash): Options hash that pass from addButton
   *
   *  Returns the selectbox button handler function to bind to the selectboxes'
   *  onchange event. It checks the options for a 'handler' attribute
   *  otherwise it defaults to a function that calls execCommand with the
   *  selectboxes' name and the option value.
  **/
  function selectboxHandler(name, options) {
    if (options.handler)
      return options.handler;
    else if (options.get('handler'))
      return options.get('handler');
    else
      var handlers = {};
      options.get('options').each(function(option){
        var handler = function(editor) { editor.execCommand(name, false, option); };
        handlers[option] = handler;
      });
      return handlers;
  }

  /**
   *  WysiHat.AdvancedToolbar#observeButtonClick(element, handler) -> undefined
   *  - element (Element): Button element
   *  - handler (Function): Handler function to bind to element
   *
   *  Bind handler to elements onclick event.
  **/
  function observeButtonClick(element, handler) {
    var toolbar = this;
    element.observe('click', function(event) {
      handler(toolbar.editor);
      toolbar.editor.fire("wysihat:change");
      toolbar.editor.fire("wysihat:cursormove");
      Event.stop(event);
    });
  }

  /**
   *  WysiHat.AdvancedToolbar#observeOptionSelect(element, handler) -> undefined
   *  - element (Element): Selectbox option element
   *  - handler (Function): Handler function to bind to element
   *
   *  Bind handler to selectboxes' onchange event.
  **/
  function observeOptionSelect(element, handler) {
    var toolbar = this;
    element.observe('change', function(event) {
      handler[element.value](toolbar.editor);
      toolbar.editor.fire("wysihat:change");
      toolbar.editor.fire("wysihat:cursormove");
      Event.stop(event);
    });
  }

  /**
   *  WysiHat.AdvancedToolbar#buttonStateHandler(name, options) -> Function
   *  - name (String): Name of button command: 'bold', 'italic'
   *  - options (Hash): Options hash that pass from addButton
   *
   *  Returns the button handler function that checks whether the button
   *  state is on (true) or off (false). It checks the options for a
   *  'query' attribute otherwise it defaults to a function that calls
   *  queryCommandState with the button name.
  **/
  function buttonStateHandler(name, options) {
    if (options.query)
      return options.query;
    else if (options.get('query'))
      return options.get('query');
    else
      return function(editor) { return editor.queryCommandState(name); };
  }

  /**
   *  WysiHat.AdvancedToolbar#selectboxStateHandler(name, options) -> Function
   *  - name (String): Name of select command: 'fontname', 'fontsize'
   *  - options (Hash): Options hash that pass from addButton
   *
   *  Returns the selectbox option handler function that checks which
   *  value is currently selected. It checks the options for a 'query'
   *  attribute otherwise it defaults to a function that calls
   * queryCommandState with the selectbox option's name.
  **/
  function selectboxStateHandler(name, options) {
    if (options.query)
      return options.query;
    else if (options.get('query'))
      return options.get('query');
    else
      return function(editor) { return editor.getSelectedStyles().get(name); }
  }

  /**
   *  WysiHat.AdvancedToolbar#observeStateChanges(element, name, handler) -> undefined
   *  - element (Element): Button element
   *  - name (String): Button name
   *  - handler (Function): State query function
   *
   *  Determines buttons state by calling the query handler function then
   *  calls updateButtonState.
  **/
  function observeStateChanges(element, name, handler) {
    var toolbar = this;
    var previousState = false;
    toolbar.editor.observe("wysihat:cursormove", function(event) {
      var state = handler(toolbar.editor);
      if (state != previousState) {
        previousState = state;
        toolbar.updateButtonState(element, name, state);
      }
    });
  }

  /**
   *  WysiHat.AdvancedToolbar#observeStateChangesSelectbox(handler) -> undefined
   *  - handler (Function): State query function
   *
   *  Determines selectboxes' state by calling the query handler function then
   *  calls updateSelectboxState.
  **/
  function observeStateChangesSelectbox(handler) {
    var toolbar = this;
    var previousState = false;
    toolbar.editor.observe("wysihat:cursormove", function(event) {
      var state = handler(toolbar.editor);
      if (state != previousState) {
        previousState = state;
        toolbar.updateSelectboxState(state);
      }
    });
  }

  /**
   *  WysiHat.AdvancedToolbar#updateButtonState(element, name, state) -> undefined
   *  - element (Element): Button element
   *  - name (String): Button name
   *  - state (Boolean): Whether button state is on/off
   *
   *  If the state is on, it adds a 'selected' class to the button element.
   *  Otherwise it removes the 'selected' class.
   *
   *  You can override this method to change the class name or styles
   *  applied to buttons when their state changes.
  **/
  function updateButtonState(element, name, state) {
    if (state)
      element.addClassName('selected');
    else
      element.removeClassName('selected');
  }

  /**
   *  WysiHat.AdvancedToolbar#updateSelectboxState(state) -> undefined
   *  - state (Boolean): The value of the selectboxes' state
   *
   *  Selects option for the current state.
  **/
  function updateSelectboxState(state) {
    $(state.toLowerCase()).selected = true;
  }

  return {
    initialize:                   initialize,
    createToolbarElement:         createToolbarElement,
    addButtonSet:                 addButtonSet,
    addButton:                    addButton,
    addSelectbox:                 addSelectbox,
    createButtonElement:          createButtonElement,
    createSelectboxElement:       createSelectboxElement,
    buttonHandler:                buttonHandler,
    selectboxHandler:             selectboxHandler,
    observeButtonClick:           observeButtonClick,
    observeOptionSelect:          observeOptionSelect,
    buttonStateHandler:           buttonStateHandler,
    observeStateChanges:          observeStateChanges,
    updateButtonState:            updateButtonState,
    updateSelectboxState:         updateSelectboxState,
    selectboxStateHandler:        selectboxStateHandler,
    observeStateChangesSelectbox: observeStateChangesSelectbox
  };
})());

//= require "advanced_toolbar/button_sets"
<commit_msg>added missing semicolon JSLint is happy again now.<commit_after>/** section: wysihat
 *  class WysiHat.AdvancedToolbar
**/
WysiHat.AdvancedToolbar = Class.create((function() {
  /**
   *  new WysiHat.AdvancedToolbar(editor)
   *  - editor (WysiHat.Editor): the editor object that you want to attach to
   *
   *  Creates a toolbar element above the editor. The WysiHat.AdvancedToolbar object
   *  has many helper methods to easily add buttons to the toolbar.
   *
   *  This toolbar class is not required for the Editor object to function.
   *  It is merely a set of helper methods to get you started and to build
   *  on top of. If you are going to use this class in your application,
   *  it is highly recommended that you subclass it and override methods
   *  to add custom functionality.
  **/
  function initialize(editor) {
    this.editor = editor;
    this.element = this.createToolbarElement();
  }

  /**
   *  WysiHat.AdvancedToolbar#createToolbarElement() -> Element
   *
   *  Creates a toolbar container element and inserts it right above the
   *  original textarea element. The element is a div with the class
   *  'editor_toolbar'.
   *
   *  You can override this method to customize the element attributes and
   *  insert position. Be sure to return the element after it has been
   *  inserted.
  **/
  function createToolbarElement() {
    var toolbar = new Element('div', { 'class': 'editor_toolbar' });
    this.editor.insert({before: toolbar});
    return toolbar;
  }

  /**
   *  WysiHat.AdvancedToolbar#addButtonSet(set) -> undefined
   *  - set (Array): The set array contains nested arrays that hold the
   *  button options, and handler.
   *
   *  Adds a button set to the toolbar.
  **/
  function addButtonSet(set) {
    var toolbar = this;
    $A(set).each(function(button){
      toolbar.addButton(button);
    });
  }

  /**
   *  WysiHat.AdvancedToolbar#addButton(options[, handler]) -> undefined
   *  - options (Hash): Required options hash
   *  - handler (Function): Function to bind to the button
   *
   *  The options hash accepts two required keys, name and label. The label
   *  value is used as the link's inner text. The name value is set to the
   *  link's class and is used to check the button state. However the name
   *  may be omitted if the name and label are the same. In that case, the
   *  label will be down cased to make the name value. So a "Bold" label
   *  will default to "bold" name.
   *
   *  The second optional handler argument will be used if no handler
   *  function is supplied in the options hash.
   *
   *  toolbar.addButton({
   *    name: 'bold', label: "Bold" }, function(editor) {
   *      editor.boldSelection();
   *  });
   *
   *  Would create a link,
   *  "Bold"
  **/
  function addButton(options, handler) {
    options = $H(options);

    if (!options.get('name'))
      options.set('name', options.get('label').toLowerCase());
    var name = options.get('name');

    var button = this.createButtonElement(this.element, options);

    var handler = this.buttonHandler(name, options);
    this.observeButtonClick(button, handler);

    var handler = this.buttonStateHandler(name, options);
    this.observeStateChanges(button, name, handler);
  }

  /**
   *  WysiHat.AdvancedToolbar#addSelectbox(options[, handler]) -> undefined
   *  - options (Hash): Required options hash
   *  - handler (Function): Function to bind to the options
   *
   *  The options hash accepts two required keys, name and options. The name
   *  value is set to the selectboxes' class. The options array will be used
   *  as the options for the selectbox.
   *
   *  The second optional handler argument will be used if no handler
   *  function is supplied in the options hash.
   *
   *  toolbar.addSelectbox({
   *    name: 'fontname',
   *    options: [
   *      'Times',
   *      'Georgia',
   *      'Arial'
   *    ]
   *  })
   *
   *  Would create a selectbox,
   *  "<select class="fontname">
   *    <option id="times">Times</option>
   *    <option id="georgia">Georgia</option>
   *    <option id="arial">Arial</option>
   *  </select>"
  **/
  function addSelectbox(options, handler) {
    options = $H(options);

    var name = options.get('name');

    var selectbox = this.createSelectboxElement(this.element, options) ;

    var handler = this.selectboxHandler(name, options);
    this.observeOptionSelect(selectbox, handler);

    var handler = this.selectboxStateHandler(name, options);
    this.observeStateChangesSelectbox(handler);
  }

  /**
   *  WysiHat.AdvancedToolbar#createButtonElement(toolbar, options) -> Element
   *  - toolbar (Element): Toolbar element created by createToolbarElement
   *  - options (Hash): Options hash that pass from addButton
   *
   *  Creates individual button elements and inserts them into the toolbar
   *  container. The default elements are 'a' tags with a 'button' class.
   *
   *  You can override this method to customize the element attributes and
   *  insert positions. Be sure to return the element after it has been
   *  inserted.
  **/
  function createButtonElement(toolbar, options) {
    var button = new Element('a', {
      'class': 'button', 'href': '#'
    });
    button.update('' + options.get('label') + '');
    button.addClassName(options.get('name'));

    toolbar.appendChild(button);

    return button;
  }

  /**
   *  WysiHat.AdvancedToolbar#createSelectboxElement(toolbar, options) -> Element
   *  - toolbar (Element): Toolbar element created by createToolbarElement
   *  - options (Hash): Options hash that pass from addButton
   *
   *  Creates a selectbox element and inserts it into the toolbar container.
  **/
  function createSelectboxElement(toolbar, options) {
    var selectbox = Element('select', {
      'class': options.get('name')
    });
    options.get('options').each(function(option){
      element = Element('option', {
        'id' : option.toLowerCase()
      });
      element.update(option);
      selectbox.appendChild(element);
    });

    toolbar.appendChild(selectbox);

    return selectbox;
  }

  /**
   *  WysiHat.AdvancedToolbar#buttonHandler(name, options) -> Function
   *  - name (String): Name of button command: 'bold', 'italic'
   *  - options (Hash): Options hash that pass from addButton
   *
   *  Returns the button handler function to bind to the buttons onclick
   *  event. It checks the options for a 'handler' attribute otherwise it
   *  defaults to a function that calls execCommand with the button name.
  **/
  function buttonHandler(name, options) {
    if (options.handler)
      return options.handler;
    else if (options.get('handler'))
      return options.get('handler');
    else
      return function(editor) { editor.execCommand(name); };
  }

  /**
   *  WysiHat.AdvancedToolbar#selectboxHandler(name, options) -> Function
   *  - name (String): Name of select command: 'fontname', 'fontsize'
   *  - options (Hash): Options hash that pass from addButton
   *
   *  Returns the selectbox button handler function to bind to the selectboxes'
   *  onchange event. It checks the options for a 'handler' attribute
   *  otherwise it defaults to a function that calls execCommand with the
   *  selectboxes' name and the option value.
  **/
  function selectboxHandler(name, options) {
    if (options.handler)
      return options.handler;
    else if (options.get('handler'))
      return options.get('handler');
    else
      var handlers = {};
      options.get('options').each(function(option){
        var handler = function(editor) { editor.execCommand(name, false, option); };
        handlers[option] = handler;
      });
      return handlers;
  }

  /**
   *  WysiHat.AdvancedToolbar#observeButtonClick(element, handler) -> undefined
   *  - element (Element): Button element
   *  - handler (Function): Handler function to bind to element
   *
   *  Bind handler to elements onclick event.
  **/
  function observeButtonClick(element, handler) {
    var toolbar = this;
    element.observe('click', function(event) {
      handler(toolbar.editor);
      toolbar.editor.fire("wysihat:change");
      toolbar.editor.fire("wysihat:cursormove");
      Event.stop(event);
    });
  }

  /**
   *  WysiHat.AdvancedToolbar#observeOptionSelect(element, handler) -> undefined
   *  - element (Element): Selectbox option element
   *  - handler (Function): Handler function to bind to element
   *
   *  Bind handler to selectboxes' onchange event.
  **/
  function observeOptionSelect(element, handler) {
    var toolbar = this;
    element.observe('change', function(event) {
      handler[element.value](toolbar.editor);
      toolbar.editor.fire("wysihat:change");
      toolbar.editor.fire("wysihat:cursormove");
      Event.stop(event);
    });
  }

  /**
   *  WysiHat.AdvancedToolbar#buttonStateHandler(name, options) -> Function
   *  - name (String): Name of button command: 'bold', 'italic'
   *  - options (Hash): Options hash that pass from addButton
   *
   *  Returns the button handler function that checks whether the button
   *  state is on (true) or off (false). It checks the options for a
   *  'query' attribute otherwise it defaults to a function that calls
   *  queryCommandState with the button name.
  **/
  function buttonStateHandler(name, options) {
    if (options.query)
      return options.query;
    else if (options.get('query'))
      return options.get('query');
    else
      return function(editor) { return editor.queryCommandState(name); };
  }

  /**
   *  WysiHat.AdvancedToolbar#selectboxStateHandler(name, options) -> Function
   *  - name (String): Name of select command: 'fontname', 'fontsize'
   *  - options (Hash): Options hash that pass from addButton
   *
   *  Returns the selectbox option handler function that checks which
   *  value is currently selected. It checks the options for a 'query'
   *  attribute otherwise it defaults to a function that calls
   * queryCommandState with the selectbox option's name.
  **/
  function selectboxStateHandler(name, options) {
    if (options.query)
      return options.query;
    else if (options.get('query'))
      return options.get('query');
    else
      return function(editor) { return editor.getSelectedStyles().get(name); };
  }

  /**
   *  WysiHat.AdvancedToolbar#observeStateChanges(element, name, handler) -> undefined
   *  - element (Element): Button element
   *  - name (String): Button name
   *  - handler (Function): State query function
   *
   *  Determines buttons state by calling the query handler function then
   *  calls updateButtonState.
  **/
  function observeStateChanges(element, name, handler) {
    var toolbar = this;
    var previousState = false;
    toolbar.editor.observe("wysihat:cursormove", function(event) {
      var state = handler(toolbar.editor);
      if (state != previousState) {
        previousState = state;
        toolbar.updateButtonState(element, name, state);
      }
    });
  }

  /**
   *  WysiHat.AdvancedToolbar#observeStateChangesSelectbox(handler) -> undefined
   *  - handler (Function): State query function
   *
   *  Determines selectboxes' state by calling the query handler function then
   *  calls updateSelectboxState.
  **/
  function observeStateChangesSelectbox(handler) {
    var toolbar = this;
    var previousState = false;
    toolbar.editor.observe("wysihat:cursormove", function(event) {
      var state = handler(toolbar.editor);
      if (state != previousState) {
        previousState = state;
        toolbar.updateSelectboxState(state);
      }
    });
  }

  /**
   *  WysiHat.AdvancedToolbar#updateButtonState(element, name, state) -> undefined
   *  - element (Element): Button element
   *  - name (String): Button name
   *  - state (Boolean): Whether button state is on/off
   *
   *  If the state is on, it adds a 'selected' class to the button element.
   *  Otherwise it removes the 'selected' class.
   *
   *  You can override this method to change the class name or styles
   *  applied to buttons when their state changes.
  **/
  function updateButtonState(element, name, state) {
    if (state)
      element.addClassName('selected');
    else
      element.removeClassName('selected');
  }

  /**
   *  WysiHat.AdvancedToolbar#updateSelectboxState(state) -> undefined
   *  - state (Boolean): The value of the selectboxes' state
   *
   *  Selects option for the current state.
  **/
  function updateSelectboxState(state) {
    $(state.toLowerCase()).selected = true;
  }

  return {
    initialize:                   initialize,
    createToolbarElement:         createToolbarElement,
    addButtonSet:                 addButtonSet,
    addButton:                    addButton,
    addSelectbox:                 addSelectbox,
    createButtonElement:          createButtonElement,
    createSelectboxElement:       createSelectboxElement,
    buttonHandler:                buttonHandler,
    selectboxHandler:             selectboxHandler,
    observeButtonClick:           observeButtonClick,
    observeOptionSelect:          observeOptionSelect,
    buttonStateHandler:           buttonStateHandler,
    observeStateChanges:          observeStateChanges,
    updateButtonState:            updateButtonState,
    updateSelectboxState:         updateSelectboxState,
    selectboxStateHandler:        selectboxStateHandler,
    observeStateChangesSelectbox: observeStateChangesSelectbox
  };
})());

//= require "advanced_toolbar/button_sets"
<|endoftext|>


<commit_before>/*
 * fuel
 * https://github.com/ExactTarget/node-fuel
 *
 * Copyright (c) 2013 ExactTarget
 * Licensed under the MIT license.
 */

var request = require('request');

function fuel(options, callback) {

	fuel.token(options, function (error, response, body) {
		if (error) {
			callback(error);
		} else {
			options.json = true;
			options.headers = options.headers || {};
			options.headers.authorization = 'Bearer ' + body.accessToken;

			fuel._performRequest(options, callback);
		}
	});
}

fuel.token = function (options, callback) {

	if (!fuel._validateOptions(options, callback)) return;

	var authOptions = {
		url: options.authUrl,
		method: 'POST',
		json: true,
		body: {
			clientId: options.clientId,
			clientSecret: options.clientSecret
		}
	};

	if (options.accessType) authOptions.body.accessType = options.accessType;
	if (options.refreshToken) authOptions.body.refreshToken = options.refreshToken;
	if (options.scope) authOptions.body.scope = options.scope;

	var authOptionsHash = fuel._authOptionsHash(authOptions);

	if (fuel._refreshTokenCache[authOptionsHash]) {
		authOptions.body.refreshToken = fuel._refreshTokenCache[authOptionsHash];
	}

	fuel._performTokenRequest(authOptions, function (error, response, body) {
		if (error) {
			callback(error);
		} else {
			if (body.refreshToken) {
				fuel._refreshTokenCache[authOptionsHash] = body.refreshToken;
			}
			callback(error, response, body);
		}
	});
};

fuel.configure = createConfigurationWrapper(fuel);
fuel.token.configure = createConfigurationWrapper(fuel.token);

fuel._validateOptions = function (options, callback) {
	var message = null;

	// When validating, handle the negations first
	if (options == null) {
		message = 'options object is required';
	} else if (!options.authUrl) {
		message = 'authUrl is required';
	} else if (!options.clientId || !fuel._verifyAPIKey('clientId', options.clientId)) {
		message = 'clientId is missing or invalid';
	} else if (!options.clientSecret || !fuel._verifyAPIKey('clientSecret', options.clientSecret)) {
		message = 'clientSecret is missing or invalid';
	}

	// Something is wrong, notifiy the user
	if (null !== message) {
		callback(new Error(message));
		return false;
	} else {
		// Should only be here if all is well
		return true;
	}
};

fuel._verifyAPIKey = function (APIKeyType, key) {
	var check = false;
	var idPattern = /^[a-z0-9]{24}$/;
	var secretPattern = /^[a-zA-Z0-9]{24}$/;

	if ('clientId' === APIKeyType) {
		check = idPattern.test(key);
	} else if ('clientSecret' === APIKeyType) {
		check = secretPattern.test(key);
	}

	return check;
};

fuel._removeAuthOptions = function (options) {
	options = deepExtend({}, options);
	delete options.clientId;
	delete options.clientSecret;
	delete options.refreshToken;
	delete options.accessType;
	delete options.authUrl;
	delete options.scope;
	return options;
};

fuel._performRequest = function (options, callback) {
	return request(fuel._removeAuthOptions(options), callback);
};

fuel._performTokenRequest = memoize(fuel._performRequest, function (options) {
	// Cache response per unique set of options
	return fuel._authOptionsHash(options);
}, function (error, response, body) {
	// Cache errors for 10 seconds, tokens until 30 seconds before expiration
	return (error) ? 10000 : (body.expiresIn - 30) * 1000;
});

fuel._authOptionsHash = function (options) {
	return options.url + options.body.clientId + options.body.scope;
};

fuel._refreshTokenCache = {};

module.exports = fuel;

// Utility

function deepExtend(dest, source) {
	for (var prop in source) {
		if (Object.prototype.toString.call(source[prop]) === "[object Array]") {
			dest[prop] = dest[prop] || [];
			source[prop].forEach(function (value, index) {
				if (typeof value === 'object') {
					dest[prop][index] = deepExtend({}, value);
				} else {
					dest[prop][index] = value;
				}
			});
		} else if (typeof source[prop] === 'object' && source[prop] !== null) {
			dest[prop] = dest[prop] || {};
			deepExtend(dest[prop], source[prop]);
		} else {
			dest[prop] = source[prop];
		}
	}
	return dest;
}

function createConfigurationWrapper(func) {
	return function (storedOptions) {
		return function (options, callback) {
			if (!callback) {
				callback = options;
				options = {};
			}
			return func(deepExtend(deepExtend({}, storedOptions), options), callback);
		};
	};
}

function memoize(fn, hasher, invalidator) {
	var memo = {};
	var queues = {};
	hasher = hasher || function (x) {
		return x;
	};
	invalidator = invalidator || function () {};
	var memoized = function () {
		var args = Array.prototype.slice.call(arguments);
		var callback = args.pop();
		var key = hasher.apply(null, args);
		if (key in memo) {
			callback.apply(null, memo[key]);
		}
		else if (key in queues) {
			queues[key].push(callback);
		}
		else {
			queues[key] = [callback];
			fn.apply(null, args.concat([function () {
				var timeout = invalidator.apply(null, arguments);
				if (timeout) {
					setTimeout(function () {
						delete memo[key];
					}, timeout);
				}
				memo[key] = arguments;
				var q = queues[key];
				delete queues[key];
				for (var i = 0, l = q.length; i < l; i++) {
					q[i].apply(null, arguments);
				}
			}]));
		}
	};
	memoized.unmemoized = fn;
	return memoized;
}
<commit_msg>Prevent timer from holding program open<commit_after>/*
 * fuel
 * https://github.com/ExactTarget/node-fuel
 *
 * Copyright (c) 2013 ExactTarget
 * Licensed under the MIT license.
 */

var request = require('request');

function fuel(options, callback) {

	fuel.token(options, function (error, response, body) {
		if (error) {
			callback(error);
		} else {
			options.json = true;
			options.headers = options.headers || {};
			options.headers.authorization = 'Bearer ' + body.accessToken;

			fuel._performRequest(options, callback);
		}
	});
}

fuel.token = function (options, callback) {

	if (!fuel._validateOptions(options, callback)) return;

	var authOptions = {
		url: options.authUrl,
		method: 'POST',
		json: true,
		body: {
			clientId: options.clientId,
			clientSecret: options.clientSecret
		}
	};

	if (options.accessType) authOptions.body.accessType = options.accessType;
	if (options.refreshToken) authOptions.body.refreshToken = options.refreshToken;
	if (options.scope) authOptions.body.scope = options.scope;

	var authOptionsHash = fuel._authOptionsHash(authOptions);

	if (fuel._refreshTokenCache[authOptionsHash]) {
		authOptions.body.refreshToken = fuel._refreshTokenCache[authOptionsHash];
	}

	fuel._performTokenRequest(authOptions, function (error, response, body) {
		if (error) {
			callback(error);
		} else {
			if (body.refreshToken) {
				fuel._refreshTokenCache[authOptionsHash] = body.refreshToken;
			}
			callback(error, response, body);
		}
	});
};

fuel.configure = createConfigurationWrapper(fuel);
fuel.token.configure = createConfigurationWrapper(fuel.token);

fuel._validateOptions = function (options, callback) {
	var message = null;

	// When validating, handle the negations first
	if (options == null) {
		message = 'options object is required';
	} else if (!options.authUrl) {
		message = 'authUrl is required';
	} else if (!options.clientId || !fuel._verifyAPIKey('clientId', options.clientId)) {
		message = 'clientId is missing or invalid';
	} else if (!options.clientSecret || !fuel._verifyAPIKey('clientSecret', options.clientSecret)) {
		message = 'clientSecret is missing or invalid';
	}

	// Something is wrong, notifiy the user
	if (null !== message) {
		callback(new Error(message));
		return false;
	} else {
		// Should only be here if all is well
		return true;
	}
};

fuel._verifyAPIKey = function (APIKeyType, key) {
	var check = false;
	var idPattern = /^[a-z0-9]{24}$/;
	var secretPattern = /^[a-zA-Z0-9]{24}$/;

	if ('clientId' === APIKeyType) {
		check = idPattern.test(key);
	} else if ('clientSecret' === APIKeyType) {
		check = secretPattern.test(key);
	}

	return check;
};

fuel._removeAuthOptions = function (options) {
	options = deepExtend({}, options);
	delete options.clientId;
	delete options.clientSecret;
	delete options.refreshToken;
	delete options.accessType;
	delete options.authUrl;
	delete options.scope;
	return options;
};

fuel._performRequest = function (options, callback) {
	return request(fuel._removeAuthOptions(options), callback);
};

fuel._performTokenRequest = memoize(fuel._performRequest, function (options) {
	// Cache response per unique set of options
	return fuel._authOptionsHash(options);
}, function (error, response, body) {
	// Cache errors for 10 seconds, tokens until 30 seconds before expiration
	return (error) ? 10000 : (body.expiresIn - 30) * 1000;
});

fuel._authOptionsHash = function (options) {
	return options.url + options.body.clientId + options.body.scope;
};

fuel._refreshTokenCache = {};

module.exports = fuel;

// Utility

function deepExtend(dest, source) {
	for (var prop in source) {
		if (Object.prototype.toString.call(source[prop]) === "[object Array]") {
			dest[prop] = dest[prop] || [];
			source[prop].forEach(function (value, index) {
				if (typeof value === 'object') {
					dest[prop][index] = deepExtend({}, value);
				} else {
					dest[prop][index] = value;
				}
			});
		} else if (typeof source[prop] === 'object' && source[prop] !== null) {
			dest[prop] = dest[prop] || {};
			deepExtend(dest[prop], source[prop]);
		} else {
			dest[prop] = source[prop];
		}
	}
	return dest;
}

function createConfigurationWrapper(func) {
	return function (storedOptions) {
		return function (options, callback) {
			if (!callback) {
				callback = options;
				options = {};
			}
			return func(deepExtend(deepExtend({}, storedOptions), options), callback);
		};
	};
}

function memoize(fn, hasher, invalidator) {
	var memo = {};
	var queues = {};
	hasher = hasher || function (x) {
		return x;
	};
	invalidator = invalidator || function () {};
	var memoized = function () {
		var args = Array.prototype.slice.call(arguments);
		var callback = args.pop();
		var key = hasher.apply(null, args);
		if (key in memo) {
			callback.apply(null, memo[key]);
		}
		else if (key in queues) {
			queues[key].push(callback);
		}
		else {
			queues[key] = [callback];
			fn.apply(null, args.concat([function () {
				var timeout = invalidator.apply(null, arguments);
				if (timeout) {
					setTimeout(function () {
						delete memo[key];
					}, timeout).unref();
				}
				memo[key] = arguments;
				var q = queues[key];
				delete queues[key];
				for (var i = 0, l = q.length; i < l; i++) {
					q[i].apply(null, arguments);
				}
			}]));
		}
	};
	memoized.unmemoized = fn;
	return memoized;
}
<|endoftext|>


<commit_before>var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors');
var request = require('request');
var events = require('events');
var fh = require('fh-mbaas-api');
var _ = require('underscore');

var fuseRoute = function() {
  var fuse = new express.Router();
  fuse.use(cors());
  fuse.use(bodyParser());

  fuse.post('/', function(req, res) {
    console.log(new Date(), 'In fuse route POST / req.body=', req.body);
    return submitToFuse(req.body, function(error, response, body){
      return res.send(body);
    });
  });

  return fuse;
};

var submitToFuse = function(submission, cb){
  var data = transform(submission);
  var url = process.env.FUSE_URL || 'http://85.190.180.161:8182/cxf/redhat/forum/register';
  var options = { "url" : url, "body": data, "json": true};
  request.post(options, function (error, response, body) {
    if (!error && response.statusCode == 200) {
      console.log("Well done!") // Show the HTML
    }
    cb(error, response, body);
  });
};

var mapping = {
  "FFIRSTNAME" : "name",
  "FLASTNAME" : "lastName",
  "FEMAIL" : "email",
  "FPICTURE" : "picture",
  "FCOMPANY" : "companyName",
  "FTITLE" : "jobTitle",
  "FWEB" : "web"
};

var transform = function(submission) {
  var map = { "register" : { } };
  _.each(submission.submission.formFields, function(item){
    //console.log(JSON.stringify(item));
    map.register[mapping[item.fieldId.fieldCode]] = item.fieldValues[0];
  });
  console.log(JSON.stringify(map));
  return map;
}

var submissionEventListener = new events.EventEmitter();

submissionEventListener.on('submissionComplete', function(submission){
  console.log('New submission received: ');
  //console.log(submission);
  return submitToFuse(submission, function(error, response, body){
      console.log('Received response from Fuse in event handler: ' + response.statusCode);
      console.log(body);
  });
});

fh.forms.registerListener(submissionEventListener, function(err){});

module.exports = fuseRoute;<commit_msg>update file /lib/fuse.js<commit_after>var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors');
var request = require('request');
var events = require('events');
var fh = require('fh-mbaas-api');
var _ = require('underscore');

var fuseRoute = function() {
  var fuse = new express.Router();
  fuse.use(cors());
  fuse.use(bodyParser());

  fuse.post('/', function(req, res) {
    console.log(new Date(), 'In fuse route POST / req.body=', req.body);
    return submitToFuse(req.body, function(error, response, body){
      return res.send(body);
    });
  });

  return fuse;
};

var submitToFuse = function(submission, cb){
  var data = transform(submission);
  var url = process.env.FUSE_URL || 'http://85.190.180.161:8182/cxf/redhat/forum/register';
  var options = { "url" : url, "body": data, "json": true};
  request.post(options, function (error, response, body) {
    if (!error && response.statusCode == 200) {
      console.log("Well done!") // Show the HTML
    }
    cb(error, response, body);
  });
};

var mapping = {
  "FFIRSTNAME" : "name",
  "FLASTNAME" : "lastName",
  "FEMAIL" : "email",
  "FPICTURE" : "picture",
  "FCOMPANY" : "companyName",
  "FTITLE" : "jobTitle",
  "FWEB" : "web"
};

var transform = function(submission) {
  var map = {};
  _.each(submission.submission.formFields, function(item){
    //console.log(JSON.stringify(item));
    map[mapping[item.fieldId.fieldCode]] = item.fieldValues[0];
  });
  console.log(JSON.stringify(map));
  return map;
}

var submissionEventListener = new events.EventEmitter();

submissionEventListener.on('submissionComplete', function(submission){
  console.log('New submission received: ');
  //console.log(submission);
  return submitToFuse(submission, function(error, response, body){
      console.log('Received response from Fuse in event handler: ' + response.statusCode);
      console.log(body);
  });
});

fh.forms.registerListener(submissionEventListener, function(err){});

module.exports = fuseRoute;<|endoftext|>


<commit_before>var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors');
var request = require('request');
var events = require('events');
var fh = require('fh-mbaas-api');
var _ = require('underscore');

var fuseRoute = function() {
  var fuse = new express.Router();
  fuse.use(cors());
  fuse.use(bodyParser());

  fuse.post('/', function(req, res) {
    console.log(new Date(), 'In fuse route POST / req.body=', req.body);
    return submitToFuse(req.body, function(error, response, body){
      return res.send(body);
    });
  });

  return fuse;
};

var submitToFuse = function(submission, cb){
  var data = transform(submission);
  var url = '';
  //console.log(submission);
  if (submission.submission.formId == '5616b01a62af16be309b500a' )
    url = process.env.FUSE_REGISTER_URL || 'http://85.190.180.161:8182/cxf/redhat/forum/register';
  else if(submission.submission.formId == '5616b26ca32871323c63964d' ){
    url = process.env.FUSE_CHECKIN_URL || 'http://85.190.180.161:8182/cxf/redhat/forum/checkin';
  }
  else {
    cb(new Error("not valid"));
  }
  console.log(url);
  var options = { "url" : url, "body": data, "json": true};
  request.post(options, function (error, response, body) {
    if (error) {
      console.log(error) // Show the error
    }
    cb(error, response, body);
  });
};

var mapping = {
  "FFIRSTNAME" : "name",
  "FLASTNAME" : "lastName",
  "FEMAIL" : "email",
  "FPICTURE" : "picture",
  "FCOMPANY" : "companyName",
  "FTITLE" : "jobTitle",
  "FWEB" : "web",
  "FCODE" : "standCode",
  "FCOMMENTS" : "comments"
};

var transform = function(submission) {
  var map = {};
  _.each(submission.submission.formFields, function(item){
    //console.log(JSON.stringify(item));
    map[mapping[item.fieldId.fieldCode]] = item.fieldValues[0];
  });
  console.log(JSON.stringify(map));
  return map;
}

var submissionEventListener = new events.EventEmitter();

submissionEventListener.on('submissionComplete', function(submission){
  console.log('New submission received: ');
  //console.log(submission);
  return submitToFuse(submission, function(error, response, body){
      console.log('Received response from Fuse in event handler: ' + response);
      console.log(body);
  });
});

fh.forms.registerListener(submissionEventListener, function(err){});

module.exports = fuseRoute;<commit_msg>update file /lib/fuse.js<commit_after>var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors');
var request = require('request');
var events = require('events');
var fh = require('fh-mbaas-api');
var _ = require('underscore');

var fuseRoute = function() {
  var fuse = new express.Router();
  fuse.use(cors());
  fuse.use(bodyParser());

  fuse.post('/', function(req, res) {
    console.log(new Date(), 'In fuse route POST / req.body=', req.body);
    return submitToFuse(req.body, function(error, response, body){
      return res.send(body);
    });
  });

  return fuse;
};

var submitToFuse = function(submission, cb){
  var data = transform(submission);
  var url = '';
  //console.log(submission);
  if (submission.submission.formId == '5616b01a62af16be309b500a' )
    url = process.env.FUSE_REGISTER_URL || 'http://85.190.180.161:8182/cxf/redhat/forum/register';
  else if(submission.submission.formId == '5616b26ca32871323c63964d' ){
    url = process.env.FUSE_CHECKIN_URL || 'http://85.190.180.161:8182/cxf/redhat/forum/checkin';
  }
  else {
    cb(new Error("not valid"));
  }
  console.log(url);
  var options = { "url" : url, "body": data, "json": true};
  request.post(options, function (error, response, body) {
    if (error) {
      console.log(error) // Show the error
    }
    cb(error, response, body);
  });
};

var mapping = {
  "FFIRSTNAME" : "name",
  "FLASTNAME" : "lastName",
  "FEMAIL" : "email",
  "FPICTURE" : "picture",
  "FCOMPANY" : "companyName",
  "FTITLE" : "jobTitle",
  "FWEB" : "web",
  "FCODE" : "standCode",
  "FCOMMENTS" : "comments"
};

var transform = function(submission) {
  var map = {};
  _.each(submission.submission.formFields, function(item){
    //console.log(JSON.stringify(item));
    map[mapping[item.fieldId.fieldCode]] = item.fieldValues[0];
    if (item.fieldId.fieldCode == 'FCODE') {
      map[mapping[item.fieldId.fieldCode]] = item.fieldValues[0].text;
    }
  });
  console.log(JSON.stringify(map));
  return map;
}

var submissionEventListener = new events.EventEmitter();

submissionEventListener.on('submissionComplete', function(submission){
  console.log('New submission received: ');
  //console.log(submission);
  return submitToFuse(submission, function(error, response, body){
      console.log('Received response from Fuse in event handler: ' + response);
      console.log(body);
  });
});

fh.forms.registerListener(submissionEventListener, function(err){});

module.exports = fuseRoute;<|endoftext|>


<commit_before><commit_msg>Update starlink tracking data.<commit_after><|endoftext|>


<commit_before>var PSF = {

  // Main config elements
  debugMode: true,
  fireRate: 100,
  nextFire: 0,

  preload: function() {
      // Load up the assets we will use for this game
      this.game.load.image('space', 'assets/starfield.png');
      this.game.load.image('ship', 'assets/ship.png');
      this.game.load.image('bullet-laser', 'assets/bullet-laser.png');
      this.game.load.image('fs-button', 'assets/fs-button.png');
      this.game.load.image('crosshair', 'assets/crosshair.png');

      // Load plugins
      this.game.kineticScrolling = this.game.plugins.add(Phaser.Plugin.KineticScrolling);
  },

  create: function() {
      // Start and config Kinetic Scrolling for camera movement
      this.game.kineticScrolling.start();
      this.game.kineticScrolling.configure({
          kineticMovement: true,
          horizontalScroll: true,
          verticalScroll: true,
      });

      // Adjust world bound
      game.world.setBounds(-1000, -1000, 2000, 2000);

      // Start arcade physics and add in the background
      this.game.physics.startSystem(Phaser.Physics.ARCADE);
      this.game.add.tileSprite(-1000, -1000, 2000, 2000, 'space');

      // Set up ScaleManager options for full screen support
      this.game.scale.fullScreenScaleMode = Phaser.ScaleManager.SHOW_ALL;
      fullscreenButton = this.game.add.button(game.world.camera.view.width - 40, 15,
        'fs-button', this.toggleFullscreen, this);
      fullscreenButton.fixedToCamera = true;

      // Set up bullets
      bullets = this.game.add.group();
      bullets.enableBody = true;
      bullets.physicsBodyType = Phaser.Physics.ARCADE;

      bullets.createMultiple(50, 'bullet-laser');
      bullets.setAll('checkWorldBounds', true);
      bullets.setAll('outOfBoundsKill', true);

      // Set up ship
      ship = this.game.add.sprite(350, 275, 'ship');
      ship.anchor.setTo(0.5, 0.5);
      this.game.physics.arcade.enable(ship);
      ship.body.collideWorldBounds = true;

      // Ship ship properties for acceleration
      ship.body.maxAngular = 100;
      ship.body.angularDrag = 100;
      ship.body.drag = 500;

      // Initiate controls
      fire = this.game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR);
      fire.onDown.add(this.fireWeapon, this);

      this.game.input.onTap.add(this.moveOnDoubleTap, this);
  },

  // This second parameter is not well documented, but it's there and uses
  // game.input.doubleTapeRate to judge.
  // @see https://github.com/photonstorm/phaser/blob/486c15f16fd7c2f154d55cb0239fa0dbdeaed1f8/src/input/Pointer.js#L930
  moveOnDoubleTap: function(pointer, doubleTap) {
      if (doubleTap) {

          // Destory any existing crosshair
          if (this.movementTarget && this.movementTarget.alive) {
              this.movementTarget.destroy();
          }

          // Create new crosshair
          this.movementTarget = this.game.add.sprite(pointer.worldX,
              pointer.worldY, 'crosshair');
          game.physics.arcade.enable(this.movementTarget);

          // Turn ship towards crosshair
          var targetAngle = this.game.physics.arcade.angleToPointer(ship, pointer) + Math.PI / 2;
          ship.rotation = targetAngle;

          // Initiate ship movement
          this.game.physics.arcade.moveToPointer(ship);

          // Adjust camera to follow ship
          this.game.camera.follow(ship);
      }
  },

  update: function() {
      // Check for a movementTarget and update when the ship arrives
      if (this.movementTarget && this.movementTarget.alive) {

          // Stop ship on overlap
          if (game.physics.arcade.overlap(ship, this.movementTarget)) {
              ship.body.velocity.x = 0;
              ship.body.velocity.y = 0;
              this.game.camera.unfollow(ship);
              this.movementTarget.destroy();
          }
      }
  },

  render: function() {
      if (this.debugMode == true) {
          game.debug.cameraInfo(game.camera, 32, 220);
          game.debug.spriteInfo(ship, 32, 32);
          game.debug.text('angularVelocity: ' + ship.body.angularVelocity, 32, 120);
          game.debug.text('angle: ' + ship.body.angle, 32, 140);
          game.debug.text('angularDrag: ' + ship.body.angularDrag, 32, 160);
          game.debug.text('deltaZ: ' + ship.body.deltaZ(), 32, 180);
          game.debug.text('velocity: (x = ' + ship.body.velocity.x +
              ', y = ' + ship.body.velocity.y + ')', 32, 200);
          game.debug.text('Active Bullets: ' + bullets.countLiving() +
              ' / ' + bullets.total, 32, 300);
      }
  },

  toggleFullscreen: function() {
      if (game.scale.isFullScreen) {
          game.scale.stopFullScreen();
      }
      else {
          game.scale.startFullScreen(false);
      }
  },

  fireWeapon: function() {
      if (game.time.now > this.nextFire && bullets.countDead() > 0) {
          this.nextFire = game.time.now + this.fireRate;

          var bullet = bullets.getFirstDead();
          bullet.reset(ship.x, ship.y - 10);

          bullet.angle = ship.angle;
          game.physics.arcade.velocityFromAngle(bullet.angle - 90, 500,
              bullet.body.velocity)
      }
  },

}

var game = new Phaser.Game(800, 600, Phaser.AUTO, 'game-canvas');
game.state.add('PSF', PSF);
game.state.start('PSF');<commit_msg>cleanup<commit_after>var PSF = {

  // Main config elements
  debugMode: false,
  fireRate: 100,
  nextFire: 0,

  preload: function() {
      // Load up the assets we will use for this game
      this.game.load.image('space', 'assets/starfield.png');
      this.game.load.image('ship', 'assets/ship.png');
      this.game.load.image('bullet-laser', 'assets/bullet-laser.png');
      this.game.load.image('fs-button', 'assets/fs-button.png');
      this.game.load.image('crosshair', 'assets/crosshair.png');

      // Load plugins
      this.game.kineticScrolling = this.game.plugins.add(Phaser.Plugin.KineticScrolling);
  },

  create: function() {
      // Start and config Kinetic Scrolling for camera movement
      this.game.kineticScrolling.start();
      this.game.kineticScrolling.configure({
          kineticMovement: true,
          horizontalScroll: true,
          verticalScroll: true,
      });

      // Adjust world bound
      game.world.setBounds(-1000, -1000, 2000, 2000);

      // Start arcade physics and add in the background
      this.game.physics.startSystem(Phaser.Physics.ARCADE);
      this.game.add.tileSprite(-1000, -1000, 2000, 2000, 'space');

      // Set up ScaleManager options for full screen support
      this.game.scale.fullScreenScaleMode = Phaser.ScaleManager.SHOW_ALL;
      fullscreenButton = this.game.add.button(game.world.camera.view.width - 40, 15,
        'fs-button', this.toggleFullscreen, this);
      fullscreenButton.fixedToCamera = true;

      // Set up bullets
      bullets = this.game.add.group();
      bullets.enableBody = true;
      bullets.physicsBodyType = Phaser.Physics.ARCADE;

      bullets.createMultiple(50, 'bullet-laser');
      bullets.setAll('checkWorldBounds', true);
      bullets.setAll('outOfBoundsKill', true);

      // Set up ship
      ship = this.game.add.sprite(350, 275, 'ship');
      ship.anchor.setTo(0.5, 0.5);
      this.game.physics.arcade.enable(ship);
      ship.body.collideWorldBounds = true;

      // Ship ship properties for acceleration
      ship.body.maxAngular = 100;
      ship.body.angularDrag = 100;
      ship.body.drag = 500;

      // Initiate controls
      fire = this.game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR);
      fire.onDown.add(this.fireWeapon, this);

      this.game.input.onTap.add(this.moveOnDoubleTap, this);
  },

  // This second parameter is not well documented, but it's there and uses
  // game.input.doubleTapeRate to judge.
  // @see https://github.com/photonstorm/phaser/blob/486c15f16fd7c2f154d55cb0239fa0dbdeaed1f8/src/input/Pointer.js#L930
  moveOnDoubleTap: function(pointer, doubleTap) {
      if (doubleTap) {

          // Destory any existing crosshair
          if (this.movementTarget && this.movementTarget.alive) {
              this.movementTarget.destroy();
          }

          // Create new crosshair
          this.movementTarget = this.game.add.sprite(pointer.worldX,
              pointer.worldY, 'crosshair');
          game.physics.arcade.enable(this.movementTarget);

          // Turn ship towards crosshair
          var targetAngle = this.game.physics.arcade.angleToPointer(ship, pointer) + Math.PI / 2;
          ship.rotation = targetAngle;

          // Initiate ship movement
          this.game.physics.arcade.moveToPointer(ship);

          // Adjust camera to follow ship
          this.game.camera.follow(ship);
      }
  },

  update: function() {
      // Check for a movementTarget and update when the ship arrives
      if (this.movementTarget && this.movementTarget.alive) {

          // Stop ship on overlap
          if (game.physics.arcade.overlap(ship, this.movementTarget)) {
              ship.body.velocity.x = 0;
              ship.body.velocity.y = 0;
              this.game.camera.unfollow(ship);
              this.movementTarget.destroy();
          }
      }
  },

  render: function() {
      if (this.debugMode == true) {
          game.debug.cameraInfo(game.camera, 32, 220);
          game.debug.spriteInfo(ship, 32, 32);
          game.debug.text('angularVelocity: ' + ship.body.angularVelocity, 32, 120);
          game.debug.text('angularAcceleration: ' + ship.body.angularAcceleration, 32, 140);
          game.debug.text('angularDrag: ' + ship.body.angularDrag, 32, 160);
          game.debug.text('deltaZ: ' + ship.body.deltaZ(), 32, 180);
          game.debug.text('velocity: (x = ' + ship.body.velocity.x +
              ', y = ' + ship.body.velocity.y + ')', 32, 200);
          game.debug.text('Active Bullets: ' + bullets.countLiving() +
              ' / ' + bullets.total, 32, 300);
      }
  },

  toggleFullscreen: function() {
      if (game.scale.isFullScreen) {
          game.scale.stopFullScreen();
      }
      else {
          game.scale.startFullScreen(false);
      }
  },

  fireWeapon: function() {
      if (game.time.now > this.nextFire && bullets.countDead() > 0) {
          this.nextFire = game.time.now + this.fireRate;

          var bullet = bullets.getFirstDead();
          bullet.reset(ship.x, ship.y - 10);

          bullet.angle = ship.angle;
          game.physics.arcade.velocityFromAngle(bullet.angle - 90, 500,
              bullet.body.velocity)
      }
  },

}

var game = new Phaser.Game(800, 600, Phaser.AUTO, 'game-canvas');
game.state.add('PSF', PSF);
game.state.start('PSF');<|endoftext|>


<commit_before>/**
 * JS module included on every page of the OSF. Site-wide initialization
 * code goes here.
 */
'use strict';
// CSS used on every page
require('../../vendor/bootstrap-editable-custom/css/bootstrap-editable.css');
require('../../vendor/bower_components/jquery-ui/themes/base/resizable.css');
require('../../css/bootstrap-xl.css');
require('../../css/animate.css');
require('font-awesome-webpack');

var $ = require('jquery');
var Cookie = require('js-cookie');

require('js/crossOrigin.js');
var $osf = require('js/osfHelpers');
var NavbarControl = require('js/navbarControl');
var AlertManager = require('js/alertsManager');
var Raven = require('raven-js');
var moment = require('moment');
var KeenTracker = require('js/keen');
var DevModeControls = require('js/devModeControls');
var bootbox = require('bootbox');

// Prevent IE from caching responses
$.ajaxSetup({cache: false});

// Polyfill for String.prototype.endsWith
if (String.prototype.endsWith === undefined) {
    String.prototype.endsWith = function(suffix) {
        return this.indexOf(suffix, this.length - suffix.length) !== -1;
    };
}

// Apply an empty view-model to the navbar, just so the tooltip bindingHandler
// can be used
// $osf.applyBindings({}, '#navbarScope');

$('[rel="tooltip"]').tooltip();

// Cookie banner notice for logged out users
var cookieBannerSelector = '#cookieBanner';
var CookieBannerViewModel = function(){
    var self = this;
    self.elem = $(cookieBannerSelector);
    var cookieConsentKey = 'osf_cookieconsent';

    self.accept = function() {
        Cookie.set(cookieConsentKey, '1', { expires: 30, path: '/'});
    };

    var accepted = Cookie.get(cookieConsentKey) === '1';
    if (!accepted) {
        self.elem.css({'display': 'flex'});
        self.elem.show();
    }
};

// If there isn't a user logged in, show the footer slide-in
var sliderSelector = '#footerSlideIn';
var SlideInViewModel = function (){
    var self = this;
    self.elem = $(sliderSelector);

    var dismissed = false;

    try {
        dismissed = dismissed || window.localStorage.getItem('slide') === '0';
    } catch (e) {}

    dismissed = dismissed || Cookie.get('slide') === '0';

    if (this.elem.length > 0 && !dismissed) {
        setTimeout(function () {
            self.elem.slideDown(1000);
        }, 3000);
    }
    self.dismiss = function() {
        self.elem.slideUp(1000);
        try {
            window.localStorage.setItem('slide', '0');
        } catch (e) {
            Cookie.set('slide', '0', { expires: 1, path: '/'});
        }
        self.trackClick('Dismiss');
    };
    // Google Analytics click event tracking
    self.trackClick = function(source) {
        window.ga('send', 'event', 'button', 'click', source);
        //in order to make the href redirect work under knockout onclick binding
        return true;
    };
};

$(document).on('click', '.panel-heading', function(){
    var toggle = $(this).find('.project-toggle');
    if(toggle.length > 0){
        var widget = $(this).closest('.panel');
        var up = toggle.find('.fa.fa-angle-up');
        var down = toggle.find('.fa.fa-angle-down');
        if(up.length > 0) {
            up.removeClass('fa fa-angle-up').addClass('fa fa-angle-down');
        }
        if(down.length > 0) {
            down.removeClass('fa fa-angle-down').addClass('fa fa-angle-up');
        }

        widget.find('.panel-body').slideToggle();
    }
});

//choose which emails/users to add to an account and which to deny
function confirmEmails(emailsToAdd) {
    if (emailsToAdd.length > 0) {
        var confirmedEmailURL = '/api/v1/confirmed_emails/';
        var email = emailsToAdd[0];
        var title;
        var requestMessage;
        var confirmMessage;
        var nopeMessage;
        if (email.user_merge) {
            title = 'Merge account';
            requestMessage = 'Would you like to merge \' + email.address + '\ into your account?  ' +
                'This action is irreversible.';
            confirmMessage = '\' + email.address + '\ has been merged into your account.';
            nopeMessage = 'You have chosen to not merge \' + email.address + '\  into your account. ' +
                'If you change your mind, visit the \user settings page.';
        }
        else {
            title = 'Add email';
            requestMessage = 'Would you like to add \' + email.address + '\ to your account?';
            confirmMessage = '\' + email.address + '\ has been added into your account.';
            nopeMessage = 'You have chosen not to add \' + email.address + '\ to your account. ' +
                'If you change your mind, visit the \user settings page.';
        }

        var confirmFailMessage = 'There was a problem adding \' + email.address +
            '\. Please contact ' + $osf.osfSupportLink() + ' if the problem persists.';

        var cancelFailMessage = 'There was a problem removing \' + email.address +
            '\. Please contact ' + $osf.osfSupportLink() + ' if the problem persists.';

        bootbox.dialog({
            title: title,
            message: requestMessage,
            onEscape: function () {
            },
            backdrop: true,
            closeButton: true,
            buttons: {
                cancel: {
                    label: 'Do not add email',
                    className: 'btn-default',
                    callback: function () {
                        $.ajax({
                            type: 'delete',
                            url: confirmedEmailURL,
                            contentType: 'application/json',
                            dataType: 'json',
                            data: JSON.stringify(email)
                        }).done(function () {
                            $osf.growl('Warning', nopeMessage, 'warning', 8000);
                            confirmEmails(emailsToAdd.slice(1));
                        }).fail(function (xhr, textStatus, error) {
                            Raven.captureMessage('Could not remove email', {
                                extra: {
                                    url: confirmedEmailURL,
                                    textStatus: textStatus,
                                    error: error
                                }
                            });
                            $osf.growl('Error',
                                cancelFailMessage,
                                'danger'
                            );
                        });
                    }
                },
                confirm: {
                    label: 'Add email',
                    className: 'btn-success pull-right',
                    callback: function () {
                        $osf.putJSON(
                            confirmedEmailURL,
                            email
                        ).done(function () {
                            $osf.growl('Success', confirmMessage, 'success', 3000);
                            confirmEmails(emailsToAdd.slice(1));
                        }).fail(function (xhr, textStatus, error) {
                            Raven.captureMessage('Could not add email', {
                                extra: {
                                    url: confirmedEmailURL,
                                    textStatus: textStatus,
                                    error: error
                                }
                            });
                            $osf.growl('Error',
                                confirmFailMessage,
                                'danger'
                            );
                        });
                    }
                }
            }
        });

    }
}

$(function() {
    if(/MSIE 9.0/.test(window.navigator.userAgent) ||
       /MSIE 8.0/.test(window.navigator.userAgent) ||
       /MSIE 7.0/.test(window.navigator.userAgent) ||
       /MSIE 6.0/.test(window.navigator.userAgent)) {
        $('.placeholder-replace').show();
    }
    if (
        $(sliderSelector).length > 0 &&
        window.contextVars.node
    ) {
        $osf.applyBindings(new SlideInViewModel(), sliderSelector);
    }

    if ($(cookieBannerSelector).length) {
        $osf.applyBindings(new CookieBannerViewModel(), cookieBannerSelector);
    }

    var affix = $('.osf-affix');
    if(affix.length){
        $osf.initializeResponsiveAffix();
    }
    new NavbarControl('.osf-nav-wrapper');
    if (__ENABLE_DEV_MODE_CONTROLS) {
        new DevModeControls('#devModeControls', '/static/built/git_logs.json', '/static/built/git_branch.txt');
    }

    var alertsSelector = '.dismissible-alerts';
    if ($(alertsSelector).length > 0 && window.contextVars.currentUser) {
        for (var i = 0; i < $(alertsSelector).length; i++) {
            var selectorId = '#' + $(alertsSelector)[i].id;
            new AlertManager(selectorId);
        }
    }

    if (window.contextVars.keen){
        //Don't track PhantomJS visits with KeenIO
        if (!(/PhantomJS/.test(navigator.userAgent))){
            KeenTracker.getInstance().trackPageView();
        }
    }

    confirmEmails(window.contextVars.currentUser.emailsToAdd);

    // Maintenance alert
    if (window.contextVars.maintenance) {
        var maintenancePersistKey = 'maintenance';
        var $maintenance = $('#maintenance').on('closed.bs.alert', function() {
            Cookie.set(maintenancePersistKey, '0', { expires: 1, path: '/'});
        });

        var levelMap = {
            1: 'info',
            2: 'warning',
            3: 'danger'
        };
        $('#maintenance').addClass('alert-' + levelMap[window.contextVars.maintenance.level]);

        var dismissed = Cookie.get(maintenancePersistKey) === '0';
        if (!dismissed) {
            $maintenance.show();
        }
        // Localize maintenance period datetimes
        var startMaintenance = moment(window.contextVars.maintenance.start);
        var endMaintenance = moment(window.contextVars.maintenance.end);
        $('#maintenanceTime').html(
            '' +
            startMaintenance.format('lll') +
                ' and ' +
                    endMaintenance.format('lll') + '' +
                        ' (' + startMaintenance.format('ZZ') + ' UTC)'
        );
    }
    // END Maintenance alert

});
<commit_msg>genralize cookie banner and morph it into IE depreciation banner<commit_after>/**
 * JS module included on every page of the OSF. Site-wide initialization
 * code goes here.
 */
'use strict';
// CSS used on every page
require('../../vendor/bootstrap-editable-custom/css/bootstrap-editable.css');
require('../../vendor/bower_components/jquery-ui/themes/base/resizable.css');
require('../../css/bootstrap-xl.css');
require('../../css/animate.css');
require('font-awesome-webpack');

var $ = require('jquery');
var Cookie = require('js-cookie');

require('js/crossOrigin.js');
var $osf = require('js/osfHelpers');
var NavbarControl = require('js/navbarControl');
var AlertManager = require('js/alertsManager');
var Raven = require('raven-js');
var moment = require('moment');
var KeenTracker = require('js/keen');
var DevModeControls = require('js/devModeControls');
var bootbox = require('bootbox');

// Prevent IE from caching responses
$.ajaxSetup({cache: false});

// Polyfill for String.prototype.endsWith
if (String.prototype.endsWith === undefined) {
    String.prototype.endsWith = function(suffix) {
        return this.indexOf(suffix, this.length - suffix.length) !== -1;
    };
}

// Apply an empty view-model to the navbar, just so the tooltip bindingHandler
// can be used
// $osf.applyBindings({}, '#navbarScope');

$('[rel="tooltip"]').tooltip();

var cookieBannerSelector = '#cookieBanner';
var cookieConsentKey = 'osf_cookieconsent';

// IE Depreciation Banner
var IEDepreciationBannerSelector = '#IEDepreciationBanner';
var IEcookieConsentKey = 'osf_IEconsent';

var makeWarningBanner = function(selector, cookieKey){
    var self = this;
    self.elem = $(selector);
    self.accept = function() {
        Cookie.set(cookieKey, '1', { expires: 30, path: '/'});
    };

    var accepted = Cookie.get(cookieKey) === '1';
    if (!accepted) {
        self.elem.css({'display': 'flex'});
        self.elem.show();
    }
};

// If there isn't a user logged in, show the footer slide-in
var sliderSelector = '#footerSlideIn';
var SlideInViewModel = function (){
    var self = this;
    self.elem = $(sliderSelector);

    var dismissed = false;

    try {
        dismissed = dismissed || window.localStorage.getItem('slide') === '0';
    } catch (e) {}

    dismissed = dismissed || Cookie.get('slide') === '0';

    if (this.elem.length > 0 && !dismissed) {
        setTimeout(function () {
            self.elem.slideDown(1000);
        }, 3000);
    }
    self.dismiss = function() {
        self.elem.slideUp(1000);
        try {
            window.localStorage.setItem('slide', '0');
        } catch (e) {
            Cookie.set('slide', '0', { expires: 1, path: '/'});
        }
        self.trackClick('Dismiss');
    };
    // Google Analytics click event tracking
    self.trackClick = function(source) {
        window.ga('send', 'event', 'button', 'click', source);
        //in order to make the href redirect work under knockout onclick binding
        return true;
    };
};

$(document).on('click', '.panel-heading', function(){
    var toggle = $(this).find('.project-toggle');
    if(toggle.length > 0){
        var widget = $(this).closest('.panel');
        var up = toggle.find('.fa.fa-angle-up');
        var down = toggle.find('.fa.fa-angle-down');
        if(up.length > 0) {
            up.removeClass('fa fa-angle-up').addClass('fa fa-angle-down');
        }
        if(down.length > 0) {
            down.removeClass('fa fa-angle-down').addClass('fa fa-angle-up');
        }

        widget.find('.panel-body').slideToggle();
    }
});

//choose which emails/users to add to an account and which to deny
function confirmEmails(emailsToAdd) {
    if (emailsToAdd.length > 0) {
        var confirmedEmailURL = '/api/v1/confirmed_emails/';
        var email = emailsToAdd[0];
        var title;
        var requestMessage;
        var confirmMessage;
        var nopeMessage;
        if (email.user_merge) {
            title = 'Merge account';
            requestMessage = 'Would you like to merge \' + email.address + '\ into your account?  ' +
                'This action is irreversible.';
            confirmMessage = '\' + email.address + '\ has been merged into your account.';
            nopeMessage = 'You have chosen to not merge \' + email.address + '\  into your account. ' +
                'If you change your mind, visit the \user settings page.';
        }
        else {
            title = 'Add email';
            requestMessage = 'Would you like to add \' + email.address + '\ to your account?';
            confirmMessage = '\' + email.address + '\ has been added into your account.';
            nopeMessage = 'You have chosen not to add \' + email.address + '\ to your account. ' +
                'If you change your mind, visit the \user settings page.';
        }

        var confirmFailMessage = 'There was a problem adding \' + email.address +
            '\. Please contact ' + $osf.osfSupportLink() + ' if the problem persists.';

        var cancelFailMessage = 'There was a problem removing \' + email.address +
            '\. Please contact ' + $osf.osfSupportLink() + ' if the problem persists.';

        bootbox.dialog({
            title: title,
            message: requestMessage,
            onEscape: function () {
            },
            backdrop: true,
            closeButton: true,
            buttons: {
                cancel: {
                    label: 'Do not add email',
                    className: 'btn-default',
                    callback: function () {
                        $.ajax({
                            type: 'delete',
                            url: confirmedEmailURL,
                            contentType: 'application/json',
                            dataType: 'json',
                            data: JSON.stringify(email)
                        }).done(function () {
                            $osf.growl('Warning', nopeMessage, 'warning', 8000);
                            confirmEmails(emailsToAdd.slice(1));
                        }).fail(function (xhr, textStatus, error) {
                            Raven.captureMessage('Could not remove email', {
                                extra: {
                                    url: confirmedEmailURL,
                                    textStatus: textStatus,
                                    error: error
                                }
                            });
                            $osf.growl('Error',
                                cancelFailMessage,
                                'danger'
                            );
                        });
                    }
                },
                confirm: {
                    label: 'Add email',
                    className: 'btn-success pull-right',
                    callback: function () {
                        $osf.putJSON(
                            confirmedEmailURL,
                            email
                        ).done(function () {
                            $osf.growl('Success', confirmMessage, 'success', 3000);
                            confirmEmails(emailsToAdd.slice(1));
                        }).fail(function (xhr, textStatus, error) {
                            Raven.captureMessage('Could not add email', {
                                extra: {
                                    url: confirmedEmailURL,
                                    textStatus: textStatus,
                                    error: error
                                }
                            });
                            $osf.growl('Error',
                                confirmFailMessage,
                                'danger'
                            );
                        });
                    }
                }
            }
        });

    }
}

$(function() {
    var isIE = /*@cc_on!@*/false || !!document.documentMode;
    if(isIE){
        $osf.applyBindings(new makeWarningBanner(IEDepreciationBannerSelector, IEcookieConsentKey), IEDepreciationBannerSelector);
    }
    if(/MSIE 9.0/.test(window.navigator.userAgent) ||
       /MSIE 8.0/.test(window.navigator.userAgent) ||
       /MSIE 7.0/.test(window.navigator.userAgent) ||
       /MSIE 6.0/.test(window.navigator.userAgent)) {
        $('.placeholder-replace').show();
    }
    if (
        $(sliderSelector).length > 0 &&
        window.contextVars.node
    ) {
        $osf.applyBindings(new SlideInViewModel(), sliderSelector);
    }

    if ($(cookieBannerSelector).length) {
        $osf.applyBindings(new makeWarningBanner(cookieBannerSelector, cookieConsentKey), cookieBannerSelector);
    }

    var affix = $('.osf-affix');
    if(affix.length){
        $osf.initializeResponsiveAffix();
    }
    new NavbarControl('.osf-nav-wrapper');
    if (__ENABLE_DEV_MODE_CONTROLS) {
        new DevModeControls('#devModeControls', '/static/built/git_logs.json', '/static/built/git_branch.txt');
    }

    var alertsSelector = '.dismissible-alerts';
    if ($(alertsSelector).length > 0 && window.contextVars.currentUser) {
        for (var i = 0; i < $(alertsSelector).length; i++) {
            var selectorId = '#' + $(alertsSelector)[i].id;
            new AlertManager(selectorId);
        }
    }

    if (window.contextVars.keen){
        //Don't track PhantomJS visits with KeenIO
        if (!(/PhantomJS/.test(navigator.userAgent))){
            KeenTracker.getInstance().trackPageView();
        }
    }

    confirmEmails(window.contextVars.currentUser.emailsToAdd);

    // Maintenance alert
    if (window.contextVars.maintenance) {
        var maintenancePersistKey = 'maintenance';
        var $maintenance = $('#maintenance').on('closed.bs.alert', function() {
            Cookie.set(maintenancePersistKey, '0', { expires: 1, path: '/'});
        });

        var levelMap = {
            1: 'info',
            2: 'warning',
            3: 'danger'
        };
        $('#maintenance').addClass('alert-' + levelMap[window.contextVars.maintenance.level]);

        var dismissed = Cookie.get(maintenancePersistKey) === '0';
        if (!dismissed) {
            $maintenance.show();
        }
        // Localize maintenance period datetimes
        var startMaintenance = moment(window.contextVars.maintenance.start);
        var endMaintenance = moment(window.contextVars.maintenance.end);
        $('#maintenanceTime').html(
            '' +
            startMaintenance.format('lll') +
                ' and ' +
                    endMaintenance.format('lll') + '' +
                        ' (' + startMaintenance.format('ZZ') + ' UTC)'
        );
    }
    // END Maintenance alert

});
<|endoftext|>


<commit_before>var $ = require('jquery');

var canvas = document.getElementById("canvas");

var Enemy = require("./enemies.js");
var Bluecifer = require('./bluecifer');

var enemy = new Enemy();

var gameScore = $('#game-score');
var startGame = $("#start-game");
var youWin = $('#you-win');
var gameOver = $('#game-over');
var finalScore = $("#final-score-display");

function showStartScreen () {
  startGame.css('visibility', 'visible');
}

function showWinScreen () {
  youWin.css('visibility', 'visible');
}

function showGameOver () {
  gameOver.css('visibility', 'visible');
}

function Game() {
  this.themeSong = new Audio("music/spark-mandrill.mp3");
  this.celebration = new Audio("music/celebration.mp3");
  this.canvas = canvas;
  this.ctx = this.canvas.getContext('2d');
  this.bluecifer = new Bluecifer();
  this.active = true;
  this.enemies = [];
  this.collisionCanHappen = true;
  this.scoreCounter = 0;
}

Game.prototype.repeat = function() {
    var blueciferY = this.bluecifer.y;
    this.clearCanvas();
    this.bluecifer.draw(this.ctx);
    this.bluecifer.gravity();
    this.detectFloorCollision();
    this.setUpEnemies(blueciferY);
    this.keepScore();
};

Game.prototype.setUpEnemies = function (blueciferY) {
  this.createNewEnemies();
  this.drawEnemiesFromArray(blueciferY);
  this.detectEnemyCollision();
};

Game.prototype.clearCanvas = function() {
  this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
};

Game.prototype.bluecifer = function() {
  this.bluecifer.draw(this.ctx);
};

Game.prototype.blueciferGravity = function() {
  this.bluecifer.gravity();
};

Game.prototype.createNewEnemies = function() {
if (this.scoreCounter % 100 === 0){
  if (this.enemies.length < 5){
    this.enemies.push(new Enemy());
    }
  }
};

Game.prototype.drawEnemiesFromArray = function(blueciferY) {
  var theBigY = blueciferY;
  var blues = {};
  blues.x = 150;
  blues.y = theBigY;
  blues.width = 50;
  blues.height = 35;

  this.enemies.forEach(function(enemy) {
    enemy.moveLeftRandom();
    enemy.draw(canvas.getContext("2d"));
  });
};

Game.prototype.detectEnemyCollision = function() {
  var b = this.bluecifer;
  var self = this;
  this.enemies.forEach(function(enemy) {
    var blueciferBottomLeft = b.y + b.height;

    var enemyTopRight = enemy.x + enemy.width;

    var blueciferTopRight = b.x + b.width;

    var enemyBottomLeft = enemy.y + enemy.height;

    if ((enemyBottomLeft < (b.y)) || (enemy.y > blueciferBottomLeft) || (enemyTopRight < b.x) || (enemy.x > (blueciferTopRight)) || self.collisionCanHappen === false) {
    }
    else {
      self.gameOver();
    }
  });
};

Game.prototype.detectCeilingCollision = function() {
  if (this.bluecifer.y < 0) {
    this.bluecifer.y = this.bluecifer.y + 20;
  }
};

Game.prototype.detectFloorCollision = function() {
  if (this.bluecifer.y > 350) {
    this.gameOver();
    this.pauseThemeSong();
  }
};

Game.prototype.startGame = function() {
  this.scoreCounter = 0;
  enemy.resetCounter();
  this.bluecifer.y = 100;
  this.active = true;
};

Game.prototype.keepScore = function() {
  var currentScore = this.scoreCounter++;
  if (currentScore <= 100){
    gameScore.text("000" + currentScore);
  } else if (currentScore <= 1000){
    gameScore.text("00" + currentScore);
  } else if (currentScore <= 10000){
    gameScore.text("0" + currentScore); //when they beat the game
    this.enemies.length = 0;
    this.active = false;
    showStartScreen();
    showWinScreen();
    this.pauseThemeSong();
    this.playCelebration();
  } else {
    this.showCurrentScore(currentScore);
  }
};

Game.prototype.showCurrentScore = function (currentScore) {
  gameScore.text(currentScore);
};

Game.prototype.gameOver = function() {
  showGameOver();
  this.enemies.length = 0;
  this.active = false;
  this.pauseThemeSong();
  finalScore.text("Your final score was " + this.scoreCounter);
};

// Game.prototype.showFinalScore = function () {
//
// };

Game.prototype.playThemeSong = function () {
  this.themeSong.play();
};

Game.prototype.pauseThemeSong = function () {
  this.themeSong.pause();
};

Game.prototype.playCelebration = function () {
  this.celebration.play();
};

Game.prototype.pauseCelebration = function () {
  this.celebration.pause();
};

Game.prototype.cheat = function (code) {
  if (code === "dogs") {
    this.collisionCanHappen = false;
    alert("Cheat mode activated!");
  }
  else {
    alert("Nope, wrong code!");
  }
};

module.exports = Game;
<commit_msg>finished showFinalScore function<commit_after>var $ = require('jquery');

var canvas = document.getElementById("canvas");

var Enemy = require("./enemies.js");
var Bluecifer = require('./bluecifer');

var enemy = new Enemy();

var gameScore = $('#game-score');
var startGame = $("#start-game");
var youWin = $('#you-win');
var gameOver = $('#game-over');
var finalScore = $("#final-score-display");

function showStartScreen () {
  startGame.css('visibility', 'visible');
}

function showWinScreen () {
  youWin.css('visibility', 'visible');
}

function showGameOver () {
  gameOver.css('visibility', 'visible');
}

function Game() {
  this.themeSong = new Audio("music/spark-mandrill.mp3");
  this.celebration = new Audio("music/celebration.mp3");
  this.canvas = canvas;
  this.ctx = this.canvas.getContext('2d');
  this.bluecifer = new Bluecifer();
  this.active = true;
  this.enemies = [];
  this.collisionCanHappen = true;
  this.scoreCounter = 0;
}

Game.prototype.repeat = function() {
    var blueciferY = this.bluecifer.y;
    this.clearCanvas();
    this.bluecifer.draw(this.ctx);
    this.bluecifer.gravity();
    this.detectFloorCollision();
    this.setUpEnemies(blueciferY);
    this.keepScore();
};

Game.prototype.setUpEnemies = function (blueciferY) {
  this.createNewEnemies();
  this.drawEnemiesFromArray(blueciferY);
  this.detectEnemyCollision();
};

Game.prototype.clearCanvas = function() {
  this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
};

Game.prototype.bluecifer = function() {
  this.bluecifer.draw(this.ctx);
};

Game.prototype.blueciferGravity = function() {
  this.bluecifer.gravity();
};

Game.prototype.createNewEnemies = function() {
if (this.scoreCounter % 100 === 0){
  if (this.enemies.length < 5){
    this.enemies.push(new Enemy());
    }
  }
};

Game.prototype.drawEnemiesFromArray = function(blueciferY) {
  var theBigY = blueciferY;
  var blues = {};
  blues.x = 150;
  blues.y = theBigY;
  blues.width = 50;
  blues.height = 35;

  this.enemies.forEach(function(enemy) {
    enemy.moveLeftRandom();
    enemy.draw(canvas.getContext("2d"));
  });
};

Game.prototype.detectEnemyCollision = function() {
  var b = this.bluecifer;
  var self = this;
  this.enemies.forEach(function(enemy) {
    var blueciferBottomLeft = b.y + b.height;

    var enemyTopRight = enemy.x + enemy.width;

    var blueciferTopRight = b.x + b.width;

    var enemyBottomLeft = enemy.y + enemy.height;

    if ((enemyBottomLeft < (b.y)) || (enemy.y > blueciferBottomLeft) || (enemyTopRight < b.x) || (enemy.x > (blueciferTopRight)) || self.collisionCanHappen === false) {
    }
    else {
      self.gameOver();
    }
  });
};

Game.prototype.detectCeilingCollision = function() {
  if (this.bluecifer.y < 0) {
    this.bluecifer.y = this.bluecifer.y + 20;
  }
};

Game.prototype.detectFloorCollision = function() {
  if (this.bluecifer.y > 350) {
    this.gameOver();
    this.pauseThemeSong();
  }
};

Game.prototype.startGame = function() {
  this.scoreCounter = 0;
  enemy.resetCounter();
  this.bluecifer.y = 100;
  this.active = true;
};

Game.prototype.keepScore = function() {
  var currentScore = this.scoreCounter++;
  if (currentScore <= 100){
    gameScore.text("000" + currentScore);
  } else if (currentScore <= 1000){
    gameScore.text("00" + currentScore);
  } else if (currentScore <= 10000){
    gameScore.text("0" + currentScore); //when they beat the game
    this.enemies.length = 0;
    this.active = false;
    showStartScreen();
    showWinScreen();
    this.pauseThemeSong();
    this.playCelebration();
  } else {
    this.showCurrentScore(currentScore);
  }
};

Game.prototype.showCurrentScore = function (currentScore) {
  gameScore.text(currentScore);
};

Game.prototype.gameOver = function() {
  showGameOver();
  this.enemies.length = 0;
  this.active = false;
  this.pauseThemeSong();
  this.showFinalScore();
};

Game.prototype.showFinalScore = function () {
  finalScore.text("Your final score was " + this.scoreCounter);
};

Game.prototype.playThemeSong = function () {
  this.themeSong.play();
};

Game.prototype.pauseThemeSong = function () {
  this.themeSong.pause();
};

Game.prototype.playCelebration = function () {
  this.celebration.play();
};

Game.prototype.pauseCelebration = function () {
  this.celebration.pause();
};

Game.prototype.cheat = function (code) {
  if (code === "dogs") {
    this.collisionCanHappen = false;
    alert("Cheat mode activated!");
  }
  else {
    alert("Nope, wrong code!");
  }
};

module.exports = Game;
<|endoftext|>