<commit_before>var Utils = require('../Utils/Utils');
var Dispatcher = require('../Dispatcher/Dispatcher');
var HideShowTransition = require('../Transition/HideShowTransition');
var BaseCache = require('../Cache/BaseCache');

var HistoryManager = require('./HistoryManager');
var Dom = require('./Dom');

/**
 * Pjax is a static object with main function
 *
 * @namespace Barba.Pjax
 * @borrows Dom as Dom
 * @type {Object}
 */
var Pjax = {
  Dom: Dom,
  History: HistoryManager,
  Cache: BaseCache,

  /**
   * Indicate wether or not use the cache
   *
   * @memberOf Barba.Pjax
   * @type {Boolean}
   * @default
   */
  cacheEnabled: true,

  /**
   * Indicate if there is an animation in progress
   *
   * @memberOf Barba.Pjax
   * @readOnly
   * @type {Boolean}
   */
  transitionProgress: false,

  /**
   * Class name used to ignore links
   *
   * @memberOf Barba.Pjax
   * @type {String}
   * @default
   */
  ignoreClassLink: 'no-barba',

  /**
   * Function to be called to start Pjax
   *
   * @memberOf Barba.Pjax
   */
  start: function() {
    this.init();
  },

  /**
   * Init the events
   *
   * @memberOf Barba.Pjax
   * @private
   */
  init: function() {
    var container = this.Dom.getContainer();
    var wrapper = this.Dom.getWrapper();

    wrapper.setAttribute('aria-live', 'polite');

    this.History.add(
      this.getCurrentUrl(),
      this.Dom.getNamespace(container)
    );

    //Fire for the current view.
    Dispatcher.trigger('initStateChange', this.History.currentStatus());
    Dispatcher.trigger('newPageReady',
      this.History.currentStatus(),
      {},
      container,
      this.Dom.currentHTML
    );
    Dispatcher.trigger('transitionCompleted', this.History.currentStatus());

    this.bindEvents();
  },

  /**
   * Attach the eventlisteners
   *
   * @memberOf Barba.Pjax
   * @private
   */
  bindEvents: function() {
    document.addEventListener('click',
      this.onLinkClick.bind(this)
    );

    window.addEventListener('popstate',
      this.onStateChange.bind(this)
    );
  },

  /**
   * Return the currentURL cleaned
   *
   * @memberOf Barba.Pjax
   * @return {String} currentUrl
   */
  getCurrentUrl: function() {
    return Utils.cleanLink(
      Utils.getCurrentUrl()
    );
  },

  /**
   * Change the URL with pushstate and trigger the state change
   *
   * @memberOf Barba.Pjax
   * @param {String} newUrl
   */
  goTo: function(url) {
    window.history.pushState(null, null, url);
    this.onStateChange();
  },

  /**
   * Force the browser to go to a certain url
   *
   * @memberOf Barba.Pjax
   * @param {String} url
   * @private
   */
  forceGoTo: function(url) {
    window.location = url;
  },

  /**
   * Load an url, will start an xhr request or load from the cache
   *
   * @memberOf Barba.Pjax
   * @private
   * @param  {String} url
   * @return {Promise}
   */
  load: function(url) {
    var deferred = Utils.deferred();
    var _this = this;
    var xhr;

    xhr = this.Cache.get(url);

    if (!xhr) {
      xhr = Utils.xhr(url);
      this.Cache.set(url, xhr);
    }

    xhr.then(
      function(data) {
        var container = _this.Dom.parseResponse(data);

        _this.Dom.putContainer(container);

        if (!_this.cacheEnabled)
          _this.Cache.reset();

        deferred.resolve(container);
      },
      function() {
        //Something went wrong (timeout, 404, 505...)
        _this.forceGoTo(url);

        deferred.reject();
      }
    );

    return deferred.promise;
  },

  /**
   * Get the .href parameter out of an element
   * and handle special cases (like xlink:href)
   *
   * @private
   * @memberOf Barba.Pjax
   * @param  {HTMLElement} el
   * @return {String} href
   */
  getHref: function(el) {
    if (!el) {
      return undefined;
    }

    if (el.getAttribute && typeof el.getAttribute('xlink:href') === 'string') {
      return el.getAttribute('xlink:href');
    }

    if (typeof el.href === 'string') {
      return el.href;
    }

    return undefined;
  },

  /**
   * Callback called from click event
   *
   * @memberOf Barba.Pjax
   * @private
   * @param {MouseEvent} evt
   */
  onLinkClick: function(evt) {
    var el = evt.target;

    //Go up in the nodelist until we
    //find something with an href
    while (el && !this.getHref(el)) {
      el = el.parentNode;
    }

    if (this.preventCheck(evt, el)) {
      evt.stopPropagation();
      evt.preventDefault();

      Dispatcher.trigger('linkClicked', el, evt);

      var href = this.getHref(el);
      this.goTo(href);
    }
  },

  /**
   * Determine if the link should be followed
   *
   * @memberOf Barba.Pjax
   * @param  {MouseEvent} evt
   * @param  {HTMLElement} element
   * @return {Boolean}
   */
  preventCheck: function(evt, element) {
    if (!window.history.pushState)
      return false;

    var href = this.getHref(element);

    //User
    if (!element || !href)
      return false;

    //Middle click, cmd click, and ctrl click
    if (evt.which > 1 || evt.metaKey || evt.ctrlKey || evt.shiftKey || evt.altKey)
      return false;

    //Ignore target with _blank target
    if (element.target && element.target === '_blank')
      return false;

    //Check if it's the same domain
    if (window.location.protocol !== element.protocol || window.location.hostname !== element.hostname)
      return false;

    //Check if the port is the same
    if (Utils.getPort() !== Utils.getPort(element.port))
      return false;

    //Ignore case when a hash is being tacked on the current URL
    if (href.indexOf('#') > -1)
      return false;

    //Ignore case where there is download attribute
    if (typeof element.download !== 'undefined')
      return false;

    //In case you're trying to load the same page
    if (Utils.cleanLink(href) == Utils.cleanLink(location.href))
      return false;

    if (element.classList.contains(this.ignoreClassLink))
      return false;

    return true;
  },

  /**
   * Return a transition object
   *
   * @memberOf Barba.Pjax
   * @return {Barba.Transition} Transition object
   */
  getTransition: function() {
    //User customizable
    return HideShowTransition;
  },

  /**
   * Method called after a 'popstate' or from .goTo()
   *
   * @memberOf Barba.Pjax
   * @private
   */
  onStateChange: function() {
    var newUrl = this.getCurrentUrl();

    if (this.transitionProgress)
      this.forceGoTo(newUrl);

    if (this.History.currentStatus().url === newUrl)
      return false;

    this.History.add(newUrl);

    var newContainer = this.load(newUrl);
    var transition = Object.create(this.getTransition());

    this.transitionProgress = true;

    Dispatcher.trigger('initStateChange',
      this.History.currentStatus(),
      this.History.prevStatus()
    );

    var transitionInstance = transition.init(
      this.Dom.getContainer(),
      newContainer
    );

    newContainer.then(
      this.onNewContainerLoaded.bind(this)
    );

    transitionInstance.then(
      this.onTransitionEnd.bind(this)
    );
  },

  /**
   * Function called as soon the new container is ready
   *
   * @memberOf Barba.Pjax
   * @private
   * @param {HTMLElement} container
   */
  onNewContainerLoaded: function(container) {
    var currentStatus = this.History.currentStatus();
    currentStatus.namespace = this.Dom.getNamespace(container);

    Dispatcher.trigger('newPageReady',
      this.History.currentStatus(),
      this.History.prevStatus(),
      container,
      this.Dom.currentHTML
    );
  },

  /**
   * Function called as soon the transition is finished
   *
   * @memberOf Barba.Pjax
   * @private
   */
  onTransitionEnd: function() {
    this.transitionProgress = false;

    Dispatcher.trigger('transitionCompleted',
      this.History.currentStatus(),
      this.History.prevStatus()
    );
  }
};

module.exports = Pjax;
<commit_msg>Fix download attribute check<commit_after>var Utils = require('../Utils/Utils');
var Dispatcher = require('../Dispatcher/Dispatcher');
var HideShowTransition = require('../Transition/HideShowTransition');
var BaseCache = require('../Cache/BaseCache');

var HistoryManager = require('./HistoryManager');
var Dom = require('./Dom');

/**
 * Pjax is a static object with main function
 *
 * @namespace Barba.Pjax
 * @borrows Dom as Dom
 * @type {Object}
 */
var Pjax = {
  Dom: Dom,
  History: HistoryManager,
  Cache: BaseCache,

  /**
   * Indicate wether or not use the cache
   *
   * @memberOf Barba.Pjax
   * @type {Boolean}
   * @default
   */
  cacheEnabled: true,

  /**
   * Indicate if there is an animation in progress
   *
   * @memberOf Barba.Pjax
   * @readOnly
   * @type {Boolean}
   */
  transitionProgress: false,

  /**
   * Class name used to ignore links
   *
   * @memberOf Barba.Pjax
   * @type {String}
   * @default
   */
  ignoreClassLink: 'no-barba',

  /**
   * Function to be called to start Pjax
   *
   * @memberOf Barba.Pjax
   */
  start: function() {
    this.init();
  },

  /**
   * Init the events
   *
   * @memberOf Barba.Pjax
   * @private
   */
  init: function() {
    var container = this.Dom.getContainer();
    var wrapper = this.Dom.getWrapper();

    wrapper.setAttribute('aria-live', 'polite');

    this.History.add(
      this.getCurrentUrl(),
      this.Dom.getNamespace(container)
    );

    //Fire for the current view.
    Dispatcher.trigger('initStateChange', this.History.currentStatus());
    Dispatcher.trigger('newPageReady',
      this.History.currentStatus(),
      {},
      container,
      this.Dom.currentHTML
    );
    Dispatcher.trigger('transitionCompleted', this.History.currentStatus());

    this.bindEvents();
  },

  /**
   * Attach the eventlisteners
   *
   * @memberOf Barba.Pjax
   * @private
   */
  bindEvents: function() {
    document.addEventListener('click',
      this.onLinkClick.bind(this)
    );

    window.addEventListener('popstate',
      this.onStateChange.bind(this)
    );
  },

  /**
   * Return the currentURL cleaned
   *
   * @memberOf Barba.Pjax
   * @return {String} currentUrl
   */
  getCurrentUrl: function() {
    return Utils.cleanLink(
      Utils.getCurrentUrl()
    );
  },

  /**
   * Change the URL with pushstate and trigger the state change
   *
   * @memberOf Barba.Pjax
   * @param {String} newUrl
   */
  goTo: function(url) {
    window.history.pushState(null, null, url);
    this.onStateChange();
  },

  /**
   * Force the browser to go to a certain url
   *
   * @memberOf Barba.Pjax
   * @param {String} url
   * @private
   */
  forceGoTo: function(url) {
    window.location = url;
  },

  /**
   * Load an url, will start an xhr request or load from the cache
   *
   * @memberOf Barba.Pjax
   * @private
   * @param  {String} url
   * @return {Promise}
   */
  load: function(url) {
    var deferred = Utils.deferred();
    var _this = this;
    var xhr;

    xhr = this.Cache.get(url);

    if (!xhr) {
      xhr = Utils.xhr(url);
      this.Cache.set(url, xhr);
    }

    xhr.then(
      function(data) {
        var container = _this.Dom.parseResponse(data);

        _this.Dom.putContainer(container);

        if (!_this.cacheEnabled)
          _this.Cache.reset();

        deferred.resolve(container);
      },
      function() {
        //Something went wrong (timeout, 404, 505...)
        _this.forceGoTo(url);

        deferred.reject();
      }
    );

    return deferred.promise;
  },

  /**
   * Get the .href parameter out of an element
   * and handle special cases (like xlink:href)
   *
   * @private
   * @memberOf Barba.Pjax
   * @param  {HTMLElement} el
   * @return {String} href
   */
  getHref: function(el) {
    if (!el) {
      return undefined;
    }

    if (el.getAttribute && typeof el.getAttribute('xlink:href') === 'string') {
      return el.getAttribute('xlink:href');
    }

    if (typeof el.href === 'string') {
      return el.href;
    }

    return undefined;
  },

  /**
   * Callback called from click event
   *
   * @memberOf Barba.Pjax
   * @private
   * @param {MouseEvent} evt
   */
  onLinkClick: function(evt) {
    var el = evt.target;

    //Go up in the nodelist until we
    //find something with an href
    while (el && !this.getHref(el)) {
      el = el.parentNode;
    }

    if (this.preventCheck(evt, el)) {
      evt.stopPropagation();
      evt.preventDefault();

      Dispatcher.trigger('linkClicked', el, evt);

      var href = this.getHref(el);
      this.goTo(href);
    }
  },

  /**
   * Determine if the link should be followed
   *
   * @memberOf Barba.Pjax
   * @param  {MouseEvent} evt
   * @param  {HTMLElement} element
   * @return {Boolean}
   */
  preventCheck: function(evt, element) {
    if (!window.history.pushState)
      return false;

    var href = this.getHref(element);

    //User
    if (!element || !href)
      return false;

    //Middle click, cmd click, and ctrl click
    if (evt.which > 1 || evt.metaKey || evt.ctrlKey || evt.shiftKey || evt.altKey)
      return false;

    //Ignore target with _blank target
    if (element.target && element.target === '_blank')
      return false;

    //Check if it's the same domain
    if (window.location.protocol !== element.protocol || window.location.hostname !== element.hostname)
      return false;

    //Check if the port is the same
    if (Utils.getPort() !== Utils.getPort(element.port))
      return false;

    //Ignore case when a hash is being tacked on the current URL
    if (href.indexOf('#') > -1)
      return false;

    //Ignore case where there is download attribute
    if (element.getAttribute && typeof element.download === 'string')
      return false;

    //In case you're trying to load the same page
    if (Utils.cleanLink(href) == Utils.cleanLink(location.href))
      return false;

    if (element.classList.contains(this.ignoreClassLink))
      return false;

    return true;
  },

  /**
   * Return a transition object
   *
   * @memberOf Barba.Pjax
   * @return {Barba.Transition} Transition object
   */
  getTransition: function() {
    //User customizable
    return HideShowTransition;
  },

  /**
   * Method called after a 'popstate' or from .goTo()
   *
   * @memberOf Barba.Pjax
   * @private
   */
  onStateChange: function() {
    var newUrl = this.getCurrentUrl();

    if (this.transitionProgress)
      this.forceGoTo(newUrl);

    if (this.History.currentStatus().url === newUrl)
      return false;

    this.History.add(newUrl);

    var newContainer = this.load(newUrl);
    var transition = Object.create(this.getTransition());

    this.transitionProgress = true;

    Dispatcher.trigger('initStateChange',
      this.History.currentStatus(),
      this.History.prevStatus()
    );

    var transitionInstance = transition.init(
      this.Dom.getContainer(),
      newContainer
    );

    newContainer.then(
      this.onNewContainerLoaded.bind(this)
    );

    transitionInstance.then(
      this.onTransitionEnd.bind(this)
    );
  },

  /**
   * Function called as soon the new container is ready
   *
   * @memberOf Barba.Pjax
   * @private
   * @param {HTMLElement} container
   */
  onNewContainerLoaded: function(container) {
    var currentStatus = this.History.currentStatus();
    currentStatus.namespace = this.Dom.getNamespace(container);

    Dispatcher.trigger('newPageReady',
      this.History.currentStatus(),
      this.History.prevStatus(),
      container,
      this.Dom.currentHTML
    );
  },

  /**
   * Function called as soon the transition is finished
   *
   * @memberOf Barba.Pjax
   * @private
   */
  onTransitionEnd: function() {
    this.transitionProgress = false;

    Dispatcher.trigger('transitionCompleted',
      this.History.currentStatus(),
      this.History.prevStatus()
    );
  }
};

