<commit_before>/**
 * @module Environment
 * @submodule Environment
 * @for p5
 * @requires core
 */

import p5 from '../core/main';
const ds = '_Description'; //Fallback container
const fds = '_fds'; //Fallback description
const ft = '_ft'; //Fallback Table
const fte = '_fte_'; //Fallback Table Element
const lb = '_Label'; //Label container
const lds = '_lds'; //Label description
const lt = '_lt'; //Label Table
const lte = '_lte_'; //Label Table Element

/**
 * Creates a screen-reader accessible description for the canvas.
 * The first parameter should be a string with a description of the canvas.
 * The second parameter is optional. If specified, it determines how the
 * description is displayed.
 *
 * describe(text, LABEL) displays
 * the description to all users as a
 * tombstone or exhibit label/caption in a
 * <div class="p5Label"></div>
 * adjacent to the canvas. You can style it as you wish in your CSS.
 *
 * describe(text, FALLBACK) makes the
 * description accessible to screen-reader users only, in
 *
 * a sub DOM inside the canvas element. If a second parameter is not
 * specified, by default, the description will only be available to
 * screen-reader users.
 *
 * @method describe
 * @param  {String} text      description of the canvas
 * @param  {Constant} [display] either LABEL or FALLBACK (Optional)
 *
 * @example
 *

 *
 * describe('pink square with red heart in the bottom right corner', LABEL);
 * background('pink');
 * fill('red');
 * noStroke();
 * ellipse(67, 67, 20, 20);
 * ellipse(83, 67, 20, 20);
 * triangle(91, 73, 75, 95, 59, 73);
 *
 *

 *
 *

 *
 * let x = 0;
 * function draw() {
 *   if (x > 100) {
 *     x = 0;
 *   }
 *   background(220);
 *   fill(0, 255, 0);
 *   ellipse(x, 50, 40, 40);
 *   x = x + 0.1;
 *   describe('green circle at x pos ' + round(x) + ' moving to the right');
 * }
 *
 *

 *
 */