module.exports = Pjax;
<|endoftext|>


<commit_before>import React from 'react';
import jQuery from 'jquery';
import PlantMenu from './PlantMenu';

class PlantSpot extends React.Component {
  constructor() {
    super()

    this.state = {
      plantSpots: [{x_position:"0"}, {x_position:"1"}, {x_position:"2"}],
      count: 3,
      plantSpot: 1
    }
  }

  // reloadPlantSpots(event) {
  //   let component = this;
  //   let plantContainerId = this.props.params.plantContainerId;
  //
  //   jQuery.getJSON(`http://localhost:5000/${plantContainerId}/plant_spots`, function(data) {
  //     console.log(data);
  //     component.setState({
  //       plantSpots: data.plant_spots
  //     });
  //   })
  // }

  selectSpot(event) {
    console.log("event is:" + event)
    console.log("plantspot before setState: " + this.state.plantSpot);
    this.setState({plantSpot: event});
    console.log("plantspot after setState: " + this.state.plantSpot)
  }

  // componentDidMount() {
  //   console.log("didMount");
  //   this.reloadPlants();
  // }

  render(){
    return(

        <PlantMenu plantSpot={this.state.plantSpot}/>

plantspots:

            {
              this.state.plantSpots.map(function(plantSpot, i){
                return(
                  <button onClick={this.selectSpot.bind(this, plantSpot.x_position)}>

                  </button>);
              }, this)
            }

    );
  }
}

export default PlantSpot;
<commit_msg>deleted some unnecessary code<commit_after>import React from 'react';
import jQuery from 'jquery';
import PlantMenu from './PlantMenu';

class PlantSpot extends React.Component {
  constructor() {
    super()

    this.state = {
      plantSpots: [{x_position:"0"}, {x_position:"1"}, {x_position:"2"}],
      count: 3,
      plantSpot: 1
    }
  }

  // reloadPlantSpots(event) {
  //   let component = this;
  //   let plantContainerId = this.props.params.plantContainerId;
  //
  //   jQuery.getJSON(`http://localhost:5000/${plantContainerId}/plant_spots`, function(data) {
  //     console.log(data);
  //     component.setState({
  //       plantSpots: data.plant_spots
  //     });
  //   })
  // }

  selectSpot(event) {
    console.log("event is:" + event);
    this.setState({plantSpot: event});
    console.log("plantspot after setState: " + this.state.plantSpot)
  }

  // componentDidMount() {
  //   console.log("didMount");
  //   this.reloadPlants();
  // }

  render(){
    return(

        <PlantMenu plantSpot={this.state.plantSpot}/>

plantspots:

            {
              this.state.plantSpots.map(function(plantSpot, i){
                return(
                  <button onClick={this.selectSpot.bind(this, plantSpot.x_position)}>

                  </button>);
              }, this)
            }

    );
  }
}

export default PlantSpot;
<|endoftext|>


<commit_before>/**
 *
 * The Preloader state is used to preload assets before the MainMenu is displayed. Once assets have been loaded the Preloader state
 * will start the MainMenu state
 */

Game.Preloader = function(game) { };

Game.Preloader.prototype = {
    preload:function(){
        var preloadBG = this.add.sprite((this.world.width-580)*0.5, (this.world.height+150)*0.5, 'loading-background');
        var preloadProgress = this.add.sprite((this.world.width-540)*0.5, (this.world.height+170)*0.5, 'loading-progress');
        this.load.setPreloadSprite(preloadProgress);
        this.preloadResources();
        //this.load.script('webfont', '//ajax.googleapis.com/ajax/libs/webfont/1.4.7/webfont.js');

    },
    preloadResources: function() {
        var pack = Game.Preloader.resources;

        for(var method in pack) {
            pack[method].forEach(function(args){
                var loader = this.load[method];
                loader && loader.apply(this.load, args);
            }, this);
        }

    },

    create:function(){
        this.state.start('MainMenu');
    }
};

Game.Preloader.resources = {
    /*
     * Load all game resources
     */
    'image' : [
        ['dot32', 'assets/img/dot32.png'],
        ['bigDot32', 'assets/img/bigDot32.png'],
        ['cherry', 'assets/img/cherry.png'],
        ['cTile32', 'assets/img/chompermazetiles32g.png'],
        ['down', 'assets/img/down.png'],
        ['left', 'assets/img/left.png'],
        ['right', 'assets/img/right.png'],
        ['up', 'assets/img/up.png'],
        ['circle', 'assets/img/circle.png'],
        ['story-bg', 'assets/img/Packground.png'],
        ['bg-story', 'assets/img/StoryBackgroundBlur.png'],
        ['logo', 'assets/img/Logo.png'],
        ['instructions', 'assets/img/instructions.png'],
        ['overlay', 'assets/img/overlay.png'],
        ['ui-bg', 'assets/img/ui-bg.png'],
        ['particle', 'assets/img/particle.png'],
        ['black', 'assets/img/black.png'],
        ['cup', 'assets/img/trophy.png'],
        ['congrats', 'assets/img/congrats.png'],
        ['coupon-one', 'assets/img/dealercoupon.png'],
        ['coupon-two', 'assets/img/dealercoupontwo.png'],
        ['coupon-three', 'assets/img/dealercouponthree.png']

    ],

    'atlasXML': [
        ['spark', 'assets/atlasXML/spark.png', 'assets/atlasXML/spark.xml']
    ],

    'audio': [
        ['level_music', ['assets/audio/finalMainLoop.mp3', 'assets/audio/finalMainLoop.ogg']],
        ['menu_music', ['assets/audio/menuLoop.mp3', 'assets/audio/menuLoop.ogg']],
        ['big_eat_sfx', ['assets/audio/bigEat.mp3', 'assets/audio/bigEat.ogg']],
		['ghost_eat_sfx', ['assets/audio/ghostEat.mp3','assets/audio/ghostEat.ogg']],
		['lose', ['assets/audio/lose.mp3', 'assets/audio/lose.ogg']],
		['win', ['assets/audio/win.mp3', 'assets/audio/win.ogg']]
    ],

    'tilemap': [
        ['pmap32', 'assets/maps/pmap32.csv']

    ],

    'spritesheet': [
        ['csprites32','assets/img/chompersprites32.png', 32, 32],
        ['cSpTile32', 'assets/img/chompermazetiles32g.png', 32, 32],
        ['downs', 'assets/img/downs.png', 143,182],
        ['lefts', 'assets/img/lefts.png', 182, 143],
        ['rights', 'assets/img/rights.png', 182, 143],
        ['ups', 'assets/img/ups.png', 143,182],
        ['button-start', 'assets/img/button-start.png', 180, 180],
        ['button-rules', 'assets/img/rules-btn.png', 110, 40],
        ['button-play', 'assets/img/play-btn.png', 475, 140],
        ['button-continue', 'assets/img/button-continue.png', 180, 180],
        ['button-mainmenu', 'assets/img/button-mainmenu.png', 180, 180],
        ['button-restart', 'assets/img/button-tryagain.png', 180, 180],
        ['button-achievements', 'assets/img/button-achievements.png', 110, 110],
        ['button-pause', 'assets/img/button-pause.png', 80, 80],
        ['button-audio', 'assets/img/button-sound.png', 80, 80],
        ['button-back', 'assets/img/button-back.png', 70, 70],
        ['claim-prize-btn', 'assets/img/claimPrizes.png', 400, 60]

    ]

};
<commit_msg>add desktop version<commit_after>/**
 *
 * The Preloader state is used to preload assets before the MainMenu is displayed. Once assets have been loaded the Preloader state
 * will start the MainMenu state
 */

Game.Preloader = function(game) { };

Game.Preloader.prototype = {
    preload:function(){
        var preloadBG = this.add.sprite((this.world.width-580)*0.5, (this.world.height+150)*0.5, 'loading-background');
        var preloadProgress = this.add.sprite((this.world.width-540)*0.5, (this.world.height+170)*0.5, 'loading-progress');
        this.load.setPreloadSprite(preloadProgress);
        this.preloadResources();
        //this.load.script('webfont', '//ajax.googleapis.com/ajax/libs/webfont/1.4.7/webfont.js');

    },
    preloadResources: function() {
        var pack = Game.Preloader.resources;

        for(var method in pack) {
            pack[method].forEach(function(args){
                var loader = this.load[method];
                loader && loader.apply(this.load, args);
            }, this);
        }

    },

    create:function(){
        this.state.start('MainMenu');
    }
};

Game.Preloader.resources = {
    /*
     * Load all game resources
     */
    'image' : [
        ['dot32', 'assets/img/dot32.png'],
        ['bigDot32', 'assets/img/bigDot32.png'],
        ['cherry', 'assets/img/cherry.png'],
        ['cTile32', 'assets/img/chompermazetiles32g.png'],
        ['down', 'assets/img/down.png'],
        ['left', 'assets/img/left.png'],
        ['right', 'assets/img/right.png'],
        ['up', 'assets/img/up.png'],
        ['circle', 'assets/img/circle.png'],
        ['story-bg', 'assets/img/Packground.png'],
        ['bg-story', 'assets/img/StoryBackgroundBlur.png'],
        ['logo', 'assets/img/Logo.png'],
        ['instructions', 'assets/img/instructions.png'],
        ['overlay', 'assets/img/overlay.png'],
        ['ui-bg', 'assets/img/ui-bg.png'],
        ['particle', 'assets/img/particle.png'],
        ['black', 'assets/img/black.png'],
        ['cup', 'assets/img/trophy.png'],
        ['congrats', 'assets/img/congrats.png'],
        ['coupon-one', 'assets/img/dealercoupon.png'],
        ['coupon-two', 'assets/img/dealercoupontwo.png'],
        ['coupon-three', 'assets/img/dealercouponthree.png']

    ],

    'atlasXML': [
        ['spark', 'assets/atlasXML/spark.png', 'assets/atlasXML/spark.xml']
    ],

    'audio': [
        ['level_music', ['assets/audio/finalMainLoop.mp3', 'assets/audio/finalMainLoop.ogg']],
        ['menu_music', ['assets/audio/menuLoop.mp3', 'assets/audio/menuLoop.ogg']],
        ['big_eat_sfx', ['assets/audio/bigEat.mp3', 'assets/audio/bigEat.ogg']],
		['ghost_eat_sfx', ['assets/audio/ghostEat.mp3','assets/audio/ghostEat.ogg']],
		['lose', ['assets/audio/lose.mp3', 'assets/audio/lose.ogg']],
		['win', ['assets/audio/win.mp3', 'assets/audio/win.ogg']]
    ],

    'tilemap': [
        ['pmap32', 'assets/maps/pmap32.csv'],
        ['pmapdesk', 'assets/maps/pmapdesk.csv']

    ],

    'spritesheet': [
        ['csprites32','assets/img/chompersprites32.png', 32, 32],
        ['cSpTile32', 'assets/img/chompermazetiles32g.png', 32, 32],
        ['downs', 'assets/img/downs.png', 143,182],
        ['lefts', 'assets/img/lefts.png', 182, 143],
        ['rights', 'assets/img/rights.png', 182, 143],
        ['ups', 'assets/img/ups.png', 143,182],
        ['movDir', 'assets/img/moveDirs.png', 256,256],
        ['button-start', 'assets/img/button-start.png', 180, 180],
        ['button-rules', 'assets/img/rules-btn.png', 110, 40],
        ['button-play', 'assets/img/play-btn.png', 475, 140],
        ['button-continue', 'assets/img/button-continue.png', 180, 180],
        ['button-mainmenu', 'assets/img/button-mainmenu.png', 180, 180],
        ['button-restart', 'assets/img/button-tryagain.png', 180, 180],
        ['button-achievements', 'assets/img/button-achievements.png', 110, 110],
        ['button-pause', 'assets/img/button-pause.png', 80, 80],
        ['button-audio', 'assets/img/button-sound.png', 80, 80],
        ['button-back', 'assets/img/button-back.png', 70, 70],
        ['claim-prize-btn', 'assets/img/claimPrizes.png', 400, 60]

    ]

};
<|endoftext|>


<commit_before>import Shape from 'kittik-shape-basic';

/**
 * Implements rectangle shape with text support.
 *
 * @since 1.0.0
 * @version 1.0.0
 */
export default class Rectangle extends Shape {
  render(cursor) {
    let text = this.getText();
    let width = this.getWidth();
    let height = this.getHeight();
    let {x: x1, y: y1} = this.getPosition();
    let {x2, y2} = {x2: width + x1 - 1, y2: height + y1 - 1};
    let background = this.getBackground();
    let foreground = this.getForeground();

    cursor.fill({x1, y1, x2, y2, background, foreground});
    cursor.setPosition(x1 + (width / 2 - text.length / 2), y1 + (height / 2)).write(text);

    return this;
  }
}
<commit_msg>refactor(shape): Move fill method from Cursor to Shape<commit_after>import Shape from 'kittik-shape-basic';

/**
 * Implements rectangle shape with text support.
 *
 * @since 1.0.0
 * @version 1.0.0
 */
export default class Rectangle extends Shape {
  fill(cursor, options = {}) {
    let {x, y, width, height, symbol = ' ', background, foreground} = options;
    let filler = symbol.repeat(width + 1);

    if (typeof background !== 'undefined') cursor.background(background);
    if (typeof foreground !== 'undefined') cursor.foreground(foreground);

    cursor.moveTo(x, y);

    while (y <= height + y) {
      cursor.write(filler);
      cursor.moveTo(x, ++y);
    }

    return this;
  }

  render(cursor) {
    let text = this.getText();
    let width = this.getWidth();
    let height = this.getHeight();
    let {x: x1, y: y1} = this.getPosition();
    let {x2, y2} = {x2: width + x1 - 1, y2: height + y1 - 1};
    let background = this.getBackground();
    let foreground = this.getForeground();

    this.fill(cursor, {x1, y1, x2, y2, background, foreground});
    cursor.setPosition(x1 + (width / 2 - text.length / 2), y1 + (height / 2)).write(text);

    return this;
  }
}
<|endoftext|>


<commit_before>const Props = require('prop-types');
const React = require('react');

function getInitialState() {
  return {
    x: null,
    y: null,
    swiping: false,
    start: 0,
  };
}

class Swipeable extends React.Component {
  constructor(props, context) {
    super(props, context);
    this.eventStart = this.eventStart.bind(this);
    this.eventMove = this.eventMove.bind(this);
    this.eventEnd = this.eventEnd.bind(this);
  }

  componentWillMount() {
    this.swipeable = getInitialState();
  }

  calculatePos(e) {
    let x;
    let y;
    // If not a touch, determine point from mouse coordinates
    if (e.changedTouches) {
      x = e.changedTouches[0].clientX;
      y = e.changedTouches[0].clientY;
    } else {
      x = e.clientX;
      y = e.clientY;
    }

    const xd = this.swipeable.x - x;
    const yd = this.swipeable.y - y;

    const axd = Math.abs(xd);
    const ayd = Math.abs(yd);

    const time = Date.now() - this.swipeable.start;
    const velocity = Math.sqrt(axd * axd + ayd * ayd) / time;

    return {
      deltaX: xd,
      deltaY: yd,
      absX: axd,
      absY: ayd,
      velocity,
    };
  }

  eventStart(e) {
    if (typeof this.props.onMouseDown === 'function') { // eslint-disable-line react/prop-types
      this.props.onMouseDown(e); // eslint-disable-line react/prop-types
    }

    if (e.type === 'mousedown' && !this.props.trackMouse) {
      return;
    }

    if (e.touches && e.touches.length > 1) {
      return;
    }
    // If not a touch, determine point from mouse coordinates
    let touches = e.touches;
    if (!touches) {
      touches = [{ clientX: e.clientX, clientY: e.clientY }];
    }
    if (this.props.stopPropagation) e.stopPropagation();

    this.swipeable = {
      start: Date.now(),
      x: touches[0].clientX,
      y: touches[0].clientY,
      swiping: false,
    };
  }

  eventMove(e) {
    if (typeof this.props.onMouseMove === 'function') { // eslint-disable-line react/prop-types
      this.props.onMouseMove(e); // eslint-disable-line react/prop-types
    }

    if (e.type === 'mousemove' && !this.props.trackMouse) {
      return;
    }

    if (!this.swipeable.x || !this.swipeable.y || e.touches && e.touches.length > 1) {
      return;
    }

    let cancelPageSwipe = false;
    const pos = this.calculatePos(e);

    if (pos.absX < this.props.delta && pos.absY < this.props.delta) {
      return;
    }

    if (this.props.stopPropagation) e.stopPropagation();

    if (this.props.onSwiping) {
      this.props.onSwiping(e, pos.deltaX, pos.deltaY, pos.absX, pos.absY, pos.velocity);
    }

    if (pos.absX > pos.absY) {
      if (pos.deltaX > 0) {
        if (this.props.onSwipingLeft || this.props.onSwipedLeft) {
          this.props.onSwipingLeft && this.props.onSwipingLeft(e, pos.absX);
          cancelPageSwipe = true;
        }
      } else if (this.props.onSwipingRight || this.props.onSwipedRight) {
        this.props.onSwipingRight && this.props.onSwipingRight(e, pos.absX);
        cancelPageSwipe = true;
      }
    } else if (pos.deltaY > 0) {
      if (this.props.onSwipingUp || this.props.onSwipedUp) {
        this.props.onSwipingUp && this.props.onSwipingUp(e, pos.absY);
        cancelPageSwipe = true;
      }
    } else if (this.props.onSwipingDown || this.props.onSwipedDown) {
      this.props.onSwipingDown && this.props.onSwipingDown(e, pos.absY);
      cancelPageSwipe = true;
    }

    this.swipeable.swiping = true;

    if (cancelPageSwipe && this.props.preventDefaultTouchmoveEvent) {
      e.preventDefault();
    }
  }

  eventEnd(e) {
    if (typeof this.props.onMouseUp === 'function') { // eslint-disable-line react/prop-types
      this.props.onMouseUp(e); // eslint-disable-line react/prop-types
    }

    if (e.type === 'mouseup' && !this.props.trackMouse) {
      return;
    }

    if (this.swipeable.swiping) {
      const pos = this.calculatePos(e);

      if (this.props.stopPropagation) e.stopPropagation();

      const isFlick = pos.velocity > this.props.flickThreshold;

      this.props.onSwiped && this.props.onSwiped(
        e,
        pos.deltaX,
        pos.deltaY,
        isFlick,
        pos.velocity,
      );

      if (pos.absX > pos.absY) {
        if (pos.deltaX > 0) {
          this.props.onSwipedLeft && this.props.onSwipedLeft(e, pos.deltaX, isFlick);
        } else {
          this.props.onSwipedRight && this.props.onSwipedRight(e, pos.deltaX, isFlick);
        }
      } else if (pos.deltaY > 0) {
        this.props.onSwipedUp && this.props.onSwipedUp(e, pos.deltaY, isFlick);
      } else {
        this.props.onSwipedDown && this.props.onSwipedDown(e, pos.deltaY, isFlick);
      }
    } else {
      this.props.onTap && this.props.onTap(e);
    }

    this.swipeable = getInitialState();
  }

  render() {
    const newProps = {
      ...this.props,
      onTouchStart: this.eventStart,
      onTouchMove: this.eventMove,
      onTouchEnd: this.eventEnd,
      onMouseDown: this.eventStart,
      onMouseMove: this.eventMove,
      onMouseUp: this.eventEnd,
    };

    delete newProps.onSwiped;
    delete newProps.onSwiping;
    delete newProps.onSwipingUp;
    delete newProps.onSwipingRight;
    delete newProps.onSwipingDown;
    delete newProps.onSwipingLeft;
    delete newProps.onSwipedUp;
    delete newProps.onSwipedRight;
    delete newProps.onSwipedDown;
    delete newProps.onSwipedLeft;
    delete newProps.onTap;
    delete newProps.flickThreshold;
    delete newProps.delta;
    delete newProps.preventDefaultTouchmoveEvent;
    delete newProps.stopPropagation;
    delete newProps.nodeName;
    delete newProps.children;
    delete newProps.trackMouse;

    return React.createElement(
      this.props.nodeName,
      newProps,
      this.props.children,
    );
  }
}

Swipeable.propTypes = {
  onSwiped: Props.func,
  onSwiping: Props.func,
  onSwipingUp: Props.func,
  onSwipingRight: Props.func,
  onSwipingDown: Props.func,
  onSwipingLeft: Props.func,
  onSwipedUp: Props.func,
  onSwipedRight: Props.func,
  onSwipedDown: Props.func,
  onSwipedLeft: Props.func,
  onTap: Props.func,
  flickThreshold: Props.number,
  delta: Props.number,
  preventDefaultTouchmoveEvent: Props.bool,
  stopPropagation: Props.bool,
  nodeName: Props.string,
  trackMouse: Props.bool,
  children: Props.node,
};