p5.prototype.describe = function(t, d) {
  const cnvId = this.canvas.id;
  p5._validateParameters('describe', arguments);
  //Creates a sub DOM inside of the canvas element and populates
  //it with description text.
  if (typeof t !== 'string') {
    return;
  }
  t = this._descriptionText(t);
  if (document.getElementById(cnvId + ds) === null) {
    document.getElementById(cnvId).innerHTML =
      '

';
  } else if (document.getElementById(cnvId + fds) === null) {
    document
      .getElementById(cnvId + ft)
      .insertAdjacentHTML('beforebegin', '

');
  }
  if (document.getElementById(cnvId + fds).innerHTML !== t) {
    document.getElementById(cnvId + fds).innerHTML = t;
  }
  //If display is LABEL creates a div adjacent to the canvas element with
  //description text.
  if (d === this.LABEL) {
    if (document.getElementById(cnvId + lb) === null) {
      document
        .getElementById(cnvId)
        .insertAdjacentHTML(
          'afterend',
          '

'
        );
    } else if (document.getElementById(cnvId + lds) === null) {
      document
        .getElementById(cnvId + lt)
        .insertAdjacentHTML('beforebegin', '

');
    }
    if (document.getElementById(cnvId + lds).innerHTML !== t) {
      document.getElementById(cnvId + lds).innerHTML = t;
    }
  }
};

/**
 * Helper function for describe() and describeElement().
 */

p5.prototype._descriptionText = function(t) {
  if (t === this.LABEL || t === this.FALLBACK) {
    throw new Error('description should not be LABEL or FALLBACK');
  }
  //if string does not end with '.'
  if (
    t.endsWith('.') === false &&
    t.endsWith('?') === false &&
    t.endsWith('!') === false
  ) {
    //add '.' to the end of string
    t = t + '.';
  }
  //if first character of string is not capitalized
  if (/^[A-Z]/.test(t) === false) {
    //capitalize first character of string
    t = t[0].toUpperCase() + t.slice(1);
  }
  return t;
};

/**
 * This function creates a screen-reader accessible
 * description for elements —shapes or groups of shapes that create
 * meaning together— in the canvas. The first paramater should
 * be the name of the element. The second parameter should be a string
 * with a description of the element. The third parameter is optional.
 * If specified, it determines how the element description is displayed.
 *
 * describeElement(name, text, LABEL)
 * displays the element description to all users as a
 *
 * tombstone or exhibit label/caption in a
 * <div class="p5Label"></div>
 * adjacent to the canvas. You can style it as you wish in your CSS.
 *
 * describeElement(name, text, FALLBACK)
 * makes the element description accessible to screen-reader users
 * only, in
 * a sub DOM inside the canvas element. If a second parameter is not
 * specified, by default, the element description will only be available
 * to screen-reader users.
 *
 * @method describeElement
 * @param  {String} name      name of the element
 * @param  {String} text      description of the element
 * @param  {Constant} [display] either LABEL or FALLBACK (Optional)
 *
 * @example
 *

 *
 * describe('Heart and yellow circle over pink background', LABEL);
 * noStroke();
 * background('pink');
 * describeElement('Circle', 'Yellow circle in the top left corner', LABEL);
 * fill('yellow');
 * ellipse(25, 25, 40, 40);
 * describeElement('Heart', 'red heart in the bottom right corner', LABEL);
 * fill('red');
 * ellipse(66.6, 66.6, 20, 20);
 * ellipse(83.2, 66.6, 20, 20);
 * triangle(91.2, 72.6, 75, 95, 58.6, 72.6);
 *
 *

 */

p5.prototype.describeElement = function(n, t, d) {
  p5._validateParameters('describeElement', arguments);
  if (typeof t !== 'string' || typeof n !== 'string') {
    return;
  }
  const cnvId = this.canvas.id;
  t = this._descriptionText(t);
  let nm = this._elementName(n);
  //Creates a sub DOM inside of the canvas with a table, populates
  //a row header cell with the name of the elements and adds the description
  //of the element in adjecent cell.
  if (document.getElementById(cnvId + ds) === null) {
    document.getElementById(cnvId).innerHTML =
      '

Canvas elements and their descriptions

';
  } else if (document.getElementById(cnvId + ft) === null) {
    document
      .getElementById(cnvId + fds)
      .insertAdjacentHTML(
        'afterend',
        '

Canvas elements and their descriptions

'
      );
  }
  if (document.getElementById(cnvId + fte + n) === null) {
    let tr = document.createElement('tr');
    tr.id = cnvId + fte + n;
    document.getElementById(cnvId + ft).appendChild(tr);
  }
  if (
    document.getElementById(cnvId + fte + n).innerHTML !==
    '' + nm + '	' + t + '	'
  ) {
    document.getElementById(cnvId + fte + n).innerHTML =
      '' + nm + '	' + t + '	';
  }
  //If display is LABEL creates a div adjacent to the canvas element with
  //a table, a row header cell with the name of the elements,
  //and adds the description of the element in adjecent cell.
  if (d === this.LABEL) {
    if (document.getElementById(cnvId + lb) === null) {
      document
        .getElementById(cnvId)
        .insertAdjacentHTML(
          'afterend',
          '

'
        );
    } else if (document.getElementById(cnvId + lt) === null) {
      document
        .getElementById(cnvId + lds)
        .insertAdjacentHTML(
          'afterend',
          '

'
        );
    }
    if (document.getElementById(cnvId + lte + n) === null) {
      let tr = document.createElement('tr');
      tr.id = cnvId + lte + n;
      document.getElementById(cnvId + lt).appendChild(tr);
    }

    if (
      document.getElementById(cnvId + lte + n).innerHTML !==
      '' + nm + '	' + t + '	'
    ) {
      document.getElementById(cnvId + lte + n).innerHTML =
        '' + nm + '	' + t + '	';
    }
  }
};
/**
 * Helper function for describeElement().
 */
p5.prototype._elementName = function(n) {
  if (n === this.LABEL || n === this.FALLBACK) {
    throw new Error('element name should not be LABEL or FALLBACK');
  }
  let lm = n[n.length - 1];
  //check if last character of string n is '.', ';', or ','
  if (lm === '.' || lm === ';' || lm === ',') {
    //replace last character with ':'
    n = n.replace(/.$/, ':');
    //if string n does not end with ':'
  } else if (n.endsWith(':') === false) {
    //add ':'' at the end of string
    n = n + ':';
  }
  //if first character of string is not capitalized
  if (/^[A-Z]/.test(n) === false) {
    //capitalize first character
    n = n[0].toUpperCase() + n.slice(1);
  }
  return n;
};

export default p5;
<commit_msg>simplify false<commit_after>/**
 * @module Environment
 * @submodule Environment
 * @for p5
 * @requires core
 */

import p5 from '../core/main';
const ds = '_Description'; //Fallback container
const fds = '_fds'; //Fallback description
const ft = '_ft'; //Fallback Table
const fte = '_fte_'; //Fallback Table Element
const lb = '_Label'; //Label container
const lds = '_lds'; //Label description
const lt = '_lt'; //Label Table
const lte = '_lte_'; //Label Table Element

/**
 * Creates a screen-reader accessible description for the canvas.
 * The first parameter should be a string with a description of the canvas.
 * The second parameter is optional. If specified, it determines how the
 * description is displayed.
 *
 * describe(text, LABEL) displays
 * the description to all users as a
 * tombstone or exhibit label/caption in a
 * <div class="p5Label"></div>
 * adjacent to the canvas. You can style it as you wish in your CSS.
 *
 * describe(text, FALLBACK) makes the
 * description accessible to screen-reader users only, in
 *
 * a sub DOM inside the canvas element. If a second parameter is not
 * specified, by default, the description will only be available to
 * screen-reader users.
 *
 * @method describe
 * @param  {String} text      description of the canvas
 * @param  {Constant} [display] either LABEL or FALLBACK (Optional)
 *
 * @example
 *

 *
 * describe('pink square with red heart in the bottom right corner', LABEL);
 * background('pink');
 * fill('red');
 * noStroke();
 * ellipse(67, 67, 20, 20);
 * ellipse(83, 67, 20, 20);
 * triangle(91, 73, 75, 95, 59, 73);
 *
 *

 *
 *

 *
 * let x = 0;
 * function draw() {
 *   if (x > 100) {
 *     x = 0;
 *   }
 *   background(220);
 *   fill(0, 255, 0);
 *   ellipse(x, 50, 40, 40);
 *   x = x + 0.1;
 *   describe('green circle at x pos ' + round(x) + ' moving to the right');
 * }
 *
 *

 *
 */

p5.prototype.describe = function(t, d) {
  const cnvId = this.canvas.id;
  p5._validateParameters('describe', arguments);
  //Creates a sub DOM inside of the canvas element and populates
  //it with description text.
  if (typeof t !== 'string') {
    return;
  }
  t = this._descriptionText(t);
  if (document.getElementById(cnvId + ds) === null) {
    document.getElementById(cnvId).innerHTML =
      '

';
  } else if (document.getElementById(cnvId + fds) === null) {
    document
      .getElementById(cnvId + ft)
      .insertAdjacentHTML('beforebegin', '

');
  }
  if (document.getElementById(cnvId + fds).innerHTML !== t) {
    document.getElementById(cnvId + fds).innerHTML = t;
  }
  //If display is LABEL creates a div adjacent to the canvas element with
  //description text.
  if (d === this.LABEL) {
    if (document.getElementById(cnvId + lb) === null) {
      document
        .getElementById(cnvId)
        .insertAdjacentHTML(
          'afterend',
          '

'
        );
    } else if (document.getElementById(cnvId + lds) === null) {
      document
        .getElementById(cnvId + lt)
        .insertAdjacentHTML('beforebegin', '

');
    }
    if (document.getElementById(cnvId + lds).innerHTML !== t) {
      document.getElementById(cnvId + lds).innerHTML = t;
    }
  }
};

/**
 * Helper function for describe() and describeElement().
 */

p5.prototype._descriptionText = function(t) {
  if (t === this.LABEL || t === this.FALLBACK) {
    throw new Error('description should not be LABEL or FALLBACK');
  }
  //if string does not end with '.'
  if (!t.endsWith('.') && !t.endsWith('?') && !t.endsWith('!')) {
    //add '.' to the end of string
    t = t + '.';
  }
  //if first character of string is not capitalized
  if (!/^[A-Z]/.test(t)) {
    //capitalize first character of string
    t = t[0].toUpperCase() + t.slice(1);
  }
  return t;
};

/**
 * This function creates a screen-reader accessible
 * description for elements —shapes or groups of shapes that create
 * meaning together— in the canvas. The first paramater should
 * be the name of the element. The second parameter should be a string
 * with a description of the element. The third parameter is optional.
 * If specified, it determines how the element description is displayed.
 *
 * describeElement(name, text, LABEL)
 * displays the element description to all users as a
 *
 * tombstone or exhibit label/caption in a
 * <div class="p5Label"></div>
 * adjacent to the canvas. You can style it as you wish in your CSS.
 *
 * describeElement(name, text, FALLBACK)
 * makes the element description accessible to screen-reader users
 * only, in
 * a sub DOM inside the canvas element. If a second parameter is not
 * specified, by default, the element description will only be available
 * to screen-reader users.
 *
 * @method describeElement
 * @param  {String} name      name of the element
 * @param  {String} text      description of the element
 * @param  {Constant} [display] either LABEL or FALLBACK (Optional)
 *
 * @example
 *

 *
 * describe('Heart and yellow circle over pink background', LABEL);
 * noStroke();
 * background('pink');
 * describeElement('Circle', 'Yellow circle in the top left corner', LABEL);
 * fill('yellow');
 * ellipse(25, 25, 40, 40);
 * describeElement('Heart', 'red heart in the bottom right corner', LABEL);
 * fill('red');
 * ellipse(66.6, 66.6, 20, 20);
 * ellipse(83.2, 66.6, 20, 20);
 * triangle(91.2, 72.6, 75, 95, 58.6, 72.6);
 *
 *

 */

p5.prototype.describeElement = function(n, t, d) {
  p5._validateParameters('describeElement', arguments);
  if (typeof t !== 'string' || typeof n !== 'string') {
    return;
  }
  const cnvId = this.canvas.id;
  t = this._descriptionText(t);
  let nm = this._elementName(n);
  //Creates a sub DOM inside of the canvas with a table, populates
  //a row header cell with the name of the elements and adds the description
  //of the element in adjecent cell.
  if (document.getElementById(cnvId + ds) === null) {
    document.getElementById(cnvId).innerHTML =
      '

Canvas elements and their descriptions

';
  } else if (document.getElementById(cnvId + ft) === null) {
    document
      .getElementById(cnvId + fds)
      .insertAdjacentHTML(
        'afterend',
        '

Canvas elements and their descriptions

'
      );
  }
  if (document.getElementById(cnvId + fte + n) === null) {
    let tr = document.createElement('tr');
    tr.id = cnvId + fte + n;
    document.getElementById(cnvId + ft).appendChild(tr);
  }
  if (
    document.getElementById(cnvId + fte + n).innerHTML !==
    '' + nm + '	' + t + '	'
  ) {
    document.getElementById(cnvId + fte + n).innerHTML =
      '' + nm + '	' + t + '	';
  }
  //If display is LABEL creates a div adjacent to the canvas element with
  //a table, a row header cell with the name of the elements,
  //and adds the description of the element in adjecent cell.
  if (d === this.LABEL) {
    if (document.getElementById(cnvId + lb) === null) {
      document
        .getElementById(cnvId)
        .insertAdjacentHTML(
          'afterend',
          '

'
        );
    } else if (document.getElementById(cnvId + lt) === null) {
      document
        .getElementById(cnvId + lds)
        .insertAdjacentHTML(
          'afterend',
          '

'
        );
    }
    if (document.getElementById(cnvId + lte + n) === null) {
      let tr = document.createElement('tr');
      tr.id = cnvId + lte + n;
      document.getElementById(cnvId + lt).appendChild(tr);
    }

    if (
      document.getElementById(cnvId + lte + n).innerHTML !==
      '' + nm + '	' + t + '	'
    ) {
      document.getElementById(cnvId + lte + n).innerHTML =
        '' + nm + '	' + t + '	';
    }
  }
};
/**
 * Helper function for describeElement().
 */
p5.prototype._elementName = function(n) {
  if (n === this.LABEL || n === this.FALLBACK) {
    throw new Error('element name should not be LABEL or FALLBACK');
  }
  let lm = n[n.length - 1];
  //check if last character of string n is '.', ';', or ','
  if (lm === '.' || lm === ';' || lm === ',') {
    //replace last character with ':'
    n = n.replace(/.$/, ':');
    //if string n does not end with ':'
  } else if (!n.endsWith(':')) {
    //add ':'' at the end of string
    n = n + ':';
  }
  //if first character of string is not capitalized
  if (!/^[A-Z]/.test(n)) {
    //capitalize first character
    n = n[0].toUpperCase() + n.slice(1);
  }
  return n;
};

export default p5;
<|endoftext|>


<commit_before>const MicroModal = (() => {
  'use strict'

  const FOCUSABLE_ELEMENTS = [
    'a[href]',
    'area[href]',
    'input:not([disabled]):not([type="hidden"]):not([aria-hidden])',
    'select:not([disabled]):not([aria-hidden])',
    'textarea:not([disabled]):not([aria-hidden])',
    'button:not([disabled]):not([aria-hidden])',
    'iframe',
    'object',
    'embed',
    '[contenteditable]',
    '[tabindex]:not([tabindex^="-"])'
  ]

  class Modal {
    constructor ({
      targetModal,
      triggers = [],
      onShow = () => { },
      onClose = () => { },
      openTrigger = 'data-micromodal-trigger',
      closeTrigger = 'data-micromodal-close',
      disableScroll = false,
      disableFocus = false,
      awaitCloseAnimation = false,
      awaitOpenAnimation = false,
      debugMode = false
    }) {
      // Save a reference of the modal
      this.modal = document.getElementById(targetModal)

      // Save a reference to the passed config
      this.config = { debugMode, disableScroll, openTrigger, closeTrigger, onShow, onClose, awaitCloseAnimation, awaitOpenAnimation, disableFocus }

      // Register click events only if pre binding eventListeners
      if (triggers.length > 0) this.registerTriggers(...triggers)

      // pre bind functions for event listeners
      this.onClick = this.onClick.bind(this)
      this.onKeydown = this.onKeydown.bind(this)
    }

    /**
     * Loops through all openTriggers and binds click event
     * @param  {array} triggers [Array of node elements]
     * @return {void}
     */
    registerTriggers (...triggers) {
      triggers.filter(Boolean).forEach(trigger => {
        trigger.addEventListener('click', event => this.showModal(event))
      })
    }

    showModal () {
      this.activeElement = document.activeElement
      this.modal.setAttribute('aria-hidden', 'false')
      this.modal.classList.add('is-open')
      this.scrollBehaviour('disable')
      this.addEventListeners()

      if (this.config.awaitOpenAnimation) {
        const handler = () => {
          this.modal.removeEventListener('animationend', handler, false)
          this.setFocusToFirstNode()
        }
        this.modal.addEventListener('animationend', handler, false)
      } else {
        this.setFocusToFirstNode()
      }

      this.config.onShow(this.modal, this.activeElement)
    }

    closeModal () {
      const modal = this.modal
      this.modal.setAttribute('aria-hidden', 'true')
      this.removeEventListeners()
      this.scrollBehaviour('enable')
      if (this.activeElement) {
        this.activeElement.focus()
      }
      this.config.onClose(this.modal)

      if (this.config.awaitCloseAnimation) {
        this.modal.addEventListener('animationend', function handler () {
          modal.classList.remove('is-open')
          modal.removeEventListener('animationend', handler, false)
        }, false)
      } else {
        modal.classList.remove('is-open')
      }
    }

    closeModalById (targetModal) {
      this.modal = document.getElementById(targetModal)
      if (this.modal) this.closeModal()
    }

    scrollBehaviour (toggle) {
      if (!this.config.disableScroll) return
      const body = document.querySelector('body')
      switch (toggle) {
        case 'enable':
          Object.assign(body.style, { overflow: '', height: '' })
          break
        case 'disable':
          Object.assign(body.style, { overflow: 'hidden', height: '100vh' })
          break
        default:
      }
    }

    addEventListeners () {
      this.modal.addEventListener('touchstart', this.onClick)
      this.modal.addEventListener('click', this.onClick)
      document.addEventListener('keydown', this.onKeydown)
    }

    removeEventListeners () {
      this.modal.removeEventListener('touchstart', this.onClick)
      this.modal.removeEventListener('click', this.onClick)
      document.removeEventListener('keydown', this.onKeydown)
    }

    onClick (event) {
      if (event.target.hasAttribute(this.config.closeTrigger)) {
        this.closeModal()
        event.preventDefault()
      }
    }

    onKeydown (event) {
      if (event.keyCode === 27) this.closeModal(event)
      if (event.keyCode === 9) this.maintainFocus(event)
    }

    getFocusableNodes () {
      const nodes = this.modal.querySelectorAll(FOCUSABLE_ELEMENTS)
      return Array(...nodes)
    }

    setFocusToFirstNode () {
      if (this.config.disableFocus) return
      const focusableNodes = this.getFocusableNodes()
      if (focusableNodes.length) focusableNodes[0].focus()
    }

    maintainFocus (event) {
      const focusableNodes = this.getFocusableNodes()

      // if disableFocus is true
      if (!this.modal.contains(document.activeElement)) {
        focusableNodes[0].focus()
      } else {
        const focusedItemIndex = focusableNodes.indexOf(document.activeElement)

        if (event.shiftKey && focusedItemIndex === 0) {
          focusableNodes[focusableNodes.length - 1].focus()
          event.preventDefault()
        }

        if (!event.shiftKey && focusedItemIndex === focusableNodes.length - 1) {
          focusableNodes[0].focus()
          event.preventDefault()
        }
      }
    }
  }

  /**
   * Modal prototype ends.
   * Here on code is responsible for detecting and
   * auto binding event handlers on modal triggers
   */

  // Keep a reference to the opened modal
  let activeModal = null

  /**
   * Generates an associative array of modals and it's
   * respective triggers
   * @param  {array} triggers     An array of all triggers
   * @param  {string} triggerAttr The data-attribute which triggers the module
   * @return {array}
   */
  const generateTriggerMap = (triggers, triggerAttr) => {
    const triggerMap = []

    triggers.forEach(trigger => {
      const targetModal = trigger.attributes[triggerAttr].value
      if (triggerMap[targetModal] === undefined) triggerMap[targetModal] = []
      triggerMap[targetModal].push(trigger)
    })

    return triggerMap
  }

  /**
   * Validates whether a modal of the given id exists
   * in the DOM
   * @param  {number} id  The id of the modal
   * @return {boolean}
   */
  const validateModalPresence = id => {
    if (!document.getElementById(id)) {
      console.warn(`MicroModal: \u2757Seems like you have missed %c'${ id }'`, 'background-color: #f8f9fa;color: #50596c;font-weight: bold;', 'ID somewhere in your code. Refer example below to resolve it.')
      console.warn(`%cExample:`, 'background-color: #f8f9fa;color: #50596c;font-weight: bold;', `<div class="modal" id="${ id }"></div>`)
      return false
    }
  }

  /**
   * Validates if there are modal triggers present
   * in the DOM
   * @param  {array} triggers An array of data-triggers
   * @return {boolean}
   */
  const validateTriggerPresence = triggers => {
    if (triggers.length <= 0) {
      console.warn(`MicroModal: \u2757Please specify at least one %c'micromodal-trigger'`, 'background-color: #f8f9fa;color: #50596c;font-weight: bold;', 'data attribute.')
      console.warn(`%cExample:`, 'background-color: #f8f9fa;color: #50596c;font-weight: bold;', `<a href="#" data-micromodal-trigger="my-modal"></a>`)
      return false
    }
  }

  /**
   * Checks if triggers and their corresponding modals
   * are present in the DOM
   * @param  {array} triggers   Array of DOM nodes which have data-triggers
   * @param  {array} triggerMap Associative array of modals and their triggers
   * @return {boolean}
   */
  const validateArgs = (triggers, triggerMap) => {
    validateTriggerPresence(triggers)
    if (!triggerMap) return true
    for (var id in triggerMap) validateModalPresence(id)
    return true
  }

  /**
   * Binds click handlers to all modal triggers
   * @param  {object} config [description]
   * @return void
   */
  const init = config => {
    // Create an config object with default openTrigger
    const options = Object.assign({}, { openTrigger: 'data-micromodal-trigger' }, config)

    // Collects all the nodes with the trigger
    const triggers = [...document.querySelectorAll(`[${ options.openTrigger }]`)]

    // Makes a mappings of modals with their trigger nodes
    const triggerMap = generateTriggerMap(triggers, options.openTrigger)

    // Checks if modals and triggers exist in dom
    if (options.debugMode === true && validateArgs(triggers, triggerMap) === false) return

    // For every target modal creates a new instance
    for (var key in triggerMap) {
      let value = triggerMap[key]
      options.targetModal = key
      options.triggers = [...value]
      activeModal = new Modal(options) // eslint-disable-line no-new
    }
  }

  /**
   * Shows a particular modal
   * @param  {string} targetModal [The id of the modal to display]
   * @param  {object} config [The configuration object to pass]
   * @return {void}
   */
  const show = (targetModal, config) => {
    const options = config || {}
    options.targetModal = targetModal

    // Checks if modals and triggers exist in dom
    if (options.debugMode === true && validateModalPresence(targetModal) === false) return

    // stores reference to active modal
    activeModal = new Modal(options) // eslint-disable-line no-new
    activeModal.showModal()
  }

  /**
   * Closes the active modal
   * @param  {string} targetModal [The id of the modal to close]
   * @return {void}
   */
  const close = targetModal => {
    targetModal ? activeModal.closeModalById(targetModal) : activeModal.closeModal()
  }

  return { init, show, close }
})()

export default MicroModal
<commit_msg>Add conditional to read focusableNodes<commit_after>const MicroModal = (() => {
  'use strict'

  const FOCUSABLE_ELEMENTS = [
    'a[href]',
    'area[href]',
    'input:not([disabled]):not([type="hidden"]):not([aria-hidden])',
    'select:not([disabled]):not([aria-hidden])',
    'textarea:not([disabled]):not([aria-hidden])',
    'button:not([disabled]):not([aria-hidden])',
    'iframe',
    'object',
    'embed',
    '[contenteditable]',
    '[tabindex]:not([tabindex^="-"])'
  ]

  class Modal {
    constructor ({
      targetModal,
      triggers = [],
      onShow = () => { },
      onClose = () => { },
      openTrigger = 'data-micromodal-trigger',
      closeTrigger = 'data-micromodal-close',
      disableScroll = false,
      disableFocus = false,
      awaitCloseAnimation = false,
      awaitOpenAnimation = false,
      debugMode = false
    }) {
      // Save a reference of the modal
      this.modal = document.getElementById(targetModal)

      // Save a reference to the passed config
      this.config = { debugMode, disableScroll, openTrigger, closeTrigger, onShow, onClose, awaitCloseAnimation, awaitOpenAnimation, disableFocus }

      // Register click events only if pre binding eventListeners
      if (triggers.length > 0) this.registerTriggers(...triggers)

      // pre bind functions for event listeners
      this.onClick = this.onClick.bind(this)
      this.onKeydown = this.onKeydown.bind(this)
    }

    /**
     * Loops through all openTriggers and binds click event
     * @param  {array} triggers [Array of node elements]
     * @return {void}
     */
    registerTriggers (...triggers) {
      triggers.filter(Boolean).forEach(trigger => {
        trigger.addEventListener('click', event => this.showModal(event))
      })
    }

    showModal () {
      this.activeElement = document.activeElement
      this.modal.setAttribute('aria-hidden', 'false')
      this.modal.classList.add('is-open')
      this.scrollBehaviour('disable')
      this.addEventListeners()

      if (this.config.awaitOpenAnimation) {
        const handler = () => {
          this.modal.removeEventListener('animationend', handler, false)
          this.setFocusToFirstNode()
        }
        this.modal.addEventListener('animationend', handler, false)
      } else {
        this.setFocusToFirstNode()
      }

      this.config.onShow(this.modal, this.activeElement)
    }

    closeModal () {
      const modal = this.modal
      this.modal.setAttribute('aria-hidden', 'true')
      this.removeEventListeners()
      this.scrollBehaviour('enable')
      if (this.activeElement) {
        this.activeElement.focus()
      }
      this.config.onClose(this.modal)

      if (this.config.awaitCloseAnimation) {
        this.modal.addEventListener('animationend', function handler () {
          modal.classList.remove('is-open')
          modal.removeEventListener('animationend', handler, false)
        }, false)
      } else {
        modal.classList.remove('is-open')
      }
    }

    closeModalById (targetModal) {
      this.modal = document.getElementById(targetModal)
      if (this.modal) this.closeModal()
    }

    scrollBehaviour (toggle) {
      if (!this.config.disableScroll) return
      const body = document.querySelector('body')
      switch (toggle) {
        case 'enable':
          Object.assign(body.style, { overflow: '', height: '' })
          break
        case 'disable':
          Object.assign(body.style, { overflow: 'hidden', height: '100vh' })
          break
        default:
      }
    }

    addEventListeners () {
      this.modal.addEventListener('touchstart', this.onClick)
      this.modal.addEventListener('click', this.onClick)
      document.addEventListener('keydown', this.onKeydown)
    }

    removeEventListeners () {
      this.modal.removeEventListener('touchstart', this.onClick)
      this.modal.removeEventListener('click', this.onClick)
      document.removeEventListener('keydown', this.onKeydown)
    }

    onClick (event) {
      if (event.target.hasAttribute(this.config.closeTrigger)) {
        this.closeModal()
        event.preventDefault()
      }
    }

    onKeydown (event) {
      if (event.keyCode === 27) this.closeModal(event)
      if (event.keyCode === 9) this.maintainFocus(event)
    }

    getFocusableNodes () {
      const nodes = this.modal.querySelectorAll(FOCUSABLE_ELEMENTS)
      return Array(...nodes)
    }

    setFocusToFirstNode () {
      if (this.config.disableFocus) return
      const focusableNodes = this.getFocusableNodes()
      if (focusableNodes.length) focusableNodes[0].focus()
    }

    maintainFocus (event) {
      const focusableNodes = this.getFocusableNodes()

      // if disableFocus is true
      if (!this.modal.contains(document.activeElement)) {
        focusableNodes[0].focus()
      } else {
        const focusedItemIndex = focusableNodes.indexOf(document.activeElement)

        if (event.shiftKey && focusedItemIndex === 0) {
          focusableNodes[focusableNodes.length - 1].focus()
          event.preventDefault()
        }

        if (!event.shiftKey && focusableNodes.length > 0 && focusedItemIndex === focusableNodes.length - 1) {
          focusableNodes[0].focus()
          event.preventDefault()
        }
      }
    }
  }

  /**
   * Modal prototype ends.
   * Here on code is responsible for detecting and
   * auto binding event handlers on modal triggers
   */

  // Keep a reference to the opened modal
  let activeModal = null

  /**
   * Generates an associative array of modals and it's
   * respective triggers
   * @param  {array} triggers     An array of all triggers
   * @param  {string} triggerAttr The data-attribute which triggers the module
   * @return {array}
   */
  const generateTriggerMap = (triggers, triggerAttr) => {
    const triggerMap = []

    triggers.forEach(trigger => {
      const targetModal = trigger.attributes[triggerAttr].value
      if (triggerMap[targetModal] === undefined) triggerMap[targetModal] = []
      triggerMap[targetModal].push(trigger)
    })

    return triggerMap
  }

  /**
   * Validates whether a modal of the given id exists
   * in the DOM
   * @param  {number} id  The id of the modal
   * @return {boolean}
   */
  const validateModalPresence = id => {
    if (!document.getElementById(id)) {
      console.warn(`MicroModal: \u2757Seems like you have missed %c'${ id }'`, 'background-color: #f8f9fa;color: #50596c;font-weight: bold;', 'ID somewhere in your code. Refer example below to resolve it.')
      console.warn(`%cExample:`, 'background-color: #f8f9fa;color: #50596c;font-weight: bold;', `<div class="modal" id="${ id }"></div>`)
      return false
    }
  }

  /**
   * Validates if there are modal triggers present
   * in the DOM
   * @param  {array} triggers An array of data-triggers
   * @return {boolean}
   */
  const validateTriggerPresence = triggers => {
    if (triggers.length <= 0) {
      console.warn(`MicroModal: \u2757Please specify at least one %c'micromodal-trigger'`, 'background-color: #f8f9fa;color: #50596c;font-weight: bold;', 'data attribute.')
      console.warn(`%cExample:`, 'background-color: #f8f9fa;color: #50596c;font-weight: bold;', `<a href="#" data-micromodal-trigger="my-modal"></a>`)
      return false
    }
  }

  /**
   * Checks if triggers and their corresponding modals
   * are present in the DOM
   * @param  {array} triggers   Array of DOM nodes which have data-triggers
   * @param  {array} triggerMap Associative array of modals and their triggers
   * @return {boolean}
   */
  const validateArgs = (triggers, triggerMap) => {
    validateTriggerPresence(triggers)
    if (!triggerMap) return true
    for (var id in triggerMap) validateModalPresence(id)
    return true
  }

  /**
   * Binds click handlers to all modal triggers
   * @param  {object} config [description]
   * @return void
   */
  const init = config => {
    // Create an config object with default openTrigger
    const options = Object.assign({}, { openTrigger: 'data-micromodal-trigger' }, config)

    // Collects all the nodes with the trigger
    const triggers = [...document.querySelectorAll(`[${ options.openTrigger }]`)]

    // Makes a mappings of modals with their trigger nodes
    const triggerMap = generateTriggerMap(triggers, options.openTrigger)

    // Checks if modals and triggers exist in dom
    if (options.debugMode === true && validateArgs(triggers, triggerMap) === false) return

    // For every target modal creates a new instance
    for (var key in triggerMap) {
      let value = triggerMap[key]
      options.targetModal = key
      options.triggers = [...value]
      activeModal = new Modal(options) // eslint-disable-line no-new
    }
  }

  /**
   * Shows a particular modal
   * @param  {string} targetModal [The id of the modal to display]
   * @param  {object} config [The configuration object to pass]
   * @return {void}
   */
  const show = (targetModal, config) => {
    const options = config || {}
    options.targetModal = targetModal

    // Checks if modals and triggers exist in dom
    if (options.debugMode === true && validateModalPresence(targetModal) === false) return

    // stores reference to active modal
    activeModal = new Modal(options) // eslint-disable-line no-new
    activeModal.showModal()
  }

  /**
   * Closes the active modal
   * @param  {string} targetModal [The id of the modal to close]
   * @return {void}
   */
  const close = targetModal => {
    targetModal ? activeModal.closeModalById(targetModal) : activeModal.closeModal()
  }

  return { init, show, close }
})()

export default MicroModal
<|endoftext|>


<commit_before>#!/usr/bin/env node
var child_process = require('child_process');

var log = function() {
	var args = Array.prototype.map.call(arguments, function(value) {
		if (typeof value === 'string') {
			return value;
		} else {
			return JSON.stringify(value, null, '\t')
		}
	});
	process.stdout.write(args.join(" ") + '\n');
}

module.exports = function(context) {
	var async = context.requireCordovaModule('cordova-lib/node_modules/request/node_modules/form-data/node_modules/async');
	var fs = context.requireCordovaModule('fs');
	var path = context.requireCordovaModule('path');
	var deferral = context.requireCordovaModule('q').defer();

	var platformDir = path.join(context.opts.projectRoot, 'platforms', 'ios');

	var podfile = function(next) {
		var target = path.join(platformDir, 'Podfile');
		var lines = ["pod 'Fabric'",
		             "pod 'Crashlytics'"];
		log("Adding ", target, ": ", lines);
		fs.appendFile(target, lines.join('\n'), 'utf-8', next);
	}

	var addInitCode = function(next) {
		var target_name = 'AppDelegate.m';
		var findFiles = function(dir, next) {
			async.waterfall(
					[
					function(next) {
						fs.readdir(dir, next);
					},
					function(list, next) {
						async.map(list, function(item, next) {
							var file = path.resolve(dir, item);
							async.waterfall(
									[
									function(next) {
										fs.stat(file, next);
									},
									function(stat, next) {
										if (stat.isDirectory()) {
											findFiles(file, next);
										} else {
											next(null, (path.basename(file) === target_name ? file : null));
										}
									}
									 ],next);
						}, next);
					},
					function(list, next) {
						async.filter(list, function(item) {
							return item !== null;
						}, next);
					}
					 ], next);
		}
		var modify = function(target, next) {
			log("Modifying ", file);
			next(null, null);
		}
		async.waterfall(
				[
				function(next) {
					findFiles(platformDir, next);
				},
				function(files, next) {
					log("Found files: ", target_name, files);
					if (files) {
						next(null, files[0]);
					} else {
						next('NotFound: ' + target_name);
					}
				},
				modify,
				 ],next);
	}

	var fixXcodeproj = function(next) {
		var script = path.join(path.dirname(context.scriptLocation), 'after_plugin_install-fix_xcodeproj.rb');
		var child = child_process.execFile(script, [context.opts.plugin.id], {cwd : platformDir}, next);
		child.stdout.on('data', function(data) {
			process.stdout.write(data);
		});
		child.stderr.on('data', function(data) {
			process.stderr.write(data);
		});
	}

	var main = function() {
		async.parallel(
				{
					'Podfile': podfile,
					'Add init code': addInitCode
				},
				function(err, result) {
					if (err) {
						deferral.reject(err);
					} else {
						deferral.resolve(result);
					}
				});
	}
	main();
	return deferral.promise;
};
<commit_msg>ログを細かく出力<commit_after>#!/usr/bin/env node
var child_process = require('child_process');

var log = function() {
	var args = Array.prototype.map.call(arguments, function(value) {
		if (typeof value === 'string') {
			return value;
		} else {
			return JSON.stringify(value, null, '\t')
		}
	});
	process.stdout.write(args.join(" ") + '\n');
}

module.exports = function(context) {
	var async = context.requireCordovaModule('cordova-lib/node_modules/request/node_modules/form-data/node_modules/async');
	var fs = context.requireCordovaModule('fs');
	var path = context.requireCordovaModule('path');
	var deferral = context.requireCordovaModule('q').defer();

	var platformDir = path.join(context.opts.projectRoot, 'platforms', 'ios');

	var podfile = function(next) {
		var target = path.join(platformDir, 'Podfile');
		var lines = ["pod 'Fabric'",
		             "pod 'Crashlytics'"];
		log("Adding ", target, ": ", lines);
		fs.appendFile(target, lines.join('\n'), 'utf-8', next);
	}

	var addInitCode = function(next) {
		var target_name = 'AppDelegate.m';
		var findFiles = function(dir, next) {
			async.waterfall(
					[
					function(next) {
						log("Searching in", dir);
						fs.readdir(dir, next);
					},
					function(list, next) {
						async.map(list, function(item, next) {
							var file = path.resolve(dir, item);
							log("Checking ", file);
							async.waterfall(
									[
									function(next) {
										fs.stat(file, next);
									},
									function(stat, next) {
										if (stat.isDirectory()) {
											findFiles(file, next);
										} else {
											var result = path.basename(file) === target_name ? file : null;
											log("Maching: ", result);
											next(null, result);
										}
									}
									 ],next);
						}, next);
					},
					function(list, next) {
						log("Finder result list: ", list);
						async.filter(list, function(item) {
							return item !== null;
						}, next);
					}
					 ], next);
		}
		var modify = function(target, next) {
			log("Modifying ", file);
			next(null, null);
		}
		async.waterfall(
				[
				function(next) {
					findFiles(platformDir, next);
				},
				function(files, next) {
					log("Found files: ", target_name, files);
					if (files) {
						next(null, files[0]);
					} else {
						next('NotFound: ' + target_name);
					}
				},
				modify,
				 ],next);
	}

	var fixXcodeproj = function(next) {
		var script = path.join(path.dirname(context.scriptLocation), 'after_plugin_install-fix_xcodeproj.rb');
		var child = child_process.execFile(script, [context.opts.plugin.id], {cwd : platformDir}, next);
		child.stdout.on('data', function(data) {
			process.stdout.write(data);
		});
		child.stderr.on('data', function(data) {
			process.stderr.write(data);
		});
	}

	var main = function() {
		async.parallel(
				{
					'Podfile': podfile,
					'Add init code': addInitCode
				},
				function(err, result) {
					if (err) {
						deferral.reject(err);
					} else {
						deferral.resolve(result);
					}
				});
	}
	main();
	return deferral.promise;
};
<|endoftext|>


<commit_before>/**
 * PostCSS webpack block.
 *
 * @see https://github.com/postcss/postcss-loader
 */

module.exports = postcss

/**
 * @param {PostCSSPlugin[]} [plugins]                   Will read `postcss.config.js` file if not supplied.
 * @param {object}          [options]
 * @param {RegExp|Function|string}  [options.exclude]     Directories to exclude.
 * @param {string}                  [options.parser]      Package name of custom PostCSS parser to use.
 * @param {string}                  [options.stringifier] Package name of custom PostCSS stringifier to use.
 * @param {string}                  [options.syntax]      Package name of custom PostCSS parser/stringifier to use.
 * @return {Function}
 */
function postcss (plugins, options) {
  plugins = plugins || []
  options = options || {}

  // https://github.com/postcss/postcss-loader#options
  const postcssOptions = Object.assign(
    {},
    options.parser && { parser: options.parser },
    options.stringifier && { stringifier: options.stringifier },
    options.syntax && { syntax: options.syntax }
  )

  return (context) => Object.assign(
    {
      module: {
        loaders: [
          Object.assign({
            test: context.fileType('text/css'),
            loaders: [ 'style-loader', 'css-loader', 'postcss-loader?' + JSON.stringify(postcssOptions) ]
          }, options.exclude ? {
            exclude: Array.isArray(options.exclude) ? options.exclude : [ options.exclude ]
          } : {})
        ]
      }
    },
    plugins ? createPostcssPluginsConfig(context.webpack, plugins) : {}
  )
}

function createPostcssPluginsConfig (webpack, plugins) {
  const isWebpack2 = typeof webpack.validateSchema !== 'undefined'

  if (isWebpack2) {
    return {
      plugins: [
        new webpack.LoaderOptionsPlugin({
          options: {
            postcss: plugins,

            // Hacky fix for a strange issue involving the postcss-loader, sass-loader and webpack@2
            // (see https://github.com/andywer/webpack-blocks/issues/116)
            // Might be removed again once the `sass` block uses a newer `sass-loader`
            context: '/'
          }
        })
      ]
    }
  } else {
    return {
      postcss: plugins
    }
  }
}
<commit_msg>Remove webpack2 conditional in postcss<commit_after>/**
 * PostCSS webpack block.
 *
 * @see https://github.com/postcss/postcss-loader
 */

module.exports = postcss

/**
 * @param {PostCSSPlugin[]} [plugins]                   Will read `postcss.config.js` file if not supplied.
 * @param {object}          [options]
 * @param {RegExp|Function|string}  [options.exclude]     Directories to exclude.
 * @param {string}                  [options.parser]      Package name of custom PostCSS parser to use.
 * @param {string}                  [options.stringifier] Package name of custom PostCSS stringifier to use.
 * @param {string}                  [options.syntax]      Package name of custom PostCSS parser/stringifier to use.
 * @return {Function}
 */
function postcss (plugins, options) {
  plugins = plugins || []
  options = options || {}

  // https://github.com/postcss/postcss-loader#options
  const postcssOptions = Object.assign(
    {},
    options.parser && { parser: options.parser },
    options.stringifier && { stringifier: options.stringifier },
    options.syntax && { syntax: options.syntax }
  )

  return (context) => Object.assign(
    {
      module: {
        loaders: [
          Object.assign({
            test: context.fileType('text/css'),
            loaders: [ 'style-loader', 'css-loader', 'postcss-loader?' + JSON.stringify(postcssOptions) ]
          }, options.exclude ? {
            exclude: Array.isArray(options.exclude) ? options.exclude : [ options.exclude ]
          } : {})
        ]
      }
    },
    plugins ? createPostcssPluginsConfig(context.webpack, plugins) : {}
  )
}

function createPostcssPluginsConfig (webpack, plugins) {
  return {
    plugins: [
      new webpack.LoaderOptionsPlugin({
        options: {
          postcss: plugins,

          // Hacky fix for a strange issue involving the postcss-loader, sass-loader and webpack@2
          // (see https://github.com/andywer/webpack-blocks/issues/116)
          // Might be removed again once the `sass` block uses a newer `sass-loader`
          context: '/'
        }
      })
    ]
  }
}
<|endoftext|>


<commit_before>'use strict';

describe ("Scoreboard", function() {
  var scoreboard
  var game

  beforeEach(function(){
    scoreboard = new Scoreboard()
    game = jasmine.createSpy("Game")
  })

  it("Should initialize with an empty scores array", function(){
    expect(scoreboard.scores).toEqual([])
  })

  it("should initialize with an empty totalScores array", function(){
    expect(scoreboard.totalScores).toEqual([])
  })

  it("should initialize with a calculated total of 0", function(){
    expect(scoreboard.totalCalculated).toEqual(0)
  })

  it("it should initialize with the maximum pins a player can knock down in one throw", function(){
    expect(scoreboard.MAXIMUM).toEqual(10)
  })

  it("should place the first roll score result into the scores array", function(){
    scoreboard.scoreFirstRoll(4)
    expect(scoreboard.scores).toContain(4)
  })

  it("should place the second roll score result into the scores array", function(){
    scoreboard.scoreSecondRoll(3)
    expect(scoreboard.scores).toContain(3)
  })

  it("should place the bonus third roll score into the scores array", function(){
    scoreboard.scoreBonusRoll(5)
    expect(scoreboard.scores).toContain(5)
  })

  it("should place the total of each set of rolls", function(){
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(2)
    scoreboard.scoreSecondRoll(1)
    scoreboard.bonusPoints()
    expect(scoreboard.totalScores).toEqual([13, 3])
  })

  it("should return the calculation of two consecutive throws", function(){
    scoreboard.scoreFirstRoll(4)
    scoreboard.scoreSecondRoll(3)
    scoreboard.bonusPoints()
    scoreboard.calculatedTotal()
    expect(scoreboard.totalCalculated).toEqual(7)
  })

  it("should place the calculated score into the totalScores array", function(){
    scoreboard.scoreFirstRoll(5)
    scoreboard.scoreSecondRoll(1)
    scoreboard.calculateScores()
    expect(scoreboard.totalScores).toContain(6)
  })

  it("should return of a calculated score of a strike and the next two consecutive throws", function(){
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(5)
    scoreboard.scoreSecondRoll(1)
    expect(scoreboard._aStrike()).toEqual(16)
  })

  it("should place the total scores of three consecutive throws (first a strike) to totalScores", function(){
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(5)
    scoreboard.scoreSecondRoll(1)
    scoreboard.bonusPoints()
    expect(scoreboard.totalScores).toEqual([16, 6])
  })

  it("should return the calculated result of two consecutive strikes and score of roll one", function(){
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(5)
    scoreboard.scoreSecondRoll(1)
    scoreboard.bonusPoints()
    expect(scoreboard.totalScores).toEqual([25, 16, 6])
  })

  it("should return 30 when three strikes are scored in a row", function(){
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    expect(scoreboard.totalScores).toEqual([30])
  })

  it("should add the result of the calculation of the spare and the first roll of the next set to totalScores", function(){
    scoreboard.scoreFirstRoll(2)
    scoreboard.scoreSecondRoll(8)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(1)
    scoreboard.scoreSecondRoll(8)
    scoreboard.bonusPoints()
    expect(scoreboard.totalScores).toEqual([11,9])
  })

  it("should call the function strike when score is 10", function(){
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(3)
    scoreboard.scoreSecondRoll(4)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(5)
    scoreboard.scoreSecondRoll(5)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(5)
    scoreboard.scoreSecondRoll(3)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(7)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    expect(scoreboard.totalScores).toEqual([17, 7, 20, 20, 18, 8, 7])
  })

  it("should return the total score of all the scores", function(){
    scoreboard.totalScores = [17, 7, 20, 20, 18, 8, 7]
    expect(scoreboard.calculatedTotal()).toEqual(97)
  })

  it("should return Gutter Game! when total score is 0", function(){
    scoreboard.totalScores = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    expect(scoreboard.calculatedTotal()).toEqual("Gutter Game!")
  })

  it("should return Perfect Game! when total score is 300", function(){
    scoreboard.totalScores = [30, 30, 30, 30, 30, 30, 30, 30, 30, 30]
    expect(scoreboard.calculatedTotal()).toEqual("Perfect Game!")
  })

  it("should return Perfect Game! when total score is 300", function(){
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints();
    expect(scoreboard.calculatedTotal()).toEqual("Perfect Game!")
  });

});
<commit_msg>Improved test layout<commit_after>'use strict';

describe ("Scoreboard", function() {
  var scoreboard
  var game

  beforeEach(function(){
    scoreboard = new Scoreboard()
    game = jasmine.createSpy("Game")
  })

  it("Should initialize with an empty scores array", function(){
    expect(scoreboard.scores).toEqual([])
  })

  it("should initialize with an empty totalScores array", function(){
    expect(scoreboard.totalScores).toEqual([])
  })

  it("should initialize with a calculated total of 0", function(){
    expect(scoreboard.totalCalculated).toEqual(0)
  })

  it("it should initialize with the maximum pins a player can knock down in one throw", function(){
    expect(scoreboard.MAXIMUM).toEqual(10)
  })

  it("should place the first roll score result into the scores array", function(){
    scoreboard.scoreFirstRoll(4)
    expect(scoreboard.scores).toContain(4)
  })

  it("should place the second roll score result into the scores array", function(){
    scoreboard.scoreSecondRoll(3)
    expect(scoreboard.scores).toContain(3)
  })

  it("should place the bonus third roll score into the scores array", function(){
    scoreboard.scoreBonusRoll(5)
    expect(scoreboard.scores).toContain(5)
  })

  it("should place the total of each set of rolls", function(){
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(2)
    scoreboard.scoreSecondRoll(1)
    scoreboard.bonusPoints()
    expect(scoreboard.totalScores).toEqual([13, 3])
  })

  it("should return the calculation of two consecutive throws", function(){
    scoreboard.scoreFirstRoll(4)
    scoreboard.scoreSecondRoll(3)
    scoreboard.bonusPoints()
    scoreboard.calculatedTotal()
    expect(scoreboard.totalCalculated).toEqual(7)
  })

  it("should place the calculated score into the totalScores array", function(){
    scoreboard.scoreFirstRoll(5)
    scoreboard.scoreSecondRoll(1)
    scoreboard.calculateScores()
    expect(scoreboard.totalScores).toContain(6)
  })

  it("should return of a calculated score of a strike and the next two consecutive throws", function(){
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(5)
    scoreboard.scoreSecondRoll(1)
    expect(scoreboard._aStrike()).toEqual(16)
  })

  it("should place the total scores of three consecutive throws (first a strike) to totalScores", function(){
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(5)
    scoreboard.scoreSecondRoll(1)
    scoreboard.bonusPoints()
    expect(scoreboard.totalScores).toEqual([16, 6])
  })

  it("should return the calculated result of two consecutive strikes and score of roll one", function(){
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(5)
    scoreboard.scoreSecondRoll(1)
    scoreboard.bonusPoints()
    expect(scoreboard.totalScores).toEqual([25, 16, 6])
  })

  it("should return 30 when three strikes are scored in a row", function(){
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    expect(scoreboard.totalScores).toEqual([30])
  })

  it("should add the result of the calculation of the spare and the first roll of the next set to totalScores", function(){
    scoreboard.scoreFirstRoll(2)
    scoreboard.scoreSecondRoll(8)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(1)
    scoreboard.scoreSecondRoll(8)
    scoreboard.bonusPoints()
    expect(scoreboard.totalScores).toEqual([11,9])
  })

  it("should call the function strike when score is 10", function(){
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(3)
    scoreboard.scoreSecondRoll(4)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(5)
    scoreboard.scoreSecondRoll(5)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(10)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(5)
    scoreboard.scoreSecondRoll(3)
    scoreboard.bonusPoints()
    scoreboard.scoreFirstRoll(7)
    scoreboard.scoreSecondRoll(0)
    scoreboard.bonusPoints()
    expect(scoreboard.totalScores).toEqual([17, 7, 20, 20, 18, 8, 7])
  })

  it("should return the total score of all the scores", function(){
    scoreboard.totalScores = [17, 7, 20, 20, 18, 8, 7]
    expect(scoreboard.calculatedTotal()).toEqual(97)
  })

  it("should return Gutter Game! when total score is 0", function(){
    scoreboard.totalScores = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    expect(scoreboard.calculatedTotal()).toEqual("Gutter Game!")
  })

  it("should return Perfect Game! when total score is 300", function(){
    scoreboard.totalScores = [30, 30, 30, 30, 30, 30, 30, 30, 30, 30]
    expect(scoreboard.calculatedTotal()).toEqual("Perfect Game!")
  })

  it("should return Perfect Game! when total score is 300", function(){
    var i = 0;
     do {
       scoreboard.scoreFirstRoll(10)
       scoreboard.scoreSecondRoll(0)
       scoreboard.bonusPoints()
       i++;
     }
     while (i <12);
    expect(scoreboard.calculatedTotal()).toEqual("Perfect Game!")
  });

});
<|endoftext|>


<commit_before>import Node from '../Node.js';

function shouldRemoveParens ( expression, parent ) {
	if ( /^Object/.test( expression.getLeftHandSide().type ) || /^Object/.test( expression.getRightHandSide().type ) ) {
		return false;
	}

	if ( expression.type === 'CallExpression' ) {
		return expression.callee.type === 'FunctionExpression'; // TODO is this right?
	}

	if ( expression.type === 'FunctionExpression' ) {
		return (
			( parent.type === 'CallExpression' && parent.parent.type === 'ExpressionStatement' ) ||
			( parent.type === 'ExpressionStatement' && parent.parent.type === 'CallExpression' )
		);
	}

	const expressionPrecedence = expression.getPrecedence();
	const parentPrecedence = parent.getPrecedence();

	if ( parentPrecedence > expressionPrecedence ) return false;
	if ( expressionPrecedence > parentPrecedence ) return true;

	if ( expression.type === 'UnaryExpression' ) return true;
	if ( expression.type === 'AssignmentExpression' ) return true;
	if ( expression.type === 'LogicalExpression' || expression.type === 'BinaryExpression' ) {
		return ( parent.operator === '**' ? parent.right : parent.left ).contains( expression );
	}
}

export default class ParenthesizedExpression extends Node {
	getLeftHandSide () {
		let node = this;

		while ( node.type === 'ParenthesizedExpression' ) {
			node = node.expression;
		}

		if ( shouldRemoveParens( node, this.parent ) ) return node.getLeftHandSide();
		return node.parent;
	}

	getPrecedence () {
		let expression = this.expression;
		while ( expression.type === 'ParenthesizedExpression' ) expression = expression.expression;

		return shouldRemoveParens( expression, this.parent ) ? expression.getPrecedence() : 20;
	}

	getValue () {
		return this.expression.getValue();
	}

	minify ( code ) {
		let start = this.start;
		let end = this.end;
		let parent = this.parent;

		let expression = this.expression;
		while ( expression.type === 'ParenthesizedExpression' ) expression = expression.expression;

		if ( shouldRemoveParens( expression, parent ) ) {
			code.remove( start, expression.start );
			code.remove( expression.end, end );
		} else {
			if ( expression.start > this.start + 1 ) code.remove( this.start + 1, expression.start );
			if ( this.end > expression.end + 1 ) code.remove( expression.end, this.end - 1 );
		}

		// special case (?) – IIFE
		if (
			(
				this.parent.type === 'CallExpression' &&
				this.parent.parent.type === 'ExpressionStatement' &&
				/FunctionExpression/.test( expression.type )
			) ||
			(
				this.parent.type === 'ExpressionStatement' &&
				expression.type === 'CallExpression' &&
				/FunctionExpression/.test( expression.callee.type )
			)
		) {
			code.prependRight( this.start, '!' ); // could be any unary operator – uglify uses !
		}

		expression.minify( code );
	}
}
<commit_msg>prevent infinite loop<commit_after>import Node from '../Node.js';

function shouldRemoveParens ( expression, parent ) {
	if ( /^Object/.test( expression.getLeftHandSide().type ) || /^Object/.test( expression.getRightHandSide().type ) ) {
		return false;
	}

	if ( expression.type === 'CallExpression' ) {
		return expression.callee.type === 'FunctionExpression'; // TODO is this right?
	}

	if ( expression.type === 'FunctionExpression' ) {
		return (
			( parent.type === 'CallExpression' && parent.parent.type === 'ExpressionStatement' ) ||
			( parent.type === 'ExpressionStatement' && parent.parent.type === 'CallExpression' )
		);
	}

	const expressionPrecedence = expression.getPrecedence();
	const parentPrecedence = parent.getPrecedence();

	if ( parentPrecedence > expressionPrecedence ) return false;
	if ( expressionPrecedence > parentPrecedence ) return true;

	if ( expression.type === 'UnaryExpression' ) return true;
	if ( expression.type === 'AssignmentExpression' ) return true;
	if ( expression.type === 'LogicalExpression' || expression.type === 'BinaryExpression' ) {
		return ( parent.operator === '**' ? parent.right : parent.left ).contains( expression );
	}
}

export default class ParenthesizedExpression extends Node {
	getLeftHandSide () {
		let node = this;

		while ( node.type === 'ParenthesizedExpression' ) {
			node = node.expression;
		}

		if ( shouldRemoveParens( node, this.parent ) ) return node.getLeftHandSide();
		return node.parent;
	}

	getPrecedence () {
		return 20;
	}

	getValue () {
		return this.expression.getValue();
	}

	minify ( code ) {
		let start = this.start;
		let end = this.end;
		let parent = this.parent;

		let expression = this.expression;
		while ( expression.type === 'ParenthesizedExpression' ) expression = expression.expression;

		if ( shouldRemoveParens( expression, parent ) ) {
			code.remove( start, expression.start );
			code.remove( expression.end, end );
		} else {
			if ( expression.start > this.start + 1 ) code.remove( this.start + 1, expression.start );
			if ( this.end > expression.end + 1 ) code.remove( expression.end, this.end - 1 );
		}

		// special case (?) – IIFE
		if (
			(
				this.parent.type === 'CallExpression' &&
				this.parent.parent.type === 'ExpressionStatement' &&
				/FunctionExpression/.test( expression.type )
			) ||
			(
				this.parent.type === 'ExpressionStatement' &&
				expression.type === 'CallExpression' &&
				/FunctionExpression/.test( expression.callee.type )
			)
		) {
			code.prependRight( this.start, '!' ); // could be any unary operator – uglify uses !
		}

		expression.minify( code );
	}
}
<|endoftext|>


<commit_before>var component = require('omniscient'),
    EventEmitter = require('events').EventEmitter,
    Immutable = require('immutable'),
    bind = require('lodash.bind'),
    React = require('react/addons');

var CELL_SIZE = 30,
    BORDER_SIZE = 1,
    TEXT_X_OFFSET = 7,
    TEXT_Y_OFFSET = 25;

function position(a) {
    return (Math.floor(a / 3) + 2) * BORDER_SIZE +
        a * (CELL_SIZE + BORDER_SIZE);
}

var Cell = component(function (props, statics) {
    var x = props.cursor.get('x'),
        y = props.cursor.get('y'),
        value = props.cursor.get('value');

    function onClick(e) {
        statics.events.emit('click', {
            x: x,
            y: y
        });
    }

    return React.DOM.g({
        className: React.addons.classSet({
            "sudoku__cell": true,
            "sudoku__cell--not-editable": !props.cursor.get('editable'),
            "sudoku__cell--highlighted": props.cursor.get('highlighted'),
            "sudoku__cell--focussed": props.cursor.get('focussed')
        })
    },
        React.DOM.rect({
            x: position(x),
            y: position(y),
            width: CELL_SIZE,
            height: CELL_SIZE,
            onClick: onClick
        }), value ? [
            React.DOM.text({
                key: "text",
                x: position(x) + TEXT_X_OFFSET,
                y: position(y) + TEXT_Y_OFFSET,
                className: "sudoku__cell-text",
                onClick: onClick
            }, value)
        ] : []
    );
});

function highlights(focusX, focusY) {
    var focusSquareX = Math.floor(focusX / 3),
        focusSquareY = Math.floor(focusY / 3);

    return function (x, y) {
        var squareX = Math.floor(x / 3),
            squareY = Math.floor(y / 3);

        return x == focusX ||
            y == focusY ||
            squareX == focusSquareX && squareY == focusSquareY;
    };
}

function fConst(a) {
    return function () {
        return a;
    };
};

var events = new EventEmitter();

function mapCells(grid, f) {
    return grid.map(function (column) {
        return column.map(f);
    });
}

var Grid = component({
    focusCell: function (position) {
        var isHighlighted = highlights(position.x, position.y),
            cells = this.props.cells;

        cells.update(function (state) {
            return mapCells(state, function (cell) {
                return cell.merge({
                    focussed: cell.get('x') === position.x && cell.get('y') === position.y,
                    highlighted: isHighlighted(cell.get('x'), cell.get('y'))
                });
            });
        });

        this.focus = cells.get([position.x, position.y]);
    },

    blurCell: function () {
        this.props.cells.update(function (state) {
            return mapCells(state, function (cell) {
                return cell.merge({
                    focussed: false,
                    highlighted: false
                });
            });
        });
    },

    componentDidMount: function () {
        events.on('click', bind(this.focusCell, this));
    },

    componentWillUnmount: function () {
        events.removeAllListeners();
    }
}, function (props) {
    var cells = props.cells.flatMap(function (column) {
        return column.map(function (cell) {
            return Cell(cell.get('x') + "_" + cell.get('y'), {
                cursor: cell,
                statics: {
                    events: events
                }
            });
        });
    });

    return React.DOM.svg({
        width: position(9),
        height: position(9),
        tabIndex: "0",
        onBlur: this.blurCell
    }, React.DOM.rect({
        x: 0,
        y: 0,
        width: position(9),
        height: position(9),
        className: "sudoku__background"
    }), cells.toJS());
});

module.exports = Grid;

<commit_msg>Remove dead code<commit_after>var component = require('omniscient'),
    EventEmitter = require('events').EventEmitter,
    Immutable = require('immutable'),
    bind = require('lodash.bind'),
    React = require('react/addons');

var CELL_SIZE = 30,
    BORDER_SIZE = 1,
    TEXT_X_OFFSET = 7,
    TEXT_Y_OFFSET = 25;

function position(a) {
    return (Math.floor(a / 3) + 2) * BORDER_SIZE +
        a * (CELL_SIZE + BORDER_SIZE);
}

var Cell = component(function (props, statics) {
    var x = props.cursor.get('x'),
        y = props.cursor.get('y'),
        value = props.cursor.get('value');

    function onClick(e) {
        statics.events.emit('click', {
            x: x,
            y: y
        });
    }

    return React.DOM.g({
        className: React.addons.classSet({
            "sudoku__cell": true,
            "sudoku__cell--not-editable": !props.cursor.get('editable'),
            "sudoku__cell--highlighted": props.cursor.get('highlighted'),
            "sudoku__cell--focussed": props.cursor.get('focussed')
        })
    },
        React.DOM.rect({
            x: position(x),
            y: position(y),
            width: CELL_SIZE,
            height: CELL_SIZE,
            onClick: onClick
        }), value ? [
            React.DOM.text({
                key: "text",
                x: position(x) + TEXT_X_OFFSET,
                y: position(y) + TEXT_Y_OFFSET,
                className: "sudoku__cell-text",
                onClick: onClick
            }, value)
        ] : []
    );
});

function highlights(focusX, focusY) {
    var focusSquareX = Math.floor(focusX / 3),
        focusSquareY = Math.floor(focusY / 3);

    return function (x, y) {
        var squareX = Math.floor(x / 3),
            squareY = Math.floor(y / 3);

        return x == focusX ||
            y == focusY ||
            squareX == focusSquareX && squareY == focusSquareY;
    };
}

var events = new EventEmitter();

function mapCells(grid, f) {
    return grid.map(function (column) {
        return column.map(f);
    });
}

var Grid = component({
    focusCell: function (position) {
        var isHighlighted = highlights(position.x, position.y),
            cells = this.props.cells;

        cells.update(function (state) {
            return mapCells(state, function (cell) {
                return cell.merge({
                    focussed: cell.get('x') === position.x && cell.get('y') === position.y,
                    highlighted: isHighlighted(cell.get('x'), cell.get('y'))
                });
            });
        });

        this.focus = cells.get([position.x, position.y]);
    },

    blurCell: function () {
        this.props.cells.update(function (state) {
            return mapCells(state, function (cell) {
                return cell.merge({
                    focussed: false,
                    highlighted: false
                });
            });
        });
    },

    componentDidMount: function () {
        events.on('click', bind(this.focusCell, this));
    },

    componentWillUnmount: function () {
        events.removeAllListeners();
    }
}, function (props) {
    var cells = props.cells.flatMap(function (column) {
        return column.map(function (cell) {
            return Cell(cell.get('x') + "_" + cell.get('y'), {
                cursor: cell,
                statics: {
                    events: events
                }
            });
        });
    });

    return React.DOM.svg({
        width: position(9),
        height: position(9),
        tabIndex: "0",
        onBlur: this.blurCell
    }, React.DOM.rect({
        x: 0,
        y: 0,
        width: position(9),
        height: position(9),
        className: "sudoku__background"
    }), cells.toJS());
});

module.exports = Grid;

<|endoftext|>


<commit_before>module.exports = function(grunt) {
    require('load-grunt-tasks')(grunt);
  // Project configuration.
grunt.initConfig({

    copy:{
	    html: {
	    	src: './index.html', dest: 'dist/index.html'
	    },
        dist: {
            files: [
                {
                    expand: true,
                    dot: true,
                    cwd: './',
                    dest: 'dist',
                    src: [
                        'images/**/*',
                        'style/fonts/*',
                    ]
                },
                {
                    expand: true,
                    cwd: '.',
                    dest: 'dist',
                    src: ['bower_components/requirejs/*.js','bower_components/requirejs-domready/*.js']
                }]
        },
        leaflet: {
            src: '.tmp/concat/app/leaflet.js',
            dest:'dist/app/leaflet.js',
        },
        templates: {
            files: [{
                expand: true,
                flatten: true,
                dot: true,
                cwd: './',
                dest: 'dist/app/templates/',
                src: ['.tmp/scripts/templates/*'],
                    }]
        },
        jstemplates: {
            src: '.tmp/templates.js', dest: 'bower_components/templates.js'
        },

    },

   useminPrepare: {
	      html: 'index.html',
	      options: {
	        dest: 'dist'
	      }
	  },

    usemin:{
        html:['dist/index.html']
          },

    htmlmin: {                                     // Task
        dist: {                                    // Target
          options: {                               // Target options
            removeComments: true,
            collapseWhitespace: true
          },
          files: [{
            expand: true,
            src: ['app/**/*.html','*.html'],
            dest:'dist/',
          }]
        }
      },

    html2js: {
        options: {
            base: '.',
            module: 'app.templates',
            singleModule: true,
            useStrict: true,
            htmlmin: {
              collapseBooleanAttributes: true,
              collapseWhitespace: true,
              removeAttributeQuotes: true,
              removeComments: true,
              removeEmptyAttributes: true,
              removeRedundantAttributes: true,
              removeScriptTypeAttributes: true,
              removeStyleLinkTypeAttributes: true
            }
        },
        main: {
          src: ['app/templates/*.html'],
          dest: 'app/templates/maintemplate.js'
        },
    },

   requirejs: {
            generated: {
                options: {
                    dir: '.tmp/scripts/',
                    modules: [{
                        name: 'main'
                    }],

                    preserveLicenseComments: false,
                    removeCombined: true,
                    baseUrl: 'app',
                    mainConfigFile: 'app/main.js',
                    optimize: 'uglify2',
                    uglify2: {
                        mangle: false
                    }
                }
            }
        },
    concat: {
        dist: {
            src: ['.tmp/scripts/main.js'],
            dest: 'dist/app/main.js'
            }
        },
    clean: {
            dist: {
                files: [{
                    dot: true,
                    src: [
                        '.tmp',
                        'dist/{,*/}*'
                        ]
                }]
            },
            tmp: {
                 files: [{
                    dot: true,
                    src: '.tmp',
                 }]
                 }
        },
    bower: {
            install: {
                options: {
                    targetDir: "./bower_components",
                    copy: false
                        }
                    }
            },

});

    // Default task(s). and build task
    grunt.registerTask('default', [
                      'clean:dist',
                      'copy:html',
                      'copy:dist',
                      'useminPrepare',
                      'concat:generated',
                      'cssmin:generated',
                      'requirejs:generated',
                      'concat',
                      'copy:leaflet',
                      'usemin'
                    ]);
    grunt.registerTask('build', [
                      //'bower',
                      'clean',
                      'copy:html',
                      'copy:dist',
                      'useminPrepare',
                      'concat:generated',
                      'cssmin:generated',
                      'requirejs:generated',
                      'concat',
                      'copy:leaflet',
                      'copy:templates',
                      'copy:jstemplates',
                      'usemin',
                      'clean:tmp',
                    ]);
    grunt.registerTask('build2', [
                      //'bower',
                      'html2js',
                      //'copy:templates',
                      'copy:html',
                      'copy:dist',
                      'useminPrepare',
                      'concat:generated',
                      'cssmin:generated',
                      'requirejs:generated',
                      'concat',
                      'copy:leaflet',
                      //'copy:templates',
                      'copy:jstemplates',
                      'usemin',
                      //'clean:tmp',
                    ]);
};<commit_msg>use grunt command to start grunt<commit_after>module.exports = function(grunt) {
    require('load-grunt-tasks')(grunt);
  // Project configuration.
grunt.initConfig({

    copy:{
	    html: {
	    	src: './index.html', dest: 'dist/index.html'
	    },
        dist: {
            files: [
                {
                    expand: true,
                    dot: true,
                    cwd: './',
                    dest: 'dist',
                    src: [
                        'images/**/*',
                        'style/fonts/*',
                    ]
                },
                {
                    expand: true,
                    cwd: '.',
                    dest: 'dist',
                    src: ['bower_components/requirejs/*.js','bower_components/requirejs-domready/*.js']
                }]
        },
        leaflet: {
            src: '.tmp/concat/app/leaflet.js',
            dest:'dist/app/leaflet.js',
        },
        templates: {
            files: [{
                expand: true,
                flatten: true,
                dot: true,
                cwd: './',
                dest: 'dist/app/templates/',
                src: ['.tmp/scripts/templates/*'],
                    }]
        },
        jstemplates: {
            src: '.tmp/templates.js', dest: 'bower_components/templates.js'
        },

    },

   useminPrepare: {
	      html: 'index.html',
	      options: {
	        dest: 'dist'
	      }
	  },

    usemin:{
        html:['dist/index.html']
          },

    htmlmin: {                                     // Task
        dist: {                                    // Target
          options: {                               // Target options
            removeComments: true,
            collapseWhitespace: true
          },
          files: [{
            expand: true,
            src: ['app/**/*.html','*.html'],
            dest:'dist/',
          }]
        }
      },

    html2js: {
        options: {
            base: '.',
            module: 'app.templates',
            singleModule: true,
            useStrict: true,
            htmlmin: {
              collapseBooleanAttributes: true,
              collapseWhitespace: true,
              removeAttributeQuotes: true,
              removeComments: true,
              removeEmptyAttributes: true,
              removeRedundantAttributes: true,
              removeScriptTypeAttributes: true,
              removeStyleLinkTypeAttributes: true
            }
        },
        main: {
          src: ['app/templates/*.html'],
          dest: 'app/templates/maintemplate.js'
        },
    },

   requirejs: {
            generated: {
                options: {
                    dir: '.tmp/scripts/',
                    modules: [{
                        name: 'main'
                    }],

                    preserveLicenseComments: false,
                    removeCombined: true,
                    baseUrl: 'app',
                    mainConfigFile: 'app/main.js',
                    optimize: 'uglify2',
                    uglify2: {
                        mangle: false
                    }
                }
            }
        },
    concat: {
        dist: {
            src: ['.tmp/scripts/main.js'],
            dest: 'dist/app/main.js'
            }
        },
    clean: {
            dist: {
                files: [{
                    dot: true,
                    src: [
                        '.tmp',
                        'dist/{,*/}*'
                        ]
                }]
            },
            tmp: {
                 files: [{
                    dot: true,
                    src: '.tmp',
                 }]
                 }
        },
    bower: {
            install: {
                options: {
                    targetDir: "./bower_components",
                    copy: false
                        }
                    }
            },

});

    // Default task(s). and build task

    grunt.registerTask('default', [
                      //'bower',
                      'html2js',
                      //'copy:templates',
                      'copy:html',
                      'copy:dist',
                      'useminPrepare',
                      'concat:generated',
                      'cssmin:generated',
                      'requirejs:generated',
                      'concat',
                      'copy:leaflet',
                      //'copy:templates',
                      'copy:jstemplates',
                      'usemin',
                      //'clean:tmp',
                    ]);
};<|endoftext|>


<commit_before>/* Copyright 2013 Florent Galland & Luc Verdier

This file is part of glark.io.

glark.io is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
at your option) any later version.

glark.io is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with glark.io.  If not, see <http://www.gnu.org/licenses/>. */
'use strict';

angular.module('glark.services')

    /* Create a glark.services.File object from a html5 File or Blob object. */
    .factory('RemoteFile', function (base64, $q, $http) {

        /* Create a remote file from his name and
         * params, where params contains information
         * to connect the Rest API. */
        var RemoteFile = function (name, params, basename) {
            this.isDirectory = false;
            this.isFile = true;

            this.name = name;
            this.basename = '/';
            this.changed = false;

            if (basename !== undefined) {
                this.basename = basename;
            }

            this.params = params;

            this.baseurl =  'http://' + params.adress + ':' + params.port + '/connector';
            this.baseurl += this.basename + this.name;

            this.authenticationHeader = 'Basic ' +
                base64.encode(params.username + ':' + params.password);
        };

        /* Get the content of the remote file. */
        RemoteFile.prototype.getContent = function () {
            var defered = $q.defer();
            $http.get(this.baseurl, {headers: {'Authorization': this.authenticationHeader}})
                .success(function (response) {
                    defered.resolve(response.data.content);
                })
            .error(function (response, status) {
                console.log('Error in $http get. Unable to get content of remote file.');
                console.log(status);
                console.log(response);
            });
            return defered.promise;
        };

        /* Set the content of the remote file. */
        RemoteFile.prototype.setContent = function (content) {
            var defered = $q.defer();
            defered.resolve();
            return defered.promise;
        };

        return RemoteFile;
    });
<commit_msg>Add put request to save file<commit_after>/* Copyright 2013 Florent Galland & Luc Verdier

This file is part of glark.io.

glark.io is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
at your option) any later version.

glark.io is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with glark.io.  If not, see <http://www.gnu.org/licenses/>. */
'use strict';

angular.module('glark.services')

    /* Create a glark.services.File object from a html5 File or Blob object. */
    .factory('RemoteFile', function (base64, $q, $http) {

        /* Create a remote file from his name and
         * params, where params contains information
         * to connect the Rest API. */
        var RemoteFile = function (name, params, basename) {
            this.isDirectory = false;
            this.isFile = true;

            this.name = name;
            this.basename = '/';
            this.changed = false;

            if (basename !== undefined) {
                this.basename = basename;
            }

            this.params = params;

            this.baseurl =  'http://' + params.adress + ':' + params.port + '/connector';
            this.baseurl += this.basename + this.name;

            this.authenticationHeader = 'Basic ' +
                base64.encode(params.username + ':' + params.password);
        };

        /* Get the content of the remote file. */
        RemoteFile.prototype.getContent = function () {
            var defered = $q.defer();
            $http.get(this.baseurl, {headers: {'Authorization': this.authenticationHeader}})
                .success(function (response) {
                    defered.resolve(response.data.content);
                })
            .error(function (response, status) {
                console.log('Error in $http get. Unable to get content of remote file.');
                console.log(status);
                console.log(response);
            });
            return defered.promise;
        };

        /* Set the content of the remote file. */
        RemoteFile.prototype.setContent = function (content) {
            var defered = $q.defer();
            $http.put(this.baseurl, {'path': this.basename + this.name, 'content': content},
                    {headers: {'Authorization': this.authenticationHeader}})
                .success(function (response) {
                    defered.resolve(response.data.content);
                })
            .error(function (response, status) {
                console.log('Error in $http put. Unable to set content of remote file.');
                console.log(status);
                console.log(response);
            });
            return defered.promise;
        };

        return RemoteFile;
    });
<|endoftext|>