Swipeable.defaultProps = {
  flickThreshold: 0.6,
  delta: 10,
  preventDefaultTouchmoveEvent: true,
  stopPropagation: false,
  nodeName: 'div',
};

module.exports = Swipeable;
<commit_msg>use 'PropTypes'<commit_after>const React = require('react');
const PropTypes = require('prop-types');

function getInitialState() {
  return {
    x: null,
    y: null,
    swiping: false,
    start: 0,
  };
}

class Swipeable extends React.Component {
  constructor(props, context) {
    super(props, context);
    this.eventStart = this.eventStart.bind(this);
    this.eventMove = this.eventMove.bind(this);
    this.eventEnd = this.eventEnd.bind(this);
  }

  componentWillMount() {
    this.swipeable = getInitialState();
  }

  calculatePos(e) {
    let x;
    let y;
    // If not a touch, determine point from mouse coordinates
    if (e.changedTouches) {
      x = e.changedTouches[0].clientX;
      y = e.changedTouches[0].clientY;
    } else {
      x = e.clientX;
      y = e.clientY;
    }

    const xd = this.swipeable.x - x;
    const yd = this.swipeable.y - y;

    const axd = Math.abs(xd);
    const ayd = Math.abs(yd);

    const time = Date.now() - this.swipeable.start;
    const velocity = Math.sqrt(axd * axd + ayd * ayd) / time;

    return {
      deltaX: xd,
      deltaY: yd,
      absX: axd,
      absY: ayd,
      velocity,
    };
  }

  eventStart(e) {
    if (typeof this.props.onMouseDown === 'function') { // eslint-disable-line react/prop-types
      this.props.onMouseDown(e); // eslint-disable-line react/prop-types
    }

    if (e.type === 'mousedown' && !this.props.trackMouse) {
      return;
    }

    if (e.touches && e.touches.length > 1) {
      return;
    }
    // If not a touch, determine point from mouse coordinates
    let touches = e.touches;
    if (!touches) {
      touches = [{ clientX: e.clientX, clientY: e.clientY }];
    }
    if (this.props.stopPropagation) e.stopPropagation();

    this.swipeable = {
      start: Date.now(),
      x: touches[0].clientX,
      y: touches[0].clientY,
      swiping: false,
    };
  }

  eventMove(e) {
    if (typeof this.props.onMouseMove === 'function') { // eslint-disable-line react/prop-types
      this.props.onMouseMove(e); // eslint-disable-line react/prop-types
    }

    if (e.type === 'mousemove' && !this.props.trackMouse) {
      return;
    }

    if (!this.swipeable.x || !this.swipeable.y || e.touches && e.touches.length > 1) {
      return;
    }

    let cancelPageSwipe = false;
    const pos = this.calculatePos(e);

    if (pos.absX < this.props.delta && pos.absY < this.props.delta) {
      return;
    }

    if (this.props.stopPropagation) e.stopPropagation();

    if (this.props.onSwiping) {
      this.props.onSwiping(e, pos.deltaX, pos.deltaY, pos.absX, pos.absY, pos.velocity);
    }

    if (pos.absX > pos.absY) {
      if (pos.deltaX > 0) {
        if (this.props.onSwipingLeft || this.props.onSwipedLeft) {
          this.props.onSwipingLeft && this.props.onSwipingLeft(e, pos.absX);
          cancelPageSwipe = true;
        }
      } else if (this.props.onSwipingRight || this.props.onSwipedRight) {
        this.props.onSwipingRight && this.props.onSwipingRight(e, pos.absX);
        cancelPageSwipe = true;
      }
    } else if (pos.deltaY > 0) {
      if (this.props.onSwipingUp || this.props.onSwipedUp) {
        this.props.onSwipingUp && this.props.onSwipingUp(e, pos.absY);
        cancelPageSwipe = true;
      }
    } else if (this.props.onSwipingDown || this.props.onSwipedDown) {
      this.props.onSwipingDown && this.props.onSwipingDown(e, pos.absY);
      cancelPageSwipe = true;
    }

    this.swipeable.swiping = true;

    if (cancelPageSwipe && this.props.preventDefaultTouchmoveEvent) {
      e.preventDefault();
    }
  }

  eventEnd(e) {
    if (typeof this.props.onMouseUp === 'function') { // eslint-disable-line react/prop-types
      this.props.onMouseUp(e); // eslint-disable-line react/prop-types
    }

    if (e.type === 'mouseup' && !this.props.trackMouse) {
      return;
    }

    if (this.swipeable.swiping) {
      const pos = this.calculatePos(e);

      if (this.props.stopPropagation) e.stopPropagation();

      const isFlick = pos.velocity > this.props.flickThreshold;

      this.props.onSwiped && this.props.onSwiped(
        e,
        pos.deltaX,
        pos.deltaY,
        isFlick,
        pos.velocity,
      );

      if (pos.absX > pos.absY) {
        if (pos.deltaX > 0) {
          this.props.onSwipedLeft && this.props.onSwipedLeft(e, pos.deltaX, isFlick);
        } else {
          this.props.onSwipedRight && this.props.onSwipedRight(e, pos.deltaX, isFlick);
        }
      } else if (pos.deltaY > 0) {
        this.props.onSwipedUp && this.props.onSwipedUp(e, pos.deltaY, isFlick);
      } else {
        this.props.onSwipedDown && this.props.onSwipedDown(e, pos.deltaY, isFlick);
      }
    } else {
      this.props.onTap && this.props.onTap(e);
    }

    this.swipeable = getInitialState();
  }

  render() {
    const newProps = {
      ...this.props,
      onTouchStart: this.eventStart,
      onTouchMove: this.eventMove,
      onTouchEnd: this.eventEnd,
      onMouseDown: this.eventStart,
      onMouseMove: this.eventMove,
      onMouseUp: this.eventEnd,
    };

    delete newProps.onSwiped;
    delete newProps.onSwiping;
    delete newProps.onSwipingUp;
    delete newProps.onSwipingRight;
    delete newProps.onSwipingDown;
    delete newProps.onSwipingLeft;
    delete newProps.onSwipedUp;
    delete newProps.onSwipedRight;
    delete newProps.onSwipedDown;
    delete newProps.onSwipedLeft;
    delete newProps.onTap;
    delete newProps.flickThreshold;
    delete newProps.delta;
    delete newProps.preventDefaultTouchmoveEvent;
    delete newProps.stopPropagation;
    delete newProps.nodeName;
    delete newProps.children;
    delete newProps.trackMouse;

    return React.createElement(
      this.props.nodeName,
      newProps,
      this.props.children,
    );
  }
}

Swipeable.propTypes = {
  onSwiped: PropTypes.func,
  onSwiping: PropTypes.func,
  onSwipingUp: PropTypes.func,
  onSwipingRight: PropTypes.func,
  onSwipingDown: PropTypes.func,
  onSwipingLeft: PropTypes.func,
  onSwipedUp: PropTypes.func,
  onSwipedRight: PropTypes.func,
  onSwipedDown: PropTypes.func,
  onSwipedLeft: PropTypes.func,
  onTap: PropTypes.func,
  flickThreshold: PropTypes.number,
  delta: PropTypes.number,
  preventDefaultTouchmoveEvent: PropTypes.bool,
  stopPropagation: PropTypes.bool,
  nodeName: PropTypes.string,
  trackMouse: PropTypes.bool,
  children: PropTypes.node,
};

Swipeable.defaultProps = {
  flickThreshold: 0.6,
  delta: 10,
  preventDefaultTouchmoveEvent: true,
  stopPropagation: false,
  nodeName: 'div',
};

module.exports = Swipeable;
<|endoftext|>


<commit_before>const Testcase = require('./Testcase');

class Testsuite {
  constructor (id, result) {
    this.testsuite = [{
      _attr: {
        id,
        name: result.testFilePath,
        errors: 0,
        package: result.testFilePath,
        hostname: 'localhost',
        tests: (result.numPendingTests + result.numFailingTests + result.numPassingTests),
        failures: result.numFailingTests,
        time: (result.perfStats.end - result.perfStats.start) / 1000,
        timestamp: new Date(result.perfStats.start).toISOString().slice(0, -5)
      }
    }];

    this.testsuite.push({ properties: [] });
    result.testResults
      .filter(result => (result.status !== 'pending'))
      .forEach(result => this.testsuite.push(new Testcase(result)));
    this.testsuite.push({ 'system-out': {} });
    this.testsuite.push({ 'system-err': {} });
  }
}

module.exports = Testsuite;
<commit_msg>Remove imperative code in favor of declarative statements for building testsuite<commit_after>const Testcase = require('./Testcase');

class Testsuite {
  constructor (id, result) {
    let testcases = result.testResults
      .filter(result => (result.status !== 'pending'))
      .map(result => new Testcase(result));

    let suite = {
      _attr: {
        id,
        name: result.testFilePath,
        errors: 0,
        package: result.testFilePath,
        hostname: 'localhost',
        tests: (result.numPendingTests + result.numFailingTests + result.numPassingTests),
        failures: result.numFailingTests,
        time: (result.perfStats.end - result.perfStats.start) / 1000,
        timestamp: new Date(result.perfStats.start).toISOString().slice(0, -5)
      }
    };

    this.testsuite = [suite, { properties: [] }]
      .concat(
        testcases,
        { 'system-out': {} },
        { 'system-err': {} }
      );
  }
}

module.exports = Testsuite;
<|endoftext|>


<commit_before>"use strict";

/**
 * Dummy empty function.
 * @function
 */
meta.emptyFunc = function() {};

/**
 * Dummy empty function with one parameter.
 * @function
 * @param param {*=} Any parameter.
 */
meta.emptyFuncParam = function(param) {};

/**
 * Load textures. Textures added will load only after requesting them first.
 * @param buffer {Array|String} Buffer with texture sources.
 * @param folderPath {String=} Path applied to texture sources.
 */
meta.loadTexture = function(buffer, folderPath, tag)
{
	if(!meta._loadResource("Texture", buffer, folderPath, tag)) {
		console.warn("(meta.loadTexture) Unsupported parameter was passed.");
	}
};

/**
 * Preload textures. When texture is added it will be auto loaded without anyone requesting it first.
 * @param buffer {Array|String} Buffer with texture sources.
 * @param folderPath {String=} Path applied to texture sources.
 */
meta.preloadTexture = function(buffer, folderPath, tag)
{
	if(!meta._preloadResource("Texture", buffer, folderPath, tag)) {
		console.warn("(meta.preloadTexture) Unsupported parameter was passed.");
	}
};

/**
 * Load sounds. Sounds added will load only after requesting them first.
 * @param buffer {Array|String} Buffer with sound sources.
 * @param folderPath {String=} Path applied to sound sources.
 */
meta.loadSound = function(buffer, folderPath, tag)
{
	if(!meta._loadResource("Sound", buffer, folderPath, tag)) {
		console.warn("(meta.loadSound) Unsupported parameter was passed.");
	}
};

/**
 * Preload sounds. When sound is added it will be auto loaded without anyone requesting it first.
 * @param buffer {Array|String} Buffer with sound sources.
 * @param folderPath {String=} Path applied to sound sources.
 */
meta.preloadSound = function(buffer, folderPath, tag)
{
	if(!meta._preloadResource("Sound", buffer, folderPath, tag)) {
		console.warn("(meta.preloadSound) Unsupported parameter was passed.");
	}
};

/**
 * Load sounds. Sounds added will load only after requesting them first.
 * @param buffer {Array|String} Buffer with sound sources.
 * @param folderPath {String=} Path applied to sound sources.
 */
meta.loadSpriteSheet = function(buffer, folderPath, tag)
{
	if(!meta._preloadResource("SpriteSheet", buffer, folderPath, tag)) {
		console.warn("(meta.loadSpriteSheet) Unsupported parameter was passed.");
	}
};

/**
 * Load bitmap fonts.
 * @param buffer {Array|String} Buffer with sound sources.
 * @param folderPath {String=} Path applied to sound sources.
 */
meta.loadFont = function(buffer, folderPath, tag)
{
	if(!meta._preloadResource("Font", buffer, folderPath, tag)) {
		console.warn("(meta.loadFont) Unsupported parameter was passed.");
	}
};

meta._loadResource = function(strType, buffer, folderPath, tag)
{
	if(folderPath)
	{
		var slashIndex = folderPath.lastIndexOf("/");
		if(slashIndex <= 0) {
			folderPath += "/";
		}
	}
	else {
		folderPath = "";
	}

	if(buffer instanceof Array)
	{
		var numResources = buffer.length;
		for(var i = 0; i < numResources; i++) {
			meta._addResource(strType, buffer[i], folderPath, tag);
		}
	}
	else if(typeof(buffer) === "object" || typeof(buffer) === "string") {
		meta._addResource(strType, buffer, folderPath, tag);
	}
	else {
		return false;
	}

	return true;
};

meta._preloadResource = function(strType, buffer, folderPath, tag)
{
	if(folderPath)
	{
		var slashIndex = folderPath.lastIndexOf("/");
		if(slashIndex !== folderPath.length - 1) {
			folderPath += "/";
		}
	}
	else {
		folderPath = "";
	}

	if(buffer instanceof Array)
	{
		var numResources = buffer.length;
		for(var i = 0; i < numResources; i++) {
			meta._addResource(strType, buffer[i], folderPath, tag);
		}
	}
	else if(typeof(buffer) === "object" || typeof(buffer) === "string") {
		meta._addResource(strType, buffer, folderPath, tag);
	}
	else {
		return false;
	}

	return true;
};

meta._addResource = function(strType, data, folderPath, tag)
{
	var resource;

	if(typeof(data) === "object")
	{
		if(data.path) {
			data.path = folderPath + data.path;
		}
		resource = new Resource[strType](data, tag);
	}
	else {
		resource = new Resource[strType](folderPath + data, tag);
	};

	Resource.ctrl.add(resource);

	return resource;
};

/**
 * Get texture by name.
 * @param name {String} Name of the texture resource.
 * @returns {Resource.Texture|null} Texture from the manager.
 */
meta.getTexture = function(name) {
	return Resource.ctrl.getTexture(name);
};

/**
 * Get sound by name.
 * @param name {String} Name of the sound resource.
 * @returns {Resource.Sound|null} Sound from the manager.
 */
meta.getSound = function(name) {
	return Resource.ctrl.getSound(name);
};

/**
 * Cross browser support window.onload like function.
 * @param func {Function} Callback function to call when window is loaded.
 * @function
 */
meta.onDomLoad = function(func)
{
	if((document.readyState === "interactive" || document.readyState === "complete")) {
		func();
		return;
	}

	var cbFunc = function(event) {
		func();
		window.removeEventListener("DOMContentLoaded", cbFunc);
	};

	window.addEventListener("DOMContentLoaded", cbFunc);
};

/**
 * Get enum key as string.
 * @param buffer {Object} Enum object where key is located.
 * @param value {*} Value of the key which needs to be converted.
 * @returns {string} Converted enum to string.
 */
meta.enumToString = function(buffer, value)
{
	if(buffer === void(0)) {
		return "unknown";
	}

	for(var enumKey in buffer)
	{
		if(buffer[enumKey] === value) {
			return enumKey;
		}
	}

	return "unknown";
};

/**
 * Convert hex string to object with RGB values.
 * @param hex {String} Hex to convert.
 * @return {{r: Number, g: Number, b: Number}} Object with rgb values.
 */
meta.hexToRgb = function(hex)
{
	if(hex.length < 6) {
		hex += hex.substr(1, 4);
	}

	var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
	return {
		r: parseInt(result[1], 16),
		g: parseInt(result[2], 16),
		b: parseInt(result[3], 16)
	}
};

/**
 * Check if string is url.
 * @param str {string} String to check.
 * @returns {boolean} true if is url.
 */
meta.isUrl = function(str)
{
	if(str.indexOf("http://") !== -1 || str.indexOf("https://") !== -1) {
		return true;
	}

	return false;
};

/**
 * Change to upper case first character of the string.
 * @param str {String} String to perform action on.
 * @returns {String}
 */
meta.toUpperFirstChar = function(str) {
	return str.charAt(0).toUpperCase() + str.slice(1);
};

meta.serialize = function(obj)
{
	var str = [];
	for(var key in obj) {
		str.push(encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]));
	}

	return str.join("&");
};

/**
 * Add descriptive widget to the view for demo purposes.
 * @param text {String} Description text.
 */
meta.info = function(text)
{
	// Text.
	var msg = new Entity.Text(text);
	msg.color = "#ffffff";
	msg.pivot(0.5);

	// Background.
	var texture = new Resource.SVG();
	texture.fillRect(0, 0, msg.width + 10, msg.height + 10);

	var bg = new Entity.Geometry(texture);
	bg.z = 9999;
	bg.position(0, 20);
	bg.anchor(0.5, 0);
	bg.pivot(0.5);

	bg.static = true;
	meta.view.attach(bg);

	bg.attach(msg);
};

meta.adaptTo = function(width, height, path)
{
	if(meta.engine && meta.engine.isInited) {
		console.warn("[meta.adaptTo]:", "Only usable before engine is initialized.");
		return;
	}

	var resolutions = meta.cache.resolutions;
	if(!resolutions) {
		resolutions = [];
		meta.cache.resolutions = resolutions;
	}

	var lastChar = path.charAt(path.length - 1);
	if(lastChar !== "/") {
		path += "/";
	}

	var newRes = {
		width: width,
		height: height,
		path: path,
		unitSize: 1,
		zoomThreshold: 1
	};

	resolutions.push(newRes);
};

meta.removeFromArray = function(item, array)
{
	var numItems = array.length;
	for(var i = 0; i < numItems; i++) {
		if(item === array[i]) {
			array[i] = array[numItems - 1];
			array.pop();
			break;
		}
	}
};

meta.shuffleArray = function(array)
{
	var length = array.length;
	var temp, item;

	while(length)
	{
		item = Math.floor(Math.random() * length--);

		temp = array[length];
		array[length] = array[item];
		array[item] = temp;
	}

	return array;
};

meta.rotateArray = function(array)
{
	var tmp = array[0];
	var numItems = array.length - 1;
	for(var i = 0; i < numItems; i++) {
		array[i] = array[i + 1];
	}
	array[numItems] = tmp;
};

meta.nextPowerOfTwo = function(value)
{
    value--;
    value |= value >> 1;
    value |= value >> 2;
    value |= value >> 4;
    value |= value >> 8;
    value |= value >> 16;
    value++;

    return value;
};

meta.toHex = function(c) {
    var hex = c.toString(16);
    return hex.length == 1 ? "0" + hex : hex;
};

meta.rgbToHex = function(r, g, b) {
    return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
<commit_msg>Added tokenises utilities.<commit_after>"use strict";

/**
 * Dummy empty function.
 * @function
 */
meta.emptyFunc = function() {};

/**
 * Dummy empty function with one parameter.
 * @function
 * @param param {*=} Any parameter.
 */
meta.emptyFuncParam = function(param) {};

/**
 * Load textures. Textures added will load only after requesting them first.
 * @param buffer {Array|String} Buffer with texture sources.
 * @param folderPath {String=} Path applied to texture sources.
 */
meta.loadTexture = function(buffer, folderPath, tag)
{
	if(!meta._loadResource("Texture", buffer, folderPath, tag)) {
		console.warn("(meta.loadTexture) Unsupported parameter was passed.");
	}
};

/**
 * Preload textures. When texture is added it will be auto loaded without anyone requesting it first.
 * @param buffer {Array|String} Buffer with texture sources.
 * @param folderPath {String=} Path applied to texture sources.
 */
meta.preloadTexture = function(buffer, folderPath, tag)
{
	if(!meta._preloadResource("Texture", buffer, folderPath, tag)) {
		console.warn("(meta.preloadTexture) Unsupported parameter was passed.");
	}
};

/**
 * Load sounds. Sounds added will load only after requesting them first.
 * @param buffer {Array|String} Buffer with sound sources.
 * @param folderPath {String=} Path applied to sound sources.
 */
meta.loadSound = function(buffer, folderPath, tag)
{
	if(!meta._loadResource("Sound", buffer, folderPath, tag)) {
		console.warn("(meta.loadSound) Unsupported parameter was passed.");
	}
};

/**
 * Preload sounds. When sound is added it will be auto loaded without anyone requesting it first.
 * @param buffer {Array|String} Buffer with sound sources.
 * @param folderPath {String=} Path applied to sound sources.
 */
meta.preloadSound = function(buffer, folderPath, tag)
{
	if(!meta._preloadResource("Sound", buffer, folderPath, tag)) {
		console.warn("(meta.preloadSound) Unsupported parameter was passed.");
	}
};

/**
 * Load sounds. Sounds added will load only after requesting them first.
 * @param buffer {Array|String} Buffer with sound sources.
 * @param folderPath {String=} Path applied to sound sources.
 */
meta.loadSpriteSheet = function(buffer, folderPath, tag)
{
	if(!meta._preloadResource("SpriteSheet", buffer, folderPath, tag)) {
		console.warn("(meta.loadSpriteSheet) Unsupported parameter was passed.");
	}
};

/**
 * Load bitmap fonts.
 * @param buffer {Array|String} Buffer with sound sources.
 * @param folderPath {String=} Path applied to sound sources.
 */
meta.preloadFont = function(buffer, folderPath, tag)
{
	if(!meta._preloadResource("Font", buffer, folderPath, tag)) {
		console.warn("(meta.loadFont) Unsupported parameter was passed.");
	}
};

meta._loadResource = function(strType, buffer, folderPath, tag)
{
	if(folderPath)
	{
		var slashIndex = folderPath.lastIndexOf("/");
		if(slashIndex <= 0) {
			folderPath += "/";
		}
	}
	else {
		folderPath = "";
	}

	if(buffer instanceof Array)
	{
		var numResources = buffer.length;
		for(var i = 0; i < numResources; i++) {
			meta._addResource(strType, buffer[i], folderPath, tag);
		}
	}
	else if(typeof(buffer) === "object" || typeof(buffer) === "string") {
		meta._addResource(strType, buffer, folderPath, tag);
	}
	else {
		return false;
	}

	return true;
};

meta._preloadResource = function(strType, buffer, folderPath, tag)
{
	if(folderPath)
	{
		var slashIndex = folderPath.lastIndexOf("/");
		if(slashIndex !== folderPath.length - 1) {
			folderPath += "/";
		}
	}
	else {
		folderPath = "";
	}

	if(buffer instanceof Array)
	{
		var numResources = buffer.length;
		for(var i = 0; i < numResources; i++) {
			meta._addResource(strType, buffer[i], folderPath, tag);
		}
	}
	else if(typeof(buffer) === "object" || typeof(buffer) === "string") {
		meta._addResource(strType, buffer, folderPath, tag);
	}
	else {
		return false;
	}

	return true;
};

meta._addResource = function(strType, data, folderPath, tag)
{
	var resource;

	if(typeof(data) === "object")
	{
		if(data.path) {
			data.path = folderPath + data.path;
		}
		resource = new Resource[strType](data, tag);
	}
	else {
		resource = new Resource[strType](folderPath + data, tag);
	};

	Resource.ctrl.add(resource);

	return resource;
};

/**
 * Get texture by name.
 * @param name {String} Name of the texture resource.
 * @returns {Resource.Texture|null} Texture from the manager.
 */
meta.getTexture = function(name) {
	return Resource.ctrl.getTexture(name);
};

/**
 * Get sound by name.
 * @param name {String} Name of the sound resource.
 * @returns {Resource.Sound|null} Sound from the manager.
 */
meta.getSound = function(name) {
	return Resource.ctrl.getSound(name);
};

/**
 * Cross browser support window.onload like function.
 * @param func {Function} Callback function to call when window is loaded.
 * @function
 */
meta.onDomLoad = function(func)
{
	if((document.readyState === "interactive" || document.readyState === "complete")) {
		func();
		return;
	}

	var cbFunc = function(event) {
		func();
		window.removeEventListener("DOMContentLoaded", cbFunc);
	};

	window.addEventListener("DOMContentLoaded", cbFunc);
};

/**
 * Get enum key as string.
 * @param buffer {Object} Enum object where key is located.
 * @param value {*} Value of the key which needs to be converted.
 * @returns {string} Converted enum to string.
 */
meta.enumToString = function(buffer, value)
{
	if(buffer === void(0)) {
		return "unknown";
	}

	for(var enumKey in buffer)
	{
		if(buffer[enumKey] === value) {
			return enumKey;
		}
	}

	return "unknown";
};

/**
 * Convert hex string to object with RGB values.
 * @param hex {String} Hex to convert.
 * @return {{r: Number, g: Number, b: Number}} Object with rgb values.
 */
meta.hexToRgb = function(hex)
{
	if(hex.length < 6) {
		hex += hex.substr(1, 4);
	}

	var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
	return {
		r: parseInt(result[1], 16),
		g: parseInt(result[2], 16),
		b: parseInt(result[3], 16)
	}
};

/**
 * Check if string is url.
 * @param str {string} String to check.
 * @returns {boolean} true if is url.
 */
meta.isUrl = function(str)
{
	if(str.indexOf("http://") !== -1 || str.indexOf("https://") !== -1) {
		return true;
	}

	return false;
};

/**
 * Change to upper case first character of the string.
 * @param str {String} String to perform action on.
 * @returns {String}
 */
meta.toUpperFirstChar = function(str) {
	return str.charAt(0).toUpperCase() + str.slice(1);
};

meta.serialize = function(obj)
{
	var str = [];
	for(var key in obj) {
		str.push(encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]));
	}

	return str.join("&");
};

/**
 * Add descriptive widget to the view for demo purposes.
 * @param text {String} Description text.
 */
meta.info = function(text)
{
	// Text.
	var msg = new Entity.Text(text);
	msg.color = "#ffffff";
	msg.pivot(0.5);

	// Background.
	var texture = new Resource.SVG();
	texture.fillRect(0, 0, msg.width + 10, msg.height + 10);

	var bg = new Entity.Geometry(texture);
	bg.z = 9999;
	bg.position(0, 20);
	bg.anchor(0.5, 0);
	bg.pivot(0.5);

	bg.static = true;
	meta.view.attach(bg);

	bg.attach(msg);
};

meta.adaptTo = function(width, height, path)
{
	if(meta.engine && meta.engine.isInited) {
		console.warn("[meta.adaptTo]:", "Only usable before engine is initialized.");
		return;
	}

	var resolutions = meta.cache.resolutions;
	if(!resolutions) {
		resolutions = [];
		meta.cache.resolutions = resolutions;
	}

	var lastChar = path.charAt(path.length - 1);
	if(lastChar !== "/") {
		path += "/";
	}

	var newRes = {
		width: width,
		height: height,
		path: path,
		unitSize: 1,
		zoomThreshold: 1
	};

	resolutions.push(newRes);
};

meta.removeFromArray = function(item, array)
{
	var numItems = array.length;
	for(var i = 0; i < numItems; i++) {
		if(item === array[i]) {
			array[i] = array[numItems - 1];
			array.pop();
			break;
		}
	}
};

meta.shuffleArray = function(array)
{
	var length = array.length;
	var temp, item;

	while(length)
	{
		item = Math.floor(Math.random() * length--);

		temp = array[length];
		array[length] = array[item];
		array[item] = temp;
	}

	return array;
};

meta.rotateArray = function(array)
{
	var tmp = array[0];
	var numItems = array.length - 1;
	for(var i = 0; i < numItems; i++) {
		array[i] = array[i + 1];
	}
	array[numItems] = tmp;
};

meta.nextPowerOfTwo = function(value)
{
    value--;
    value |= value >> 1;
    value |= value >> 2;
    value |= value >> 4;
    value |= value >> 8;
    value |= value >> 16;
    value++;

    return value;
};

meta.toHex = function(c) {
    var hex = c.toString(16);
    return hex.length == 1 ? "0" + hex : hex;
};

meta.rgbToHex = function(r, g, b) {
    return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
};

function isSpace(c) {
	return (c === " " || c === "\t" || c === "\r" || c === "\n");
};

function isNewline(c) {
	return (c === "\r" || c === "\n");
};

function isDigit(c) {
	return (c >= "0" && c <= "9") || (c === ".");
};

function isAlpha(c)
{
	return (c >= "a" && c <= "z") ||
		   (c >= "A" && c <= "Z") ||
		   (c == "_" && c <= "$");
};

function isAlphaNum(c)
{
	return (c >= "a" && c <= "z") ||
		   (c >= "A" && c <= "Z") ||
		   (c >= "0" && c <= "9") ||
		   c === "_" || c === "$";
};

function isBinOp(c)
{
	return (c === "=" || c === "!" || c === "<" || c === ">" ||
			c === "+" || c === "-" || c === "*" || c === "/" ||
			c === "&" || c === "~" || c === "|" || c === "%");
};

<|endoftext|>


<commit_before>'use strict';
/*
 * Copyright (C) 2012 Nicolas Froidure
 *
 * This file is free software;
 * you can redistribute it and/or modify it under the terms of the GNU
 * General Public License (GPL) as published by the Free Software
 * Foundation, in version 3. It is distributed in the
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 *
 */
var DuplexStream = require('readable-stream').Duplex
  , util = require('util')
  , VarStreamReader = require('./VarStreamReader')
  , VarStreamWriter = require('./VarStreamWriter')
;

// Inherit of duplex stream
util.inherits(VarStream, DuplexStream);

// Constructor
function VarStream(rootObject, rootProperty, options) {
  var self = this;

  // Ensure new were used
  if(!(this instanceof VarStream)) {
    return new VarStream(rootObject, rootProperty, options);
  }

  // Ensure we had root object and property
  if(!(rootObject instanceof Object)) {
    throw new Error('No root object provided.');
  }
  if('string' !== typeof rootProperty || rootProperty == '') {
    throw new Error('No root property name given.');
  }

  // Parent constructor
  DuplexStream.call(this);

  this._varstreamReader=new VarStreamReader(rootObject, rootProperty,
    options ? options&VarStreamReader.OPTIONS : 0);

  this._varstreamWriter = new VarStreamWriter(function(str) {
      self.push(new Buffer(str, 'utf8'));
  }, options ? options&VarStreamWriter.OPTIONS : 0);

  // Parse input
  this._write = function _write(chunk, encoding, done) {
    this._varstreamReader.read(chunk.toString(
      encoding !== 'buffer' ? encoding : 'utf8'
    ));
    done();
  };

  // Output data
  this._read = function _read() {
    this._varstreamWriter.write(rootObject[rootProperty]);
    this.push(null);
  };

}

// Parse helper
VarStream.parse = function(content) {
  var root = {};
  var stream = new VarStream(root, 'prop');
  stream.write(Buffer(content));
  stream.end();
  return root.prop || {};
};

// Export helper
VarStream.stringify = function(obj) {
  var root = {prop: obj}, stream, content;
  if('object' !== typeof obj) {
    throw new Error('The stringified object must be an instance of Object.');
  }
  stream = new VarStream(root, 'prop');
  content = stream.read();
  stream.end();
  return String(content);
};

// Exporting
VarStream.VarStreamReader = VarStream.Reader = VarStreamReader;
VarStream.VarStreamWriter = VarStream.Writer = VarStreamWriter;
module.exports = VarStream;
<commit_msg>No need to end the writable stream for stringifying objects<commit_after>'use strict';
/*
 * Copyright (C) 2012 Nicolas Froidure
 *
 * This file is free software;
 * you can redistribute it and/or modify it under the terms of the GNU
 * General Public License (GPL) as published by the Free Software
 * Foundation, in version 3. It is distributed in the
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 *
 */
var DuplexStream = require('readable-stream').Duplex
  , util = require('util')
  , VarStreamReader = require('./VarStreamReader')
  , VarStreamWriter = require('./VarStreamWriter')
;

// Inherit of duplex stream
util.inherits(VarStream, DuplexStream);

// Constructor
function VarStream(rootObject, rootProperty, options) {
  var self = this;

  // Ensure new were used
  if(!(this instanceof VarStream)) {
    return new VarStream(rootObject, rootProperty, options);
  }

  // Ensure we had root object and property
  if(!(rootObject instanceof Object)) {
    throw new Error('No root object provided.');
  }
  if('string' !== typeof rootProperty || rootProperty == '') {
    throw new Error('No root property name given.');
  }

  // Parent constructor
  DuplexStream.call(this);

  this._varstreamReader=new VarStreamReader(rootObject, rootProperty,
    options ? options&VarStreamReader.OPTIONS : 0);

  this._varstreamWriter = new VarStreamWriter(function(str) {
      self.push(new Buffer(str, 'utf8'));
  }, options ? options&VarStreamWriter.OPTIONS : 0);

  // Parse input
  this._write = function _write(chunk, encoding, done) {
    this._varstreamReader.read(chunk.toString(
      encoding !== 'buffer' ? encoding : 'utf8'
    ));
    done();
  };

  // Output data
  this._read = function _read() {
    this._varstreamWriter.write(rootObject[rootProperty]);
    this.push(null);
  };

}

// Parse helper
VarStream.parse = function(content) {
  var root = {};
  var stream = new VarStream(root, 'prop');
  stream.write(Buffer(content));
  stream.end();
  return root.prop || {};
};

// Export helper
VarStream.stringify = function(obj) {
  var root = {prop: obj}, stream, content;
  if('object' !== typeof obj) {
    throw new Error('The stringified object must be an instance of Object.');
  }
  stream = new VarStream(root, 'prop');
  content = stream.read();
  return String(content);
};

// Exporting
VarStream.VarStreamReader = VarStream.Reader = VarStreamReader;
VarStream.VarStreamWriter = VarStream.Writer = VarStreamWriter;
module.exports = VarStream;
<|endoftext|>


<commit_before>"use strict";

// Import
// ========

var _ = require("underscore");
var util = require("substance-util");
var Document = require("./document");
var Operator = require("substance-operator");

// Module
// ========

// A class that manages a document's annotations.
// --------
//

var Annotator;

function _getBehavior(doc) {
  // Note: this is rather experimental
  // It is important to inverse the control over the annotation behavior,
  // i.e., which annotations exist and how they should be handled
  // This approach makes use of the static context of a Document implementation (e.g., Substance.Article)
  // For this to work you need to have:
  // - the `constructor` property set on the class
  // - a static property `annotationBehavior` specifying the behavior
  //   according to `Annotator.defaultBehavior`
  if (doc.constructor && doc.constructor.annotationBehavior) {
    return doc.constructor.annotationBehavior;
  } else {
    throw new Error("No Annotation behavior specified.");
  }
}

Annotator = function(doc, options) {
  options = options || {};

  this.document = doc;
  this.behavior = _getBehavior(doc);

  // register for co-transformations to keep annotations up2date.
  this.document.on("operation:applied", this.handleOperation, this);

  // defines groups of annotations that will be mutually exclusive
  this.groups = this.behavior.groups;
  this.expansion = this.behavior.expansion;
  this.split = this.behavior.split;

  this._index = Annotator.createIndex(doc);

  this.withTransformation = options.withTransformation;
};

Annotator.Prototype = function() {

  // Creates a new annotation
  // --------
  //

  // var _update = function(self, annotation, newRange) {
  //   self.document.apply(Operator.ObjectOperation.Set([annotation.id, "range"], annotation.range, newRange));
  // };

  // Deletes an annotation
  // --------
  //
  var _delete = function(self, annotation) {
    self.document.delete(annotation.id);
  };

  // Takes care of updating annotations whenever an graph operation is applied.
  // --------
  // Triggers new events dedicated to annotation changes.
  this.handleOperation = function(op) {

    // TODO: it would be great to have some API to retrieve reflection information for an object operation.

    var typeChain, annotations, annotation;

    if (op.type === "delete" || op.type === "create") {

      typeChain = this.document.schema.typeChain(op.val.type);

      // handle creation or deletion of annotations
      if (typeChain.indexOf("annotation") >= 0) {
        annotation = op.val;
        this.triggerLater("annotation:changed", op.type, annotation);
      }
      // handle deletion of other nodes, i.e., remove associated annotations
      else if (op.type === "delete") {
        annotations = this._index.get(op.path);
        _.each(annotations, function(a) {
          _delete(this, a);
        }, this);
      }
    }

    else if (op.type === "update" || op.type === "set") {

      var node = this.document.get(op.path[0]);

      // FIXME: due to the use of Compunds and the rather late fired property change events
      // it happens, that there arrive atomic operations with the original node being deleted already
      // or should we tolerate this?
      if (node === undefined) {
        return;
      }

      typeChain = this.document.schema.typeChain(node.type);

      if (typeChain.indexOf("annotation") >= 0) {
        // for now we only are interested range updates
        if (op.path[1] !== "range") return;

        this.triggerLater("annotation:changed", "update", node);

      }

      // It turns out that it is not enough to co-transform annotations.
      // E.g., when text gets deleted and the operation is undone
      // the annotation could not be reconstructed.
      // So we have to trigger annotation updates explicitely
      else if (this.withTransformation) {
        this.transform(op);
      }
    }
  };

  this.create = function(annotation) {
    this.document.create(annotation);
    return annotation;
  };

  // Updates all annotations according to a given operation.
  // --------
  //
  // The provided operation is an ObjectOperation which has been applied
  // to the document already.

  // TODO: this needs to be rethought.
  // On the one hand, we need explicit changes to be able to undo e.g. deletions.
  // OTOH, such co-transforms would then be applied twice... i.e., during simulation
  // co-transformation but when applying the simulation we would not want to have them anymore.
  // Also not when redoing changes (as they would be contained in the change).

  var _transform = function(op, annotation) {
        // only apply the transformation on annotations with the same property
    // Note: currently we only have annotations on the `content` property of nodes
    if (!_.isEqual(annotation.path, op.path)) return;

    if (op.type === "update") {
      // Note: these are implicit transformations, i.e., not triggered via annotation controls
      var expandLeft = false;
      var expandRight = false;

      var expandSpec = this.expansion[annotation.type];
      if (expandSpec) {
        if (expandSpec.left) expandLeft =  expandSpec.left(annotation);
        if (expandSpec.right) expandRight = expandSpec.right(annotation);
      }

      var newRange = util.clone(annotation.range);
      var changed = Operator.TextOperation.Range.transform(newRange, op.diff, expandLeft, expandRight);
      if (changed) {
        if (newRange[0] === newRange[1]) {
          _delete(this, annotation);
        } else {
          this.document.set([annotation.id, "range"], newRange);
        }
      }
    }
    // if somebody has reset the property we must delete the annotation
    else if (op.type === "delete" || op.type === "set") {
      _delete(this, annotation);
    }
  };

  this.transform = function(op) {
    var annotations = this._index.get(op.path);
    _.each(annotations, function(a) {
      _transform.call(this, op, a);
    }, this);
  };

  this.paste = function(/*annotations, newNodeId, offset*/) {
    throw new Error("FIXME: this must be updated considering the other API changes.");

    // for (var i = 0; i < annotations.length; i++) {
    //   var annotation = annotations[i];
    //   if (newNodeId !== undefined) {
    //     annotation.path = _.clone(annotation.path);
    //     annotation.path[0] = newNodeId;
    //   }
    //   if (offset !== undefined) {
    //     annotation.range[0] += offset;
    //     annotation.range[1] += offset;
    //   }
    //   this.create(annotation);
    // }
  };

  // Copy annotations in the given selection.
  // --------
  // This is the pendant to the writer's copy method.
  // Partially selected annotations may not get copied depending on the
  // annotation type, for others, new annotation fragments would be created.

  this.copy = function(/*selection*/) {
    throw new Error("FIXME: this must be updated considering the other API changes.");

    // var ranges = _getRanges(this, selection);

    // // get all affected annotations
    // var annotations = this.getAnnotations({selection: selection});
    // var result = [];

    // _.each(annotations, function(annotation) {

    //   // TODO: determine if an annotation would be split by the given selection.
    //   var range = ranges[annotation.path[0]];
    //   var isPartial = (range[0] > annotation.range[0] || range[1] < annotation.range[1]);

    //   var newAnnotation;
    //   if (isPartial) {
    //     // for the others create a new fragment (depending on type) and truncate the original
    //     if (this.isSplittable(annotation.type)) {
    //       newAnnotation = util.clone(annotation);
    //       // make the range relative to the selection
    //       newAnnotation.id = util.uuid();
    //       newAnnotation.range = [Math.max(0, annotation.range[0] - range[0]), annotation.range[1] - range[0]];
    //       result.push(newAnnotation);
    //     }
    //   } else {
    //     // add totally included ones
    //     // TODO: need more control over uuid generation
    //     newAnnotation = util.clone(annotation);
    //     newAnnotation.id = util.uuid();
    //     newAnnotation.range = [newAnnotation.range[0] - range[0], newAnnotation.range[1] - range[0]];
    //     result.push(newAnnotation);
    //   }

    // }, this);

    // return result;
  };

  // Retrieve annotations
  // --------
  // The selection can be filtered via
  //
  // - node + range : a node id and (optionally) a given range (only if node is given)
  // - selection: a selection of type `{start: [nodePos, charPos], end: [nodePos, charPos]}`
  // - filter: a custom filter of type `function(annotation) -> boolean`
  //

  // var _filterAnnotations = function(filter, annotations) {
  //   var filtered = [];
  //   _.each(annotations, function(a) {
  //     if(filter(a)) {
  //       filtered.push(a);
  //     }
  //   });
  //   return filtered;
  // };

  var __isOverlap = function(anno, range) {
    var sStart = range.start;
    var sEnd = range.end;
    var aStart = anno.range[0];
    var aEnd = anno.range[1];

    var overlap = (aEnd >= sStart);

    // Note: it is allowed to give only omit the end part
    if (_.isNumber(sEnd)) {
      overlap &= (aStart <= sEnd);
    }

    return overlap;
  };

  var _filterByRange = function(range) {

    var result = [];
    var component = range.component;

    var annotations;
    if (component.type === "node") {
      var node = component.node;
      annotations = this._index.get(node.id);
    }
    else if (component.type === "property") {
      annotations = this._index.get(component.propertyPath);
    }
    else if (component.type === "custom") {
      annotations = this._index.get(component.path);
    }
    else {
      console.error("FIXME");
    }

    _.each(annotations, function(a) {
      if (__isOverlap(a, range)) {
        result.push(a);
      }
    });

    return result;
  };

  this.getAnnotationsForNode = function(nodeId) {
    return this._index.get(nodeId);
  };

  // TODO: we could do a minor optimization, as it happens that the same query is performed multiple times
  // -- which is ok as those are different peers.
  this.getAnnotations = function(sel) {
    if (!(sel instanceof Document.Selection)) {
      throw new Error("API has changed: now getAnnotations() takes only a selection.");
    }

    var annotations = [];

    var ranges = sel.getRanges();

    for (var i = 0; i < ranges.length; i++) {
      var range = ranges[i];
      var annos = _filterByRange.call(this, range);
      annotations = annotations.concat(annos);
    }

    // console.log("Annotator.getAnnotations():", sel, annotations);
    return annotations;
  };

  // Returns true if two annotation types are mutually exclusive
  // ---------
  // Currently there is a built-in mechanism which considers two annotations
  // exclusive if they belong to the same group.
  //

  this.isExclusive = function(type1, type2) {
    return this.groups[type1] === this.groups[type2];
  };

  // Tell if an annotation can be split or should be truncated only.
  // --------
  //
  // E.g. when cutting a selection or inserting a new node existing annotations
  // may be affected. In some cases (e.g., `emphasis` or `strong`) it is wanted
  // that a new annotation of the same type is created for the cut fragment.

  this.isSplittable = function(type) {
    return this.split.indexOf(type) >= 0;
  };

  this.dispose = function() {
    this.stopListening();
  };
};

Annotator.Prototype.prototype = util.Events;
Annotator.prototype = new Annotator.Prototype();

Annotator.isOnNodeStart = function(a) {
  return a.range[0] === 0;
};

Annotator.isTrue = function() {
  return true;
};

// Creates a shared index for annotations on a given document.
// --------
//

Annotator.createIndex = function(doc) {
  if (doc.indexes["annotations"] === undefined) {
    var options = {
      types: ["annotation"],
      property: "path"
    };
    var index = doc.addIndex("annotations", options);
    index.ENABLE_LOGGING = true;
    doc.indexes["annotations"] = index;
  }
  return doc.indexes["annotations"];
};

// TODO:
Annotator.defaultBehavior = {
  groups: {
    "emphasis": "style",
    "strong": "style",
    "link": "style",
    "remark": "marker",
    "idea": "marker",
    "remark_reference": "marker",
    "error_reference": "marker"
  },
  expansion: {
    "emphasis": {
      left: Annotator.isOnNodeStart,
    },
    "strong": {
      left: Annotator.isOnNodeStart,
    }
  },
  split: ["emphasis", "strong"],
  levels: {
    idea: 1,
    remark: 1,
    error: 1,
    comment: 1,
    link: 1,
    strong: 2,
    emphasis: 2,
    code: 2,
    subscript: 2,
    superscript: 2,
    underline: 2,
    cross_reference: 1,
    figure_reference: 1,
    person_reference: 1,
    citation_reference: 1,
    error_reference: 1,
    remark_reference: 1
  }
};

// LEGACY: I moved this to util as it is useful in different contexts:
// currently Annotations, Markdown-Converter.
Annotator.Fragmenter = require("substance-util").Fragmenter;

// Export
// ========

module.exports = Annotator;
<commit_msg>Breaking: first round on streamlining the annotator.<commit_after>"use strict";

var _ = require("underscore");
var util = require("substance-util");
var Document = require("./document");
var Operator = require("substance-operator");

var _getConfig;

// A class that provides helpers to manage a document's annotations.
// --------
//
// Note: the provided document is used to retrieve the annotation behavior and to initialize an annotation index.
//
var Annotator = function(doc) {
  this.config = _getConfig(doc);
  doc.addIndex("annotations", {types: ["annotation"], property: "path"});
  this.document = doc;
};

Annotator.Prototype = function() {

  // Updates all annotations according to a given operation.
  // --------
  //
  // The provided operation is an ObjectOperation which has been applied already or should be applied afterwards.
  //
  // Depending on the operation's `path` and the impact on an annotations range
  // there are the following cases:
  // 1. op='update', path==a.path: update the range following the rules given in the configuration
  // 2. op='delete', path[0]==a.path[0]: the annotation gets deleted
  // 3. op='set', path==a.path: the annotation gets deleted as the referenced property has been reset
  //
  this.update = function(op) {
    var index = this.document.getIndex("annotations");
    var annotations = index.get(op.path);
    _.each(annotations, function(a) {
      _update(this, a, op);
    }, this);
  };

  // Copy annotations in the given selection.
  // --------
  // This is the pendant to the writer's copy method.
  // Partially selected annotations may not get copied depending on the
  // annotation type, for others, new annotation fragments would be created.

  this.copy = function(/*selection*/) {
    throw new Error("FIXME: this must be updated considering the other API changes.");

    // var ranges = _getRanges(this, selection);

    // // get all affected annotations
    // var annotations = this.getAnnotations(session, selection);
    // var result = [];

    // _.each(annotations, function(annotation) {

    //   // TODO: determine if an annotation would be split by the given selection.
    //   var range = ranges[annotation.path[0]];
    //   var isPartial = (range[0] > annotation.range[0] || range[1] < annotation.range[1]);

    //   var newAnnotation;
    //   if (isPartial) {
    //     // for the others create a new fragment (depending on type) and truncate the original
    //     if (this.isSplittable(annotation.type)) {
    //       newAnnotation = util.clone(annotation);
    //       // make the range relative to the selection
    //       newAnnotation.id = util.uuid();
    //       newAnnotation.range = [Math.max(0, annotation.range[0] - range[0]), annotation.range[1] - range[0]];
    //       result.push(newAnnotation);
    //     }
    //   } else {
    //     // add totally included ones
    //     // TODO: need more control over uuid generation
    //     newAnnotation = util.clone(annotation);
    //     newAnnotation.id = util.uuid();
    //     newAnnotation.range = [newAnnotation.range[0] - range[0], newAnnotation.range[1] - range[0]];
    //     result.push(newAnnotation);
    //   }

    // }, this);

    // return result;
  };

  this.paste = function(/*annotations, newNodeId, offset*/) {
    throw new Error("FIXME: this must be updated considering the other API changes.");
    // for (var i = 0; i < annotations.length; i++) {
    //   var annotation = annotations[i];
    //   if (newNodeId !== undefined) {
    //     annotation.path = _.clone(annotation.path);
    //     annotation.path[0] = newNodeId;
    //   }
    //   if (offset !== undefined) {
    //     annotation.range[0] += offset;
    //     annotation.range[1] += offset;
    //   }
    //   this.create(annotation);
    // }
  };

  this.getAnnotationsForNode = function(nodeId) {
    return this.index.get(nodeId);
  };

  // Provides all annotations that correspond to a given selection.
  // --------
  // TODO: we could do a minor optimization, as it happens that the same query is performed multiple times.
  //
  this.getAnnotations = function(sel) {
    if (!(sel instanceof Document.Selection)) {
      throw new Error("API has changed: now getAnnotations() takes only a selection.");
    }

    var annotations = [];
    var ranges = sel.getRanges();
    for (var i = 0; i < ranges.length; i++) {
      var range = ranges[i];
      var annos = _annotationsByRange(this.document, range);
      annotations = annotations.concat(annos);
    }
    // console.log("Annotator.getAnnotations():", sel, annotations);
    return annotations;
  };

  // Returns true if two annotation types are mutually exclusive
  // ---------
  // Currently there is a built-in mechanism which considers two annotations
  // exclusive if they belong to the same group.
  //
  this.isExclusive = function(type1, type2) {
    return this.config.groups[type1] === this.config.groups[type2];
  };

  // Tell if an annotation can be split or should be truncated only.
  // --------
  //
  // E.g. when cutting a selection or inserting a new node existing annotations
  // may be affected. In some cases (e.g., `emphasis` or `strong`) it is wanted
  // that a new annotation of the same type is created for the cut fragment.
  //
  this.isSplittable = function(type) {
    return this.config.split.indexOf(type) >= 0;
  };

  // Updates a single annotation according to a given operation.
  // --------
  //
  var _update = function(self, annotation, op) {
    // only apply the transformation on annotations with the same property
    // Note: currently we only have annotations on the `content` property of nodes
    if (!_.isEqual(annotation.path, op.path)) return;

    if (op.type === "update") {
      // Note: these are implicit transformations, i.e., not triggered via annotation controls
      var expandLeft = false;
      var expandRight = false;

      var expandSpec = self.config.expansion[annotation.type];
      if (expandSpec) {
        if (expandSpec.left) expandLeft =  expandSpec.left(annotation);
        if (expandSpec.right) expandRight = expandSpec.right(annotation);
      }

      var newRange = util.clone(annotation.range);
      var changed = Operator.TextOperation.Range.transform(newRange, op.diff, expandLeft, expandRight);
      if (changed) {
        if (newRange[0] === newRange[1]) {
          self.document.delete(annotation.id);
        } else {
          self.document.set([annotation.id, "range"], newRange);
        }
      }
    }
    // if somebody has reset the property we must delete the annotation
    else if (op.type === "delete" || op.type === "set") {
      self.document.delete(annotation.id);
    }
  };

  // Checks if an annotation overlaps with a given range
  // --------
  //
  var __isOverlap = function(anno, range) {
    var sStart = range.start;
    var sEnd = range.end;
    var aStart = anno.range[0];
    var aEnd = anno.range[1];
    var overlap = (aEnd >= sStart);

    // Note: it is allowed to omit the end part
    if (_.isNumber(sEnd)) {
      overlap &= (aStart <= sEnd);
    }
    return overlap;
  };

  var _annotationsByRange = function(doc, range) {
    var result = [];
    var component = range.component;
    var annotations;
    var index = doc.getIndex("annotations");

    if (component.type === "node") {
      var node = component.node;
      annotations = index.get(node.id);
    }
    else if (component.type === "property") {
      annotations = index.get(component.propertyPath);
    }
    else if (component.type === "custom") {
      annotations = index.get(component.path);
    }
    else {
      console.error("FIXME");
    }
    _.each(annotations, function(a) {
      if (__isOverlap(a, range)) {
        result.push(a);
      }
    });
    return result;
  };

};

Annotator.Prototype.prototype = util.Events;
Annotator.prototype = new Annotator.Prototype();

Annotator.isOnNodeStart = function(a) {
  return a.range[0] === 0;
};

Annotator.isTrue = function() {
  return true;
};

_getConfig = function(doc) {
  // Note: this is rather experimental
  // It is important to inverse the control over the annotation behavior,
  // i.e., which annotations exist and how they should be handled
  // This approach makes use of the static context of a Document implementation (e.g., Substance.Article)
  // For this to work you need to have:
  // - the `constructor` property set on the class
  // - a static property `annotationBehavior` specifying the behavior
  //   according to `Annotator.defaultBehavior`
  if (doc.constructor && doc.constructor.annotationBehavior) {
    return doc.constructor.annotationBehavior;
  } else {
    throw new Error("No Annotation behavior specified.");
  }
};

module.exports = Annotator;
<|endoftext|>


<commit_before>import SPECS from 'common/SPECS';
import SPEC_ANALYSIS_COMPLETENESS from 'common/SPEC_ANALYSIS_COMPLETENESS';

import CombatLogParser from './CombatLogParser';
import CHANGELOG from './CHANGELOG';

export default {
  spec: SPECS.RESTORATION_DRUID,
  maintainer: '@blazyb and @sref',
  completeness: SPEC_ANALYSIS_COMPLETENESS.GREAT, // When changing this please make a PR with ONLY this value changed, we will do a review of your analysis to find out of it is complete enough.
  changelog: CHANGELOG,
  parser: CombatLogParser,
  path: __dirname, // used for generating a GitHub link directly to your spec
};
<commit_msg>[resto druid] Added spec info to CONFIG.js<commit_after>import React from 'react';

import SPECS from 'common/SPECS';
import SPEC_ANALYSIS_COMPLETENESS from 'common/SPEC_ANALYSIS_COMPLETENESS';

import CombatLogParser from './CombatLogParser';
import CHANGELOG from './CHANGELOG';

export default {
  spec: SPECS.RESTORATION_DRUID,
  maintainer: '@blazyb and @sref',
  description: (

      Welcome to the Resto Druid analyzer! We hope you find these suggestions and statistics useful.

      If you want to learn more about Resto Druids, join the Druid community at the Dreamgrove discord channel. Remember to check the pins (ctrl-P while in #resto channel) for guides, FAQs, and gearing guidelines.

  ),
  completeness: SPEC_ANALYSIS_COMPLETENESS.GREAT, // When changing this please make a PR with ONLY this value changed, we will do a review of your analysis to find out of it is complete enough.
  specDiscussionUrl: 'https://github.com/WoWAnalyzer/WoWAnalyzer/issues/55',
  changelog: CHANGELOG,
  parser: CombatLogParser,
  path: __dirname, // used for generating a GitHub link directly to your spec
};
<|endoftext|>


<commit_before>angular.module('angulartics.prx.count', ['angulartics', 'prx.url-translate'])
.config(['$provide', function ($provide) {
  $provide.decorator('$analytics', ['$delegate', '$window', 'urlTranslate', function ($delegate, $window, urlTranslate) {
    var pageTrack = $delegate.pageTrack;
    var eventTrack = $delegate.eventTrack;
    var prefix = window.location.protocol + '//' + window.location.host;

    $delegate.pageTrack = function (url) {
      TheCount.logAction({action: 'view', url: prefix + urlTranslate(url)});
      pageTrack.call(this, url);
    };

    $delegate.eventTrack = function (eventName, eventValue) {
      TheCount.logAction({
        action: eventName.split(' ',1).join('').toLowerCase(),
        action_value: JSON.stringify(eventValue)
      });
      eventTrack.call(this, eventName, eventValue);
    };

    return $delegate;
  }]);
}]);
<commit_msg>translate url for action logging<commit_after>angular.module('angulartics.prx.count', ['angulartics', 'prx.url-translate'])
.config(['$provide', function ($provide) {
  $provide.decorator('$analytics', ['$delegate', '$window', 'urlTranslate', function ($delegate, $window, urlTranslate) {
    var pageTrack = $delegate.pageTrack;
    var eventTrack = $delegate.eventTrack;
    var prefix = window.location.protocol + '//' + window.location.host;

    $delegate.pageTrack = function (url) {
      TheCount.logAction({action: 'view', url: prefix + urlTranslate(url)});
      pageTrack.call(this, url);
    };

    $delegate.eventTrack = function (eventName, eventValue) {
      TheCount.logAction({
        url: (prefix + urlTranslate(url)),
        action: eventName.split(' ',1).join('').toLowerCase(),
        action_value: JSON.stringify(eventValue)
      });
      eventTrack.call(this, eventName, eventValue);
    };

    return $delegate;
  }]);
}]);
<|endoftext|>


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

const Checkbox = ({
  className,
  id,
  labelText,
  onChange,
  indeterminate,
  hideLabel,
  wrapperClassName,
  title = '',
  ...other
}) => {
  let input;
  const labelClasses = classNames('bx--checkbox-label', className);
  const innerLabelClasses = classNames({
    'bx--visually-hidden': hideLabel,
  });
  const wrapperClasses = classNames(
    'bx--form-item',
    'bx--checkbox-wrapper',
    wrapperClassName
  );

  return (

      <input
        {...other}
        type="checkbox"
        onChange={evt => {
          onChange(input.checked, id, evt);
        }}
        className="bx--checkbox"
        id={id}
        ref={el => {
          input = el;
          if (input) {
            input.indeterminate = indeterminate;
          }
        }}
      />

        {labelText}

  );
};

Checkbox.propTypes = {
  checked: PropTypes.bool,
  defaultChecked: PropTypes.bool,
  indeterminate: PropTypes.bool,
  /**
   * The CSS class name to be placed on inner label element.
   */
  className: PropTypes.string,
  disabled: PropTypes.bool,
  id: PropTypes.string.isRequired,
  labelText: PropTypes.node.isRequired,
  hideLabel: PropTypes.bool,
  onChange: PropTypes.func,
  title: PropTypes.string,
  /**
   * The CSS class name to be placed on the wrapping element
   */
  wrapperClassName: PropTypes.string,
};

Checkbox.defaultProps = {
  onChange: () => {},
  indeterminate: false,
};

export default Checkbox;
<commit_msg>docs: Add description. (#1214)<commit_after>import PropTypes from 'prop-types';
import React from 'react';
import classNames from 'classnames';

const Checkbox = ({
  className,
  id,
  labelText,
  onChange,
  indeterminate,
  hideLabel,
  wrapperClassName,
  title = '',
  ...other
}) => {
  let input;
  const labelClasses = classNames('bx--checkbox-label', className);
  const innerLabelClasses = classNames({
    'bx--visually-hidden': hideLabel,
  });
  const wrapperClasses = classNames(
    'bx--form-item',
    'bx--checkbox-wrapper',
    wrapperClassName
  );

  return (

      <input
        {...other}
        type="checkbox"
        onChange={evt => {
          onChange(input.checked, id, evt);
        }}
        className="bx--checkbox"
        id={id}
        ref={el => {
          input = el;
          if (input) {
            input.indeterminate = indeterminate;
          }
        }}
      />

        {labelText}

  );
};

Checkbox.propTypes = {
  checked: PropTypes.bool,
  defaultChecked: PropTypes.bool,
  indeterminate: PropTypes.bool,
  /**
   * The CSS class name to be placed on inner label element.
   */
  className: PropTypes.string,
  disabled: PropTypes.bool,
  id: PropTypes.string.isRequired,
  labelText: PropTypes.node.isRequired,
  hideLabel: PropTypes.bool,
  /**
   * Receives three arguments: true/false, the checkbox's id, and the dom event.
   * `(value, id, event) => console.log({value, id, event})`
   */
  onChange: PropTypes.func,
  title: PropTypes.string,
  /**
   * The CSS class name to be placed on the wrapping element
   */
  wrapperClassName: PropTypes.string,
};

Checkbox.defaultProps = {
  onChange: () => {},
  indeterminate: false,
};

export default Checkbox;
<|endoftext|>