<commit_before>import React, { Component } from 'react'
import GameTable from '../GameTable'
import PlayerUI from '../PlayerUI'

export default class App extends Component {

  constructor( props ) {
    super( props )
    this.state = {
      ai_1: {},
      ai_2: {},
      dealer: {},
      deck: [],
      number_of_decks: 2,
      player: {},
      round: 0,
      turn: 0
    }
    this.hitItPlayer = this.hitItPlayer.bind( this )
    this.newRound = this.newRound.bind( this )
    this.setupGame = this.setupGame.bind( this )
    this.showDealerCard = this.showDealerCard.bind( this )
    this.testDeal = this.testDeal.bind( this )
    this.handValue = this.handValue.bind( this )
  }

  componentDidMount() {
    this.setupGame()
  }

  setupGame() {
    let decks = (this.state.number_of_decks < 2 ) ? 2 : this.state.number_of_decks
    this.createCards(decks)
    this.createPlayers()
  }

  newRound() {
    let { ai_1, ai_2, dealer, player, turn, round } = this.state
    ai_1.hand = []
    ai_2.hand = []
    dealer.hand = []
    player.hand = []
    turn = 0
    round++
    this.setState({ ai_1, ai_2, dealer, player, turn, round })
  }

  createPlayers() {
    const dealerName = 'Jeff Goldblum'
    const aiNames = [ 'Bob Ross', 'Pamela Anderson' ]
    const playerName = prompt( 'What is your name?' )
    const round = 0

    const dealer = {
      name: dealerName,
      hand: [],
      role: 'dealer'
    }
    dealer.hand.value = 0
    dealer.hand.bet = 0

    const ai_1 = { name: aiNames[0], bank: 100, hand: [], role: 'ai' }
    ai_1.hand.value = 0
    ai_1.hand.bet = 0
    const ai_2 = { name: aiNames[1], bank: 100, hand: [], role: 'ai' }
    ai_2.hand.value = 0
    ai_2.hand.bet = 0

    const player = {
      name: playerName,
      bank: 100,
      hand: [],
      role: 'player'
    }
    player.hand.value = 0
    player.hand.bet = 0
    this.setState({ dealer, ai_1, ai_2, player, round })
  }

  createCards( deckQuantity ) {
    let decks = []
    for (var q = 0; q < deckQuantity; q++) {
      const cards = []
      const faces = ['A','2','3','4','5','6','7','8','9','10','J','Q','K']
      const suits = ['Spade','Diamond','Club','Heart']

      for (var i = 0; i < 4; i++) {
        for (var j = 0; j < 13; j++) {
          let item = { face: faces[j], suit: suits[i], value: this.getValue(faces[j]), faceDown: false }
          item.isAce = ( item.value == 11 ) ? true : false
          cards.push(item)
        }
      }

      let passByReference = {deck: cards}
      this.shuffle(passByReference)
      decks.push(cards)
    }

    let merged = [].concat.apply([], decks)
    this.setState({ deck: merged })
  }

  getValue( face ) {
    if( face === 'A' ) return 11
    else if(face === 'J' || face === 'Q' || face === 'K') return 10
    else return parseInt( face )
  }

  shuffle( passByReference ) {
    passByReference.deck = passByReference.deck || []

    var j, x, i
    for (i = passByReference.deck.length; i; i--) {
      j = Math.floor(Math.random() * i)
      x = passByReference.deck[i - 1]
      passByReference.deck[i - 1] = passByReference.deck[j]
      passByReference.deck[j]= x
    }
  }

  testDeal() {
    let { ai_1, ai_2, dealer, deck, player, turn } = this.state

    if ( turn < 1 ) {
      for ( let cycle = 0; cycle<2; cycle++ ) {
        ai_1.hand.push( deck.shift() )
        player.hand.push( deck.shift() )
        ai_2.hand.push( deck.shift() )
        dealer.hand.push( deck.shift() )
        if (cycle === 0) { dealer.hand[0].faceDown = true}
      }
      turn = 1
    } else {
      return
    }
    console.log(deck.length)
    ai_1.hand.value = this.handValue( ai_1.hand )
    ai_2.hand.value = this.handValue( ai_2.hand )
    player.hand.value = this.handValue( player.hand )
    dealer.hand.value = this.handValue( dealer.hand )
    this.setState({ ai_1, ai_2, dealer, deck, player, turn })
  }

  aiTurn( whichAiPlayer ) {
    let holdStats = getLocalStorage('hold')
    let hitStats = getLocalStorage('hitStats')

    if () {
      hitItPlayer( whichAiPlayer )
    } else {
      // skip turn by doing nothing. We're holding.
    }
  }

  getLocalStorage(type) {
    let holdStats = {
      currentlyGathering: true,
      playerHand: player.hand,
      playerValue: this.handValue( player.hand ),
      dealerHand: dealer.hand,
      dealerValue: this.handValue( dealer.hand ),
      hitOrStay: type,
      winOrLose: 'pending'
    }
    let stats = JSON.parse(localStorage.getItem(type) || '[]')
    stats.push( holdStats )
    return stats
  }

  makeChoice(type) {
    // Seek similar hands to what player had
    let predictAction = getLocalStorage(type).find( (ele) => {
      if(ele.playerValue >= p1ofN*currPlayerValue && ele.playerValue < p2ofN*currPlayerValue) return ele.hitOrStay
    })

    // If unable to find similar circumstance, then guess
    // random and adjust weights
    if( predictAction === undefined) {
      do {
        p1ofN = Math.random()
        p2ofN = Math.random()
      } while (p1ofN > p2ofN)
      // Store random value into database to check against later
      predictAction = Math.random() > 0.5 ? 'hit' : 'stay'
    }
    return predictAction
  }

  holdButton() {
    let { ai_1, ai_2, dealer, player, deck } = this.state

    // START AI Capture K for k-n-n
    localStorage.setItem('hold', JSON.stringify( getLocalStorage('hold') ))
    // END AI
  }

  hitItPlayer( whichPlayer ) {

   let { ai_1, ai_2, dealer, player, deck } = this.state

   // START AI Capture K for k-n-n
   localStorage.setItem('hit', JSON.stringify( getLocalStorage('hit') ))
   // END AI

   console.log('--> Hand with length?', player.hand)

   const temp = {
     "player": player,
     "dealer": dealer,
     "ai_1": ai_1,
     "ai_2": ai_2
   }

   let hand = temp[ whichPlayer ].hand

   if ( this.handValue( hand ) >= 21 ){ return }
   if ( hand.length < 5 ) {

     hand.push( deck.shift() )
     hand.value = this.handValue( hand )
     //NOTE: With this method I think we may be loosing the 'value' key when
     // it is put back into the state. When I add the value key to a hand
     // I don't see it in the state and when I try to store it and access
     // it later its not there.
     temp[whichPlayer].hand = hand
     this.setState({ ai_1, ai_2, dealer, player, deck })
     return
   }
   else {
     return
   }
  }

 //TODO: Adjust handValue() function to act dynamically on the hand
  handValue( hand ) {

   if ( hand.length <= 0 ){ return 0 }

    let value = 0
    hand.map( card => {
      value += card.value
    })
    return value
  }

  showDealerCard() {
    let { dealer } = this.state
    dealer.hand[0].faceDown = false
    this.setState({ dealer })
  }

  render() {

    const { ai_1, ai_2, dealer, deck, player, round } = this.state

    return (

          <GameTable ai_1={ai_1} ai_2={ai_2} dealer={dealer} deck={deck} player={player} round={round} />
          <PlayerUI
            testDeal={this.testDeal}
            reset={this.newRound}
            showCard={this.showDealerCard}
            hitItPlayer={this.hitItPlayer}
            playerBank={player.bank}
            playerHandValue={player.hand.value}
          />

      )
  }
}
<commit_msg>Fix error of updating function when only intending to get info in makeChoice<commit_after>import React, { Component } from 'react'
import GameTable from '../GameTable'
import PlayerUI from '../PlayerUI'

export default class App extends Component {

  constructor( props ) {
    super( props )
    this.state = {
      ai_1: {},
      ai_2: {},
      dealer: {},
      deck: [],
      number_of_decks: 2,
      player: {},
      round: 0,
      turn: 0
    }
    this.hitItPlayer = this.hitItPlayer.bind( this )
    this.newRound = this.newRound.bind( this )
    this.setupGame = this.setupGame.bind( this )
    this.showDealerCard = this.showDealerCard.bind( this )
    this.testDeal = this.testDeal.bind( this )
    this.handValue = this.handValue.bind( this )
  }

  componentDidMount() {
    this.setupGame()
  }

  setupGame() {
    let decks = (this.state.number_of_decks < 2 ) ? 2 : this.state.number_of_decks
    this.createCards(decks)
    this.createPlayers()
  }

  newRound() {
    let { ai_1, ai_2, dealer, player, turn, round } = this.state
    ai_1.hand = []
    ai_2.hand = []
    dealer.hand = []
    player.hand = []
    turn = 0
    round++
    this.setState({ ai_1, ai_2, dealer, player, turn, round })
  }

  createPlayers() {
    const dealerName = 'Jeff Goldblum'
    const aiNames = [ 'Bob Ross', 'Pamela Anderson' ]
    const playerName = prompt( 'What is your name?' )
    const round = 0

    const dealer = {
      name: dealerName,
      hand: [],
      role: 'dealer'
    }
    dealer.hand.value = 0
    dealer.hand.bet = 0

    const ai_1 = { name: aiNames[0], bank: 100, hand: [], role: 'ai' }
    ai_1.hand.value = 0
    ai_1.hand.bet = 0
    const ai_2 = { name: aiNames[1], bank: 100, hand: [], role: 'ai' }
    ai_2.hand.value = 0
    ai_2.hand.bet = 0

    const player = {
      name: playerName,
      bank: 100,
      hand: [],
      role: 'player'
    }
    player.hand.value = 0
    player.hand.bet = 0
    this.setState({ dealer, ai_1, ai_2, player, round })
  }

  createCards( deckQuantity ) {
    let decks = []
    for (var q = 0; q < deckQuantity; q++) {
      const cards = []
      const faces = ['A','2','3','4','5','6','7','8','9','10','J','Q','K']
      const suits = ['Spade','Diamond','Club','Heart']

      for (var i = 0; i < 4; i++) {
        for (var j = 0; j < 13; j++) {
          let item = { face: faces[j], suit: suits[i], value: this.getValue(faces[j]), faceDown: false }
          item.isAce = ( item.value == 11 ) ? true : false
          cards.push(item)
        }
      }

      let passByReference = {deck: cards}
      this.shuffle(passByReference)
      decks.push(cards)
    }

    let merged = [].concat.apply([], decks)
    this.setState({ deck: merged })
  }

  getValue( face ) {
    if( face === 'A' ) return 11
    else if(face === 'J' || face === 'Q' || face === 'K') return 10
    else return parseInt( face )
  }

  shuffle( passByReference ) {
    passByReference.deck = passByReference.deck || []

    var j, x, i
    for (i = passByReference.deck.length; i; i--) {
      j = Math.floor(Math.random() * i)
      x = passByReference.deck[i - 1]
      passByReference.deck[i - 1] = passByReference.deck[j]
      passByReference.deck[j]= x
    }
  }

  testDeal() {
    let { ai_1, ai_2, dealer, deck, player, turn } = this.state

    if ( turn < 1 ) {
      for ( let cycle = 0; cycle<2; cycle++ ) {
        ai_1.hand.push( deck.shift() )
        player.hand.push( deck.shift() )
        ai_2.hand.push( deck.shift() )
        dealer.hand.push( deck.shift() )
        if (cycle === 0) { dealer.hand[0].faceDown = true}
      }
      turn = 1
    } else {
      return
    }
    console.log(deck.length)
    ai_1.hand.value = this.handValue( ai_1.hand )
    ai_2.hand.value = this.handValue( ai_2.hand )
    player.hand.value = this.handValue( player.hand )
    dealer.hand.value = this.handValue( dealer.hand )
    this.setState({ ai_1, ai_2, dealer, deck, player, turn })
  }

  aiTurn( whichAiPlayer ) {
    let holdStats = getLocalStorage('hold')
    let hitStats = getLocalStorage('hitStats')

    if () {
      hitItPlayer( whichAiPlayer )
    } else {
      // skip turn by doing nothing. We're holding.
    }
  }

  getLocalStorage(type) {
    let holdStats = {
      currentlyGathering: true,
      playerHand: player.hand,
      playerValue: this.handValue( player.hand ),
      dealerHand: dealer.hand,
      dealerValue: this.handValue( dealer.hand ),
      hitOrStay: type,
      winOrLose: 'pending'
    }
    let stats = JSON.parse(localStorage.getItem(type) || '[]')
    stats.push( holdStats )
    return stats
  }

  makeChoice(type) {
    // Seek similar hands to what player had
    let stats = JSON.parse(localStorage.getItem(type) || '[]')
    let predictAction = stats.find( (ele) => {
      if(ele.playerValue >= p1ofN*currPlayerValue && ele.playerValue < p2ofN*currPlayerValue) return ele.hitOrStay
    })

    // If unable to find similar circumstance, then guess
    // random and adjust weights
    if( predictAction === undefined) {
      do {
        p1ofN = Math.random()
        p2ofN = Math.random()
      } while (p1ofN > p2ofN)
      // Store random value into database to check against later
      predictAction = Math.random() > 0.5 ? 'hit' : 'stay'
    }
    return predictAction
  }

  holdButton() {
    let { ai_1, ai_2, dealer, player, deck } = this.state

    // START AI Capture K for k-n-n
    localStorage.setItem('hold', JSON.stringify( getLocalStorage('hold') ))
    // END AI
  }

  hitItPlayer( whichPlayer ) {

   let { ai_1, ai_2, dealer, player, deck } = this.state

   // START AI Capture K for k-n-n
   localStorage.setItem('hit', JSON.stringify( getLocalStorage('hit') ))
   // END AI

   console.log('--> Hand with length?', player.hand)

   const temp = {
     "player": player,
     "dealer": dealer,
     "ai_1": ai_1,
     "ai_2": ai_2
   }

   let hand = temp[ whichPlayer ].hand

   if ( this.handValue( hand ) >= 21 ){ return }
   if ( hand.length < 5 ) {

     hand.push( deck.shift() )
     hand.value = this.handValue( hand )
     //NOTE: With this method I think we may be loosing the 'value' key when
     // it is put back into the state. When I add the value key to a hand
     // I don't see it in the state and when I try to store it and access
     // it later its not there.
     temp[whichPlayer].hand = hand
     this.setState({ ai_1, ai_2, dealer, player, deck })
     return
   }
   else {
     return
   }
  }

 //TODO: Adjust handValue() function to act dynamically on the hand
  handValue( hand ) {

   if ( hand.length <= 0 ){ return 0 }

    let value = 0
    hand.map( card => {
      value += card.value
    })
    return value
  }

  showDealerCard() {
    let { dealer } = this.state
    dealer.hand[0].faceDown = false
    this.setState({ dealer })
  }

  render() {

    const { ai_1, ai_2, dealer, deck, player, round } = this.state

    return (

          <GameTable ai_1={ai_1} ai_2={ai_2} dealer={dealer} deck={deck} player={player} round={round} />
          <PlayerUI
            testDeal={this.testDeal}
            reset={this.newRound}
            showCard={this.showDealerCard}
            hitItPlayer={this.hitItPlayer}
            playerBank={player.bank}
            playerHandValue={player.hand.value}
          />

      )
  }
}
<|endoftext|>


<commit_before>/* global AFRAME, NAF, THREE */
var deepEqual = require('../DeepEquals');
var InterpolationBuffer = require('buffered-interpolation');
var DEG2RAD = THREE.Math.DEG2RAD;
var OBJECT3D_COMPONENTS = ['position', 'rotation', 'scale'];

function defaultRequiresUpdate() {
  let cachedData = null;

  return (newData) => {
    if (cachedData === null || !deepEqual(cachedData, newData)) {
      cachedData = AFRAME.utils.clone(newData);
      return true;
    }

    return false;
  };
}

AFRAME.registerSystem("networked", {
  init() {
    this.components = [];
    this.nextSyncTime = 0;
  },

  register(component) {
    this.components.push(component);
  },

  deregister(component) {
    const idx = this.components.indexOf(component);

    if (idx > -1) {
      this.components.splice(idx, 1);
    }
  },

  tick: (function() {

    return function() {
      if (!NAF.connection.adapter) return;
      if (this.el.clock.elapsedTime < this.nextSyncTime) return;

      const data = { d: [] };

      for (let i = 0, l = this.components.length; i < l; i++) {
        const c = this.components[i];
        if (!c.isMine()) continue;
        if (!c.el.parentElement) {
          NAF.log.error("entity registered with system despite being removed");
          //TODO: Find out why tick is still being called
          return;
        }

        const syncData = this.components[i].syncDirty();
        if (!syncData) continue;

        data.d.push(syncData);
      }

      if (data.d.length > 0) {
        NAF.connection.broadcastData('um', data);
      }

      this.updateNextSyncTime();
    };
  })(),

  updateNextSyncTime() {
    this.nextSyncTime = this.el.clock.elapsedTime + 1 / NAF.options.updateRate;
  }
});

AFRAME.registerComponent('networked', {
  schema: {
    template: {default: ''},
    attachTemplateToLocal: { default: true },
    persistent: { default: false },

    networkId: {default: ''},
    owner: {default: ''},
    creator: {default: ''}
  },

  init: function() {
    this.OWNERSHIP_GAINED = 'ownership-gained';
    this.OWNERSHIP_CHANGED = 'ownership-changed';
    this.OWNERSHIP_LOST = 'ownership-lost';

    this.onOwnershipGainedEvent = {
      el: this.el
    };
    this.onOwnershipChangedEvent = {
      el: this.el
    };
    this.onOwnershipLostEvent = {
      el: this.el
    };

    this.conversionEuler = new THREE.Euler();
    this.conversionEuler.order = "YXZ";
    this.bufferInfos = [];
    this.bufferPosition = new THREE.Vector3();
    this.bufferQuaternion = new THREE.Quaternion();
    this.bufferScale = new THREE.Vector3();

    var wasCreatedByNetwork = this.wasCreatedByNetwork();

    this.onConnected = this.onConnected.bind(this);

    this.syncData = {};
    this.componentSchemas =  NAF.schemas.getComponents(this.data.template);
    this.cachedElements = new Array(this.componentSchemas.length);
    this.networkUpdatePredicates = this.componentSchemas.map(x => (x.requiresNetworkUpdate && x.requiresNetworkUpdate()) || defaultRequiresUpdate());

    // Fill cachedElements array with null elements
    this.invalidateCachedElements();

    this.initNetworkParent();

    if (this.data.networkId === '') {
      this.el.setAttribute(this.name, {networkId: NAF.utils.createNetworkId()});
    }

    if (wasCreatedByNetwork) {
      this.firstUpdate();
    } else {
      if (this.data.attachTemplateToLocal) {
        this.attachTemplateToLocal();
      }

      this.registerEntity(this.data.networkId);
    }

    this.lastOwnerTime = -1;

    if (NAF.clientId) {
      this.onConnected();
    } else {
      document.body.addEventListener('connected', this.onConnected, false);
    }

    document.body.dispatchEvent(this.entityCreatedEvent());
    this.el.dispatchEvent(new CustomEvent('instantiated', {detail: {el: this.el}}));
    this.el.sceneEl.systems.networked.register(this);
  },

  attachTemplateToLocal: function() {
    const template = NAF.schemas.getCachedTemplate(this.data.template);
    const elAttrs = template.attributes;

    // Merge root element attributes with this entity
    for (let attrIdx = 0; attrIdx < elAttrs.length; attrIdx++) {
      this.el.setAttribute(elAttrs[attrIdx].name, elAttrs[attrIdx].value);
    }

    // Append all child elements
    while (template.firstElementChild) {
      this.el.appendChild(template.firstElementChild);
    }
  },

  takeOwnership: function() {
    const owner = this.data.owner;
    const lastOwnerTime = this.lastOwnerTime;
    const now = NAF.connection.getServerTime();
    if (owner && !this.isMine() && lastOwnerTime < now) {
      this.lastOwnerTime = now;
      this.removeLerp();
      this.el.setAttribute('networked', { owner: NAF.clientId });
      this.syncAll();

      this.onOwnershipGainedEvent.oldOwner = owner;
      this.el.emit(this.OWNERSHIP_GAINED, this.onOwnershipGainedEvent);

      this.onOwnershipChangedEvent.oldOwner = owner;
      this.onOwnershipChangedEvent.newOwner = NAF.clientId;
      this.el.emit(this.OWNERSHIP_CHANGED, this.onOwnershipChangedEvent);

      return true;
    }
    return false;
  },

  wasCreatedByNetwork: function() {
    return !!this.el.firstUpdateData;
  },

  initNetworkParent: function() {
    var parentEl = this.el.parentElement;
    if (parentEl['components'] && parentEl.components['networked']) {
      this.parent = parentEl;
    } else {
      this.parent = null;
    }
  },

  registerEntity: function(networkId) {
    NAF.entities.registerEntity(networkId, this.el);
  },

  applyPersistentFirstSync: function() {
    const { networkId } = this.data;
    const persistentFirstSync = NAF.entities.getPersistentFirstSync(networkId);
    if (persistentFirstSync) {
      this.networkUpdate(persistentFirstSync);
      NAF.entities.forgetPersistentFirstSync(networkId);
    }
  },

  firstUpdate: function() {
    var entityData = this.el.firstUpdateData;
    this.networkUpdate(entityData);
  },

  onConnected: function() {
    if (this.data.owner === '') {
      this.lastOwnerTime = NAF.connection.getServerTime();
      this.el.setAttribute(this.name, { owner: NAF.clientId, creator: NAF.clientId });
      setTimeout(() => {
        //a-primitives attach their components on the next frame; wait for components to be attached before calling syncAll
        if (!this.el.parentNode){
          NAF.log.warn("Networked element was removed before ever getting the chance to syncAll");
          return;
        }
        this.syncAll(undefined, true);
      }, 0);
    }

    document.body.removeEventListener('connected', this.onConnected, false);
  },

  isMine: function() {
    return this.data.owner === NAF.clientId;
  },

  createdByMe: function() {
    return this.data.creator === NAF.clientId;
  },

  tick: function(time, dt) {
    if (!this.isMine() && NAF.options.useLerp) {
      for (var i = 0; i < this.bufferInfos.length; i++) {
        var bufferInfo = this.bufferInfos[i];
        var buffer = bufferInfo.buffer;
        var object3D = bufferInfo.object3D;
        var componentNames = bufferInfo.componentNames;
        buffer.update(dt);
        if (componentNames.includes('position')) {
          object3D.position.copy(buffer.getPosition());
        }
        if (componentNames.includes('rotation')) {
          object3D.quaternion.copy(buffer.getQuaternion());
        }
        if (componentNames.includes('scale')) {
          object3D.scale.copy(buffer.getScale());
        }
      }
    }
  },

  /* Sending updates */

  syncAll: function(targetClientId, isFirstSync) {
    if (!this.canSync()) {
      return;
    }

    var components = this.gatherComponentsData(true);

    var syncData = this.createSyncData(components, isFirstSync);

    if (targetClientId) {
      NAF.connection.sendDataGuaranteed(targetClientId, 'u', syncData);
    } else {
      NAF.connection.broadcastDataGuaranteed('u', syncData);
    }
  },

  syncDirty: function() {
    if (!this.canSync()) {
      return;
    }

    var components = this.gatherComponentsData(false);

    if (components === null) {
      return;
    }

    return this.createSyncData(components);
  },

  getCachedElement(componentSchemaIndex) {
    var cachedElement = this.cachedElements[componentSchemaIndex];

    if (cachedElement) {
      return cachedElement;
    }

    var componentSchema = this.componentSchemas[componentSchemaIndex];

    if (componentSchema.selector) {
      return this.cachedElements[componentSchemaIndex] = this.el.querySelector(componentSchema.selector);
    } else {
      return this.cachedElements[componentSchemaIndex] = this.el;
    }
  },

  invalidateCachedElements() {
    for (var i = 0; i < this.cachedElements.length; i++) {
      this.cachedElements[i] = null;
    }
  },

  gatherComponentsData: function(fullSync) {
    var componentsData = null;

    for (var i = 0; i < this.componentSchemas.length; i++) {
      var componentSchema = this.componentSchemas[i];
      var componentElement = this.getCachedElement(i);

      if (!componentElement) {
        if (fullSync) {
          componentsData = componentsData || {};
          componentsData[i] = null;
        }
        continue;
      }

      var componentName = componentSchema.component ? componentSchema.component : componentSchema;
      var componentData = componentElement.getAttribute(componentName);

      if (componentData === null) {
        if (fullSync) {
          componentsData = componentsData || {};
          componentsData[i] = null;
        }
        continue;
      }

      var syncedComponentData = componentSchema.property ? componentData[componentSchema.property] : componentData;

      // Use networkUpdatePredicate to check if the component needs to be updated.
      // Call networkUpdatePredicate first so that it can update any cached values in the event of a fullSync.
      if (this.networkUpdatePredicates[i](syncedComponentData) || fullSync) {
        componentsData = componentsData || {};
        componentsData[i] = syncedComponentData;
      }
    }

    return componentsData;
  },

  createSyncData: function(components, isFirstSync) {
    var { syncData, data } = this;
    syncData.networkId = data.networkId;
    syncData.owner = data.owner;
    syncData.creator = data.creator;
    syncData.lastOwnerTime = this.lastOwnerTime;
    syncData.template = data.template;
    syncData.persistent = data.persistent;
    syncData.parent = this.getParentId();
    syncData.components = components;
    syncData.isFirstSync = !!isFirstSync;
    return syncData;
  },

  canSync: function() {
    // This client will send a sync if:
    //
    // - The client is the owner
    // - The client is the creator, and the owner is not in the room.
    //
    // The reason for the latter case is so the object will still be
    // properly instantiated if the owner leaves. (Since the object lifetime
    // is tied to the creator.)
    if (this.data.owner && this.isMine()) return true;
    if (!this.createdByMe()) return false;

    const clients = NAF.connection.getConnectedClients();

    for (let clientId in clients) {
      if (clientId === this.data.owner) return false;
    }

    return true;
  },

  getParentId: function() {
    this.initNetworkParent(); // TODO fix calling this each network tick
    if (!this.parent) {
      return null;
    }
    var netComp = this.parent.getAttribute('networked');
    return netComp.networkId;
  },

  /* Receiving updates */

  networkUpdate: function(entityData) {
    // Avoid updating components if the entity data received did not come from the current owner.
    if (entityData.lastOwnerTime < this.lastOwnerTime ||
          (this.lastOwnerTime === entityData.lastOwnerTime && this.data.owner > entityData.owner)) {
      return;
    }

    if (this.data.owner !== entityData.owner) {
      var wasMine = this.isMine();
      this.lastOwnerTime = entityData.lastOwnerTime;

      const oldOwner = this.data.owner;
      const newOwner = entityData.owner;

      this.el.setAttribute('networked', { owner: entityData.owner });

      if (wasMine) {
        this.onOwnershipLostEvent.newOwner = newOwner;
        this.el.emit(this.OWNERSHIP_LOST, this.onOwnershipLostEvent);
      }
      this.onOwnershipChangedEvent.oldOwner = oldOwner;
      this.onOwnershipChangedEvent.newOwner = newOwner;
      this.el.emit(this.OWNERSHIP_CHANGED, this.onOwnershipChangedEvent);
    }
    if (this.data.persistent !== entityData.persistent) {
      this.el.setAttribute('networked', { persistent: entityData.persistent });
    }
    this.updateNetworkedComponents(entityData.components);
  },

  updateNetworkedComponents: function(components) {
    for (var componentIndex = 0, l = this.componentSchemas.length; componentIndex < l; componentIndex++) {
      var componentData = components[componentIndex];
      var componentSchema = this.componentSchemas[componentIndex];
      var componentElement = this.getCachedElement(componentIndex);

      if (componentElement === null || componentData === null || componentData === undefined ) {
        continue;
      }

      if (componentSchema.component) {
        if (componentSchema.property) {
          this.updateNetworkedComponent(componentElement, componentSchema.component, componentSchema.property, componentData);
        } else {
          this.updateNetworkedComponent(componentElement, componentSchema.component, componentData);
        }
      } else {
        this.updateNetworkedComponent(componentElement, componentSchema, componentData);
      }
    }
  },

  updateNetworkedComponent: function (el, componentName, data, value) {
    if(!NAF.options.useLerp || !OBJECT3D_COMPONENTS.includes(componentName)) {
      if (value === undefined) {
        el.setAttribute(componentName, data);
      } else {
        el.setAttribute(componentName, data, value);
      }
      return;
    }

    let bufferInfo;

    for (let i = 0, l = this.bufferInfos.length; i < l; i++) {
      const info = this.bufferInfos[i];

      if (info.object3D === el.object3D) {
        bufferInfo = info;
        break;
      }
    }

    if (!bufferInfo) {
      bufferInfo = { buffer: new InterpolationBuffer(InterpolationBuffer.MODE_LERP, 0.1),
                     object3D: el.object3D,
                     componentNames: [componentName] };
      this.bufferInfos.push(bufferInfo);
    } else {
      var componentNames = bufferInfo.componentNames;
      if (!componentNames.includes(componentName)) {
        componentNames.push(componentName);
      }
    }
    var buffer = bufferInfo.buffer;

    switch(componentName) {
      case 'position':
        buffer.setPosition(this.bufferPosition.set(data.x, data.y, data.z));
        return;
      case 'rotation':
        this.conversionEuler.set(DEG2RAD * data.x, DEG2RAD * data.y, DEG2RAD * data.z);
        buffer.setQuaternion(this.bufferQuaternion.setFromEuler(this.conversionEuler));
        return;
      case 'scale':
        buffer.setScale(this.bufferScale.set(data.x, data.y, data.z));
        return;
    }
    NAF.log.error('Could not set value in interpolation buffer.', el, componentName, data, bufferInfo);
  },

  removeLerp: function() {
    this.bufferInfos = [];
  },

  remove: function () {
    if (this.isMine() && NAF.connection.isConnected()) {
      var syncData = { networkId: this.data.networkId };
      if (NAF.entities.hasEntity(this.data.networkId)) {
        NAF.connection.broadcastDataGuaranteed('r', syncData);
      } else {
        NAF.log.error("Removing networked entity that is not in entities array.");
      }
    }
    NAF.entities.forgetEntity(this.data.networkId);
    document.body.dispatchEvent(this.entityRemovedEvent(this.data.networkId));
    this.el.sceneEl.systems.networked.deregister(this);
  },

  entityCreatedEvent() {
    return new CustomEvent('entityCreated', {detail: {el: this.el}});
  },

  entityRemovedEvent(networkId) {
    return new CustomEvent('entityRemoved', {detail: {networkId: networkId}});
  }
});
<commit_msg>components/networked.js: this.data can be undefined<commit_after>/* global AFRAME, NAF, THREE */
var deepEqual = require('../DeepEquals');
var InterpolationBuffer = require('buffered-interpolation');
var DEG2RAD = THREE.Math.DEG2RAD;
var OBJECT3D_COMPONENTS = ['position', 'rotation', 'scale'];

function defaultRequiresUpdate() {
  let cachedData = null;

  return (newData) => {
    if (cachedData === null || !deepEqual(cachedData, newData)) {
      cachedData = AFRAME.utils.clone(newData);
      return true;
    }

    return false;
  };
}

AFRAME.registerSystem("networked", {
  init() {
    this.components = [];
    this.nextSyncTime = 0;
  },

  register(component) {
    this.components.push(component);
  },

  deregister(component) {
    const idx = this.components.indexOf(component);

    if (idx > -1) {
      this.components.splice(idx, 1);
    }
  },

  tick: (function() {

    return function() {
      if (!NAF.connection.adapter) return;
      if (this.el.clock.elapsedTime < this.nextSyncTime) return;

      const data = { d: [] };

      for (let i = 0, l = this.components.length; i < l; i++) {
        const c = this.components[i];
        if (!c.isMine()) continue;
        if (!c.el.parentElement) {
          NAF.log.error("entity registered with system despite being removed");
          //TODO: Find out why tick is still being called
          return;
        }

        const syncData = this.components[i].syncDirty();
        if (!syncData) continue;

        data.d.push(syncData);
      }

      if (data.d.length > 0) {
        NAF.connection.broadcastData('um', data);
      }

      this.updateNextSyncTime();
    };
  })(),

  updateNextSyncTime() {
    this.nextSyncTime = this.el.clock.elapsedTime + 1 / NAF.options.updateRate;
  }
});

AFRAME.registerComponent('networked', {
  schema: {
    template: {default: ''},
    attachTemplateToLocal: { default: true },
    persistent: { default: false },

    networkId: {default: ''},
    owner: {default: ''},
    creator: {default: ''}
  },

  init: function() {
    this.OWNERSHIP_GAINED = 'ownership-gained';
    this.OWNERSHIP_CHANGED = 'ownership-changed';
    this.OWNERSHIP_LOST = 'ownership-lost';

    this.onOwnershipGainedEvent = {
      el: this.el
    };
    this.onOwnershipChangedEvent = {
      el: this.el
    };
    this.onOwnershipLostEvent = {
      el: this.el
    };

    this.conversionEuler = new THREE.Euler();
    this.conversionEuler.order = "YXZ";
    this.bufferInfos = [];
    this.bufferPosition = new THREE.Vector3();
    this.bufferQuaternion = new THREE.Quaternion();
    this.bufferScale = new THREE.Vector3();

    var wasCreatedByNetwork = this.wasCreatedByNetwork();

    this.onConnected = this.onConnected.bind(this);

    this.syncData = {};
    this.componentSchemas =  NAF.schemas.getComponents(this.data.template);
    this.cachedElements = new Array(this.componentSchemas.length);
    this.networkUpdatePredicates = this.componentSchemas.map(x => (x.requiresNetworkUpdate && x.requiresNetworkUpdate()) || defaultRequiresUpdate());

    // Fill cachedElements array with null elements
    this.invalidateCachedElements();

    this.initNetworkParent();

    if (this.data.networkId === '') {
      this.el.setAttribute(this.name, {networkId: NAF.utils.createNetworkId()});
    }

    if (wasCreatedByNetwork) {
      this.firstUpdate();
    } else {
      if (this.data.attachTemplateToLocal) {
        this.attachTemplateToLocal();
      }

      this.registerEntity(this.data.networkId);
    }

    this.lastOwnerTime = -1;

    if (NAF.clientId) {
      this.onConnected();
    } else {
      document.body.addEventListener('connected', this.onConnected, false);
    }

    document.body.dispatchEvent(this.entityCreatedEvent());
    this.el.dispatchEvent(new CustomEvent('instantiated', {detail: {el: this.el}}));
    this.el.sceneEl.systems.networked.register(this);
  },

  attachTemplateToLocal: function() {
    const template = NAF.schemas.getCachedTemplate(this.data.template);
    const elAttrs = template.attributes;

    // Merge root element attributes with this entity
    for (let attrIdx = 0; attrIdx < elAttrs.length; attrIdx++) {
      this.el.setAttribute(elAttrs[attrIdx].name, elAttrs[attrIdx].value);
    }

    // Append all child elements
    while (template.firstElementChild) {
      this.el.appendChild(template.firstElementChild);
    }
  },

  takeOwnership: function() {
    const owner = this.data.owner;
    const lastOwnerTime = this.lastOwnerTime;
    const now = NAF.connection.getServerTime();
    if (owner && !this.isMine() && lastOwnerTime < now) {
      this.lastOwnerTime = now;
      this.removeLerp();
      this.el.setAttribute('networked', { owner: NAF.clientId });
      this.syncAll();

      this.onOwnershipGainedEvent.oldOwner = owner;
      this.el.emit(this.OWNERSHIP_GAINED, this.onOwnershipGainedEvent);

      this.onOwnershipChangedEvent.oldOwner = owner;
      this.onOwnershipChangedEvent.newOwner = NAF.clientId;
      this.el.emit(this.OWNERSHIP_CHANGED, this.onOwnershipChangedEvent);

      return true;
    }
    return false;
  },

  wasCreatedByNetwork: function() {
    return !!this.el.firstUpdateData;
  },

  initNetworkParent: function() {
    var parentEl = this.el.parentElement;
    if (parentEl['components'] && parentEl.components['networked']) {
      this.parent = parentEl;
    } else {
      this.parent = null;
    }
  },

  registerEntity: function(networkId) {
    NAF.entities.registerEntity(networkId, this.el);
  },

  applyPersistentFirstSync: function() {
    const { networkId } = this.data;
    const persistentFirstSync = NAF.entities.getPersistentFirstSync(networkId);
    if (persistentFirstSync) {
      this.networkUpdate(persistentFirstSync);
      NAF.entities.forgetPersistentFirstSync(networkId);
    }
  },

  firstUpdate: function() {
    var entityData = this.el.firstUpdateData;
    this.networkUpdate(entityData);
  },

  onConnected: function() {
    if (this.data.owner === '') {
      this.lastOwnerTime = NAF.connection.getServerTime();
      this.el.setAttribute(this.name, { owner: NAF.clientId, creator: NAF.clientId });
      setTimeout(() => {
        //a-primitives attach their components on the next frame; wait for components to be attached before calling syncAll
        if (!this.el.parentNode){
          NAF.log.warn("Networked element was removed before ever getting the chance to syncAll");
          return;
        }
        this.syncAll(undefined, true);
      }, 0);
    }

    document.body.removeEventListener('connected', this.onConnected, false);
  },

  isMine: function() {
    return this.data.owner === NAF.clientId;
  },

  createdByMe: function() {
    return this.data.creator === NAF.clientId;
  },

  tick: function(time, dt) {
    if (!this.isMine() && NAF.options.useLerp) {
      for (var i = 0; i < this.bufferInfos.length; i++) {
        var bufferInfo = this.bufferInfos[i];
        var buffer = bufferInfo.buffer;
        var object3D = bufferInfo.object3D;
        var componentNames = bufferInfo.componentNames;
        buffer.update(dt);
        if (componentNames.includes('position')) {
          object3D.position.copy(buffer.getPosition());
        }
        if (componentNames.includes('rotation')) {
          object3D.quaternion.copy(buffer.getQuaternion());
        }
        if (componentNames.includes('scale')) {
          object3D.scale.copy(buffer.getScale());
        }
      }
    }
  },

  /* Sending updates */

  syncAll: function(targetClientId, isFirstSync) {
    if (!this.canSync()) {
      return;
    }

    var components = this.gatherComponentsData(true);

    var syncData = this.createSyncData(components, isFirstSync);

    if (targetClientId) {
      NAF.connection.sendDataGuaranteed(targetClientId, 'u', syncData);
    } else {
      NAF.connection.broadcastDataGuaranteed('u', syncData);
    }
  },

  syncDirty: function() {
    if (!this.canSync()) {
      return;
    }

    var components = this.gatherComponentsData(false);

    if (components === null) {
      return;
    }

    return this.createSyncData(components);
  },

  getCachedElement(componentSchemaIndex) {
    var cachedElement = this.cachedElements[componentSchemaIndex];

    if (cachedElement) {
      return cachedElement;
    }

    var componentSchema = this.componentSchemas[componentSchemaIndex];

    if (componentSchema.selector) {
      return this.cachedElements[componentSchemaIndex] = this.el.querySelector(componentSchema.selector);
    } else {
      return this.cachedElements[componentSchemaIndex] = this.el;
    }
  },

  invalidateCachedElements() {
    for (var i = 0; i < this.cachedElements.length; i++) {
      this.cachedElements[i] = null;
    }
  },

  gatherComponentsData: function(fullSync) {
    var componentsData = null;

    for (var i = 0; i < this.componentSchemas.length; i++) {
      var componentSchema = this.componentSchemas[i];
      var componentElement = this.getCachedElement(i);

      if (!componentElement) {
        if (fullSync) {
          componentsData = componentsData || {};
          componentsData[i] = null;
        }
        continue;
      }

      var componentName = componentSchema.component ? componentSchema.component : componentSchema;
      var componentData = componentElement.getAttribute(componentName);

      if (componentData === null) {
        if (fullSync) {
          componentsData = componentsData || {};
          componentsData[i] = null;
        }
        continue;
      }

      var syncedComponentData = componentSchema.property ? componentData[componentSchema.property] : componentData;

      // Use networkUpdatePredicate to check if the component needs to be updated.
      // Call networkUpdatePredicate first so that it can update any cached values in the event of a fullSync.
      if (this.networkUpdatePredicates[i](syncedComponentData) || fullSync) {
        componentsData = componentsData || {};
        componentsData[i] = syncedComponentData;
      }
    }

    return componentsData;
  },

  createSyncData: function(components, isFirstSync) {
    var { syncData, data } = this;
    syncData.networkId = data.networkId;
    syncData.owner = data.owner;
    syncData.creator = data.creator;
    syncData.lastOwnerTime = this.lastOwnerTime;
    syncData.template = data.template;
    syncData.persistent = data.persistent;
    syncData.parent = this.getParentId();
    syncData.components = components;
    syncData.isFirstSync = !!isFirstSync;
    return syncData;
  },

  canSync: function() {
    // This client will send a sync if:
    //
    // - The client is the owner
    // - The client is the creator, and the owner is not in the room.
    //
    // The reason for the latter case is so the object will still be
    // properly instantiated if the owner leaves. (Since the object lifetime
    // is tied to the creator.)
    if (this.data.owner && this.isMine()) return true;
    if (!this.createdByMe()) return false;

    const clients = NAF.connection.getConnectedClients();

    for (let clientId in clients) {
      if (clientId === this.data.owner) return false;
    }

    return true;
  },

  getParentId: function() {
    this.initNetworkParent(); // TODO fix calling this each network tick
    if (!this.parent) {
      return null;
    }
    var netComp = this.parent.getAttribute('networked');
    return netComp.networkId;
  },

  /* Receiving updates */

  networkUpdate: function(entityData) {
    // Avoid updating components if the entity data received did not come from the current owner.
    if (entityData.lastOwnerTime < this.lastOwnerTime ||
          (this.lastOwnerTime === entityData.lastOwnerTime && this.data.owner > entityData.owner)) {
      return;
    }

    if (this.data === undefined) {
      return;
    }

    if (this.data.owner !== entityData.owner) {
      var wasMine = this.isMine();
      this.lastOwnerTime = entityData.lastOwnerTime;

      const oldOwner = this.data.owner;
      const newOwner = entityData.owner;

      this.el.setAttribute('networked', { owner: entityData.owner });

      if (wasMine) {
        this.onOwnershipLostEvent.newOwner = newOwner;
        this.el.emit(this.OWNERSHIP_LOST, this.onOwnershipLostEvent);
      }
      this.onOwnershipChangedEvent.oldOwner = oldOwner;
      this.onOwnershipChangedEvent.newOwner = newOwner;
      this.el.emit(this.OWNERSHIP_CHANGED, this.onOwnershipChangedEvent);
    }
    if (this.data.persistent !== entityData.persistent) {
      this.el.setAttribute('networked', { persistent: entityData.persistent });
    }
    this.updateNetworkedComponents(entityData.components);
  },

  updateNetworkedComponents: function(components) {
    for (var componentIndex = 0, l = this.componentSchemas.length; componentIndex < l; componentIndex++) {
      var componentData = components[componentIndex];
      var componentSchema = this.componentSchemas[componentIndex];
      var componentElement = this.getCachedElement(componentIndex);

      if (componentElement === null || componentData === null || componentData === undefined ) {
        continue;
      }

      if (componentSchema.component) {
        if (componentSchema.property) {
          this.updateNetworkedComponent(componentElement, componentSchema.component, componentSchema.property, componentData);
        } else {
          this.updateNetworkedComponent(componentElement, componentSchema.component, componentData);
        }
      } else {
        this.updateNetworkedComponent(componentElement, componentSchema, componentData);
      }
    }
  },

  updateNetworkedComponent: function (el, componentName, data, value) {
    if(!NAF.options.useLerp || !OBJECT3D_COMPONENTS.includes(componentName)) {
      if (value === undefined) {
        el.setAttribute(componentName, data);
      } else {
        el.setAttribute(componentName, data, value);
      }
      return;
    }

    let bufferInfo;

    for (let i = 0, l = this.bufferInfos.length; i < l; i++) {
      const info = this.bufferInfos[i];

      if (info.object3D === el.object3D) {
        bufferInfo = info;
        break;
      }
    }

    if (!bufferInfo) {
      bufferInfo = { buffer: new InterpolationBuffer(InterpolationBuffer.MODE_LERP, 0.1),
                     object3D: el.object3D,
                     componentNames: [componentName] };
      this.bufferInfos.push(bufferInfo);
    } else {
      var componentNames = bufferInfo.componentNames;
      if (!componentNames.includes(componentName)) {
        componentNames.push(componentName);
      }
    }
    var buffer = bufferInfo.buffer;

    switch(componentName) {
      case 'position':
        buffer.setPosition(this.bufferPosition.set(data.x, data.y, data.z));
        return;
      case 'rotation':
        this.conversionEuler.set(DEG2RAD * data.x, DEG2RAD * data.y, DEG2RAD * data.z);
        buffer.setQuaternion(this.bufferQuaternion.setFromEuler(this.conversionEuler));
        return;
      case 'scale':
        buffer.setScale(this.bufferScale.set(data.x, data.y, data.z));
        return;
    }
    NAF.log.error('Could not set value in interpolation buffer.', el, componentName, data, bufferInfo);
  },

  removeLerp: function() {
    this.bufferInfos = [];
  },

  remove: function () {
    if (this.isMine() && NAF.connection.isConnected()) {
      var syncData = { networkId: this.data.networkId };
      if (NAF.entities.hasEntity(this.data.networkId)) {
        NAF.connection.broadcastDataGuaranteed('r', syncData);
      } else {
        NAF.log.error("Removing networked entity that is not in entities array.");
      }
    }
    NAF.entities.forgetEntity(this.data.networkId);
    document.body.dispatchEvent(this.entityRemovedEvent(this.data.networkId));
    this.el.sceneEl.systems.networked.deregister(this);
  },

  entityCreatedEvent() {
    return new CustomEvent('entityCreated', {detail: {el: this.el}});
  },

  entityRemovedEvent(networkId) {
    return new CustomEvent('entityRemoved', {detail: {networkId: networkId}});
  }
});
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { Field, reduxForm} from 'redux-form';

class PostsNew extends Component {
  renderField(field) {
    return (

        {field.label}
        <input
          className="form-control"
          type="text"
          {...field.input}
        />

    )
  }

  render() {
    return (
      <form>
        <Field
          label="Title"
          name="title"
          component={this.renderField}
        />
        <Field
          label="Tags"
          name="tags"
          component={this.renderField}
        />
        <Field
          label="Posts Content"
          name="content"
          component={this.renderField}
        />
      </form>
    )
  }
}

export default reduxForm({
  form: 'PostsNewForm'
})(PostsNew);<commit_msg>Added form validation<commit_after>import React, { Component } from 'react';
import { Field, reduxForm} from 'redux-form';

class PostsNew extends Component {
  renderField(field) {
    return (

        {field.label}
        <input
          className="form-control"
          type="text"
          {...field.input}
        />

    )
  }

  render() {
    return (
      <form>
        <Field
          label="Title"
          name="title"
          component={this.renderField}
        />
        <Field
          label="Categories"
          name="categories"
          component={this.renderField}
        />
        <Field
          label="Posts Content"
          name="content"
          component={this.renderField}
        />
      </form>
    )
  }
}

function validate(values) {
  const errors = {};

  if(!values.title) {
    errors.title = "Enter a title";
  }
  if(!values.categories) {
    errors.categories = "Enter some  categories";
  }
  if(!values.content) {
    errors.content = "Enter some content";
  }

  // errors empty = validation ok
  return errors;
}

export default reduxForm({
  validate,
  form: 'PostsNewForm'
})(PostsNew);<|endoftext|>


<commit_before>import Bootable from '../../mixins/bootable'

export default {
  name: 'tabs',

  mixins: [Bootable],

  data () {
    return {
      activators: [],
      activeIndex: null,
      isMobile: false,
      reverse: false,
      target: null,
      resizeDebounce: {},
      targetEl: null
    }
  },

  props: {
    centered: Boolean,
    grow: Boolean,
    icons: Boolean,
    mobileBreakPoint: {
      type: [Number, String],
      default: 1024
    },
    scrollBars: Boolean,
    value: String
  },

  computed: {
    classes () {
      return {
        'tabs': true,
        'tabs--centered': this.centered,
        'tabs--grow': this.grow,
        'tabs--icons': this.icons,
        'tabs--scroll-bars': this.scrollBars
      }
    }
  },

  watch: {
    value () {
      this.tabClick(this.value)
    },
    activeIndex () {
      this.activators.forEach(i => {
        i.toggle(this.target)

        if (i.isActive) {
          this.slider(i.$el)
        }
      })

      this.$refs.content.$children.forEach(i => i.toggle(this.target, this.reverse, this.isBooted))
      this.$emit('input', this.target)
      this.isBooted = true
    }
  },

  mounted () {
    this.$vuetify.load(() => {
      this.activators = this.$refs.activators.$children.filter(i => i.$options._componentTag === 'v-tab-item')
      const tab = this.value || (this.activators[0] || {}).target

      tab && this.tabClick(tab) && this.resize()
      window.addEventListener('resize', this.resize, false)
    })
  },

  beforeDestroy () {
    window.removeEventListener('resize', this.resize, false)
  },

  methods: {
    resize () {
      clearTimeout(this.resizeDebounce)

      this.resizeDebounce = setTimeout(() => {
        this.slider()
        this.isMobile = window.innerWidth < this.mobileBreakPoint
      }, 0)
    },
    slider (el) {
      this.targetEl = el || this.targetEl
      this.$refs.slider.style.width = `${this.targetEl.clientWidth}px`
      this.$refs.slider.style.left = `${this.targetEl.offsetLeft}px`
    },
    tabClick (target) {
      this.target = target

      if (!this.$refs.content) {
        this.activeIndex = target
        return
      }

      this.$nextTick(() => {
        const nextIndex = this.$refs.content.$children.findIndex(i => i.id === this.target)
        this.reverse = nextIndex < this.activeIndex
        this.activeIndex = nextIndex
      })
    }
  },

  render (h) {
    const tabs = h('v-tabs-tabs', {
      ref: 'activators',
      props: {
        mobile: this.isMobile
      }
    }, [
      h('v-tabs-slider', { ref: 'slider' }),
      this.$slots.activators
    ])

    const items = h('v-tabs-items', {
      'class': 'tabs__items',
      ref: 'content'
    }, [this.$slots.content])

    return h('div', {
      'class': this.classes
    }, [this.$slots.default, tabs, items])
  }
}
<commit_msg>removed redundant class declaration<commit_after>import Bootable from '../../mixins/bootable'

export default {
  name: 'tabs',

  mixins: [Bootable],

  data () {
    return {
      activators: [],
      activeIndex: null,
      isMobile: false,
      reverse: false,
      target: null,
      resizeDebounce: {},
      targetEl: null
    }
  },

  props: {
    centered: Boolean,
    grow: Boolean,
    icons: Boolean,
    mobileBreakPoint: {
      type: [Number, String],
      default: 1024
    },
    scrollBars: Boolean,
    value: String
  },

  computed: {
    classes () {
      return {
        'tabs': true,
        'tabs--centered': this.centered,
        'tabs--grow': this.grow,
        'tabs--icons': this.icons,
        'tabs--scroll-bars': this.scrollBars
      }
    }
  },

  watch: {
    value () {
      this.tabClick(this.value)
    },
    activeIndex () {
      this.activators.forEach(i => {
        i.toggle(this.target)

        if (i.isActive) {
          this.slider(i.$el)
        }
      })

      this.$refs.content.$children.forEach(i => i.toggle(this.target, this.reverse, this.isBooted))
      this.$emit('input', this.target)
      this.isBooted = true
    }
  },

  mounted () {
    this.$vuetify.load(() => {
      this.activators = this.$refs.activators.$children.filter(i => i.$options._componentTag === 'v-tab-item')
      const tab = this.value || (this.activators[0] || {}).target

      tab && this.tabClick(tab) && this.resize()
      window.addEventListener('resize', this.resize, false)
    })
  },

  beforeDestroy () {
    window.removeEventListener('resize', this.resize, false)
  },

  methods: {
    resize () {
      clearTimeout(this.resizeDebounce)

      this.resizeDebounce = setTimeout(() => {
        this.slider()
        this.isMobile = window.innerWidth < this.mobileBreakPoint
      }, 0)
    },
    slider (el) {
      this.targetEl = el || this.targetEl
      this.$refs.slider.style.width = `${this.targetEl.clientWidth}px`
      this.$refs.slider.style.left = `${this.targetEl.offsetLeft}px`
    },
    tabClick (target) {
      this.target = target

      if (!this.$refs.content) {
        this.activeIndex = target
        return
      }

      this.$nextTick(() => {
        const nextIndex = this.$refs.content.$children.findIndex(i => i.id === this.target)
        this.reverse = nextIndex < this.activeIndex
        this.activeIndex = nextIndex
      })
    }
  },

  render (h) {
    const tabs = h('v-tabs-tabs', {
      ref: 'activators',
      props: {
        mobile: this.isMobile
      }
    }, [
      h('v-tabs-slider', { ref: 'slider' }),
      this.$slots.activators
    ])

    const items = h('v-tabs-items', {
      ref: 'content'
    }, [this.$slots.content])

    return h('div', {
      'class': this.classes
    }, [this.$slots.default, tabs, items])
  }
}
<|endoftext|>


<commit_before>'use strict';

Crafty.c('TiledMap', {
  init: function () {
    // Defines a default object builder
    this.setObjectBuilderFor('$default', function (object, layer) {
      var objectEntity =
        Crafty.e('2D, Canvas, Collision, Grid ' + object.type)
        .attr({
          x: object.x,
          y: object.y,
          w: object.width,
          h: object.height,
          z: layer.z
        });

      if ('polyline' in object) {
        var polygon =
          new Crafty.polygon(object.polyline.map(function (point) {
            return [point.x, point.y];
          }));

        objectEntity.collision(polygon);
      } else {
        objectEntity.collision();
      }
    });

    return this;
  },

  setObjectBuilderFor: function (objectType, builder) {
    this._objectBuilders = (this._objectBuilders || {});
    this._objectBuilders[objectType] = builder;

    return this;
  },

  setTiledMap: function (tiledMap) {
    this.tiledMap = tiledMap;

    var z = 0;
    this.visibleLayers = this.tiledMap.layers.reduce(function (grouped, layer, i) {
      if ('visible' in layer ? layer.visible : true) {
        // Define layer z value (this value will be add to each entity on layer)
        layer.z = z++;
        grouped[layer.type] = (grouped[layer.type] || []);
        grouped[layer.type].push(layer);
      }

      return grouped;
    }, {});

    // This will create sprites (which will create tile components)
    tiledMap.tilesets.forEach(this.createSpriteFromTileset.bind(this));

    // Apply images
    (this.visibleLayers.imagelayer || []).forEach(this.createImageFromLayer.bind(this));

    // Apply objects
    (this.visibleLayers.objectgroup || []).forEach(this.createObjectsOfLayer.bind(this));

    return this;
  },

  createImageFromLayer: function (layer) {
    Crafty.e('2D, Canvas, Grid, Image')
    .forLevel(this.tiledMap)
    .at({x: layer.x, y: layer.y})
    .image(layer.image);
  },

  createObjectsOfLayer: function (layer) {
    if (!('objects' in layer) || layer.type !== 'objectgroup')
      throw new Error('You must provide a layer of objects');

    for (var i = 0; i < layer.objects.length; i++) {
      var object = layer.objects[i];

      object.type = (object.type || 'ObjectCollision');

      var builder = (this._objectBuilders[object.type] ||
                     this._objectBuilders.$default);

      builder(object, layer);
    }

    return this;
  },

  createSpriteFromTileset: function (tileset) {
    return Crafty.sprite(
      tileset.tilewidth,
      tileset.tileheight,
      tileset.image,
      this.tilesetToSpriteMap(tileset),
      tileset.spacing,
      tileset.spacing
    );
  },

  tilesetToSpriteMap: function (tileset) {
    var columns = Math.round(
      tileset.imagewidth / (tileset.tilewidth + tileset.margin)
    );
    var rows = Math.round(
      tileset.imageheight / (tileset.tileheight + tileset.margin)
    );
    var tilesMap = {};

    for (var row = 0; row < rows; row++) {
      for (var column = 0; column < columns; column++) {
        // Tiled Map Editor exports tiled maps with many tilesets images but
        // gives an unique gid for each tile. We need to create an component
        // for each tile in order to reproduce the map.
        var tileNumber =
          ((parseInt(tileset.firstgid, 10) + column) + (columns * row));

        tilesMap['Tile' + tileNumber] = [column, row];
      }
    }

    return tilesMap;
  },

  getDataAtTile: function (x, y) {
    this.visibleLayers.tilelayer.map(function (layer) {
      return {gid: layer.data[x + y * this.tiledMap.width], z: layer.z};
    });
  },

  cameraFollow: function () {
    var args = Array.prototype.slice.call(arguments);
    var entity = args[0];
    var self = this;

    self.determineCameraSegments();

    entity.bind('Move', function () {
      self.cameraSegment.moveCamera(this.x, this.y);
    });

    Crafty.viewport.follow.apply(Crafty.viewport, args);
  },

  // Divide the camera into seagments to determine when to load/unload tiles
  determineCameraSegments: function () {
    var tiledMapEntity = this;

    var tileWidthInPx   = this.tiledMap.tilewidth;
    var tileHeightInPx  = this.tiledMap.tileheight;
    var mapWidthInTiles = this.tiledMap.width;
    var mapHeightInTiles = this.tiledMap.height;

    var viewportWidthInTiles  = Math.ceil(Crafty.viewport.width / tileWidthInPx);
    var viewportHeightInTiles = Math.ceil(Crafty.viewport.height / tileHeightInPx);

    var segmentsOnX = (this.tiledMap.properties.segmentsOnX || 3);
    var segmentsOnY = (this.tiledMap.properties.segmentsOnY || 3);

    var segmentWidthInTiles  = Math.ceil(viewportWidthInTiles / segmentsOnX);
    var segmentHeightInTiles = Math.ceil(viewportHeightInTiles / segmentsOnY);

    this.cameraSegment = {
      tilesCache: {},
      segmentsCache: {},

      mapWidthInTiles: mapWidthInTiles,
      mapHeightInTiles: mapHeightInTiles,

      segmentsOnX: segmentsOnX,
      segmentsOnY: segmentsOnY,

      segmentWidthInTiles: segmentWidthInTiles,
      segmentHeightInTiles: segmentHeightInTiles,

      segmentsPerRow: Math.ceil(mapWidthInTiles / segmentWidthInTiles),

      currentSegmentLinearPosition: -1,

      getSegmentLinearPositionAt: function (x, y) {
        var column = Math.floor(x / segmentWidthInTiles * tileWidthInPx);
        var row = Math.floor(y / segmentHeightInTiles * tileHeightInPx);

        return column + row * this.segmentsPerRow;
      },

      clearSegment: function (position) {
        if (position < 0)
          return;

        if (!this.segmentsCache[position] ||
            !this.segmentsCache[position].loaded)
          return;

        this.segmentsCache[position].loaded = false;

        setTimeout(function () {
          while (this.segmentsCache[position].tiles.length) {
            var tile = this.segmentsCache[position].tiles.pop();

            tile.visible = false;
            tile.attr({ x: -10000, y: -10000 });

            this.tilesCache[tile.gid].push(tile);
          }
        }.bind(this), 10);
      },

      loadSegment: function (position) {
        if (position < 0)
          return;

        if (this.segmentsCache[position] &&
            this.segmentsCache[position].loaded)
          return;

        if (!this.segmentsCache[position])
          this.segmentsCache[position] = {loaded: true, tiles: []};

        setTimeout(function () {
          var tileX =
            (this.currentSegmentLinearPosition % this.segmentsPerRow) *
            this.segmentWidthInTiles;

          var tileY =
            Math.ceil(this.currentSegmentLinearPosition / this.segmentsPerRow) *
            this.segmentHeightInTiles;

          var maxSegmentX = this.segmentWidthInTiles;
          var maxSegmentY = this.segmentHeightInTiles;
          var maxX = this.mapWidthInTiles;
          var maxY = this.mapHeightInTiles;

          var activateTile = function (tileData) {
            var gid = tileData.gid;

            if (!this.tilesCache[gid])
              this.tilesCache[gid] = [];

            var tile;
            if (this.tilesCache[gid].length) {
              tile = this.tilesCache[gid].pop();
              tile.visible = true;
            } else {
              tile = Crafty.e('Tile, Tile' + gid).setGid(gid);
            }
            tile.z = tileData.z;

            return tile;
          }.bind(this);

          for (var y = tileY; y < (tileY + maxSegmentY) && y < maxY && y >= 0; y++) {
            for (var x = tileX; x < (tileX + maxSegmentX) && x < maxX && x >= 0; x++) {
              var tiles = tiledMapEntity.getTilesGid(x, y).map(activateTile);

              for (var i = 0; i < tiles.length; i++) {
                tiles[i].attr({
                  x: x * tileWidthInPx,
                  y: y * tileHeightInPx
                });

                this.segmentsCache[position].tiles.push(tiles[i]);
              }
            }
          }
        }.bind(this), 10);
      },

      clearFarthestSegments: function () {
        var farOffsetY = Math.ceil(this.segmentsOnY / 2) + 1;
        var farOffsetX = Math.ceil(this.segmentsOnX / 2) + 1;

        // clear the row above and below
        for (var x = -farOffsetX; x <= farOffsetX; x++) {
          this.clearSegment(
            this.currentSegmentLinearPosition   +
            (-farOffsetY * this.segmentsPerRow) +
            x
          );

          this.clearSegment(
            this.currentSegmentLinearPosition  +
            (farOffsetY * this.segmentsPerRow) +
            x
          );
        }

        // clear the column behind and ahead
        for (var y = -(farOffsetY - 1); y <= (farOffsetY - 1); y++) {
          this.clearSegment(
            this.currentSegmentLinearPosition +
            (y * this.segmentsPerRow)         +
            farOffsetX
          );

          this.clearSegment(
            this.currentSegmentLinearPosition +
            (y * this.segmentsPerRow)         +
            -farOffsetX
          );
        }
      },

      loadNearestSegments: function () {
        var nearOffsetY = Math.ceil(this.segmentsOnY / 2);
        var nearOffsetX = Math.ceil(this.segmentsOnX / 2);

        for (var y = -nearOffsetY; y <= nearOffsetY; y++)
          for (var x = -nearOffsetX; x <= nearOffsetX; x++)
            this.loadSegment(
              this.currentSegmentLinearPosition +
              y * this.segmentsPerRow +
              x
            );
      }
    };

    return this;
  },

  moveCamera: function (x, y) {
    var newPosition = this.cameraSegment.getSegmentLinearPositionAt(x, y);

    if (this.currentSegmentLinearPosition !== newPosition) {
      this.currentSegmentLinearPosition = newPosition;

      setTimeout(this.cameraSegment.clearFarthestSegments.bind(this.cameraSegment), 0);
      setTimeout(this.cameraSegment.loadNearestSegments.bind(this.cameraSegment), 0);
    }
  }
});
<commit_msg>Fixing image positioning<commit_after>'use strict';

Crafty.c('TiledMap', {
  init: function () {
    // Defines a default object builder
    this.setObjectBuilderFor('$default', function (object, layer) {
      var objectEntity =
        Crafty.e('2D, Canvas, Collision, Grid ' + object.type)
        .attr({
          x: object.x,
          y: object.y,
          w: object.width,
          h: object.height,
          z: layer.z
        });

      if ('polyline' in object) {
        var polygon =
          new Crafty.polygon(object.polyline.map(function (point) {
            return [point.x, point.y];
          }));

        objectEntity.collision(polygon);
      } else {
        objectEntity.collision();
      }
    });

    return this;
  },

  setObjectBuilderFor: function (objectType, builder) {
    this._objectBuilders = (this._objectBuilders || {});
    this._objectBuilders[objectType] = builder;

    return this;
  },

  setTiledMap: function (tiledMap) {
    this.tiledMap = tiledMap;

    var z = 0;
    this.visibleLayers = this.tiledMap.layers.reduce(function (grouped, layer, i) {
      if ('visible' in layer ? layer.visible : true) {
        // Define layer z value (this value will be add to each entity on layer)
        layer.z = z++;
        grouped[layer.type] = (grouped[layer.type] || []);
        grouped[layer.type].push(layer);
      }

      return grouped;
    }, {});

    // This will create sprites (which will create tile components)
    tiledMap.tilesets.forEach(this.createSpriteFromTileset.bind(this));

    // Apply images
    (this.visibleLayers.imagelayer || []).forEach(this.createImageFromLayer.bind(this));

    // Apply objects
    (this.visibleLayers.objectgroup || []).forEach(this.createObjectsOfLayer.bind(this));

    return this;
  },

  createImageFromLayer: function (layer) {
    Crafty.e('2D, Canvas, Grid, Image')
    .forLevel(this.tiledMap)
    .at(layer.x, layer.y)
    .image(layer.image);
  },

  createObjectsOfLayer: function (layer) {
    if (!('objects' in layer) || layer.type !== 'objectgroup')
      throw new Error('You must provide a layer of objects');

    for (var i = 0; i < layer.objects.length; i++) {
      var object = layer.objects[i];

      object.type = (object.type || 'ObjectCollision');

      var builder = (this._objectBuilders[object.type] ||
                     this._objectBuilders.$default);

      builder(object, layer);
    }

    return this;
  },

  createSpriteFromTileset: function (tileset) {
    return Crafty.sprite(
      tileset.tilewidth,
      tileset.tileheight,
      tileset.image,
      this.tilesetToSpriteMap(tileset),
      tileset.spacing,
      tileset.spacing
    );
  },

  tilesetToSpriteMap: function (tileset) {
    var columns = Math.round(
      tileset.imagewidth / (tileset.tilewidth + tileset.margin)
    );
    var rows = Math.round(
      tileset.imageheight / (tileset.tileheight + tileset.margin)
    );
    var tilesMap = {};

    for (var row = 0; row < rows; row++) {
      for (var column = 0; column < columns; column++) {
        // Tiled Map Editor exports tiled maps with many tilesets images but
        // gives an unique gid for each tile. We need to create an component
        // for each tile in order to reproduce the map.
        var tileNumber =
          ((parseInt(tileset.firstgid, 10) + column) + (columns * row));

        tilesMap['Tile' + tileNumber] = [column, row];
      }
    }

    return tilesMap;
  },

  getDataAtTile: function (x, y) {
    this.visibleLayers.tilelayer.map(function (layer) {
      return {gid: layer.data[x + y * this.tiledMap.width], z: layer.z};
    });
  },

  cameraFollow: function () {
    var args = Array.prototype.slice.call(arguments);
    var entity = args[0];
    var self = this;

    self.determineCameraSegments();

    entity.bind('Move', function () {
      self.cameraSegment.moveCamera(this.x, this.y);
    });

    Crafty.viewport.follow.apply(Crafty.viewport, args);
  },

  // Divide the camera into seagments to determine when to load/unload tiles
  determineCameraSegments: function () {
    var tiledMapEntity = this;

    var tileWidthInPx   = this.tiledMap.tilewidth;
    var tileHeightInPx  = this.tiledMap.tileheight;
    var mapWidthInTiles = this.tiledMap.width;
    var mapHeightInTiles = this.tiledMap.height;

    var viewportWidthInTiles  = Math.ceil(Crafty.viewport.width / tileWidthInPx);
    var viewportHeightInTiles = Math.ceil(Crafty.viewport.height / tileHeightInPx);

    var segmentsOnX = (this.tiledMap.properties.segmentsOnX || 3);
    var segmentsOnY = (this.tiledMap.properties.segmentsOnY || 3);

    var segmentWidthInTiles  = Math.ceil(viewportWidthInTiles / segmentsOnX);
    var segmentHeightInTiles = Math.ceil(viewportHeightInTiles / segmentsOnY);

    this.cameraSegment = {
      tilesCache: {},
      segmentsCache: {},

      mapWidthInTiles: mapWidthInTiles,
      mapHeightInTiles: mapHeightInTiles,

      segmentsOnX: segmentsOnX,
      segmentsOnY: segmentsOnY,

      segmentWidthInTiles: segmentWidthInTiles,
      segmentHeightInTiles: segmentHeightInTiles,

      segmentsPerRow: Math.ceil(mapWidthInTiles / segmentWidthInTiles),

      currentSegmentLinearPosition: -1,

      getSegmentLinearPositionAt: function (x, y) {
        var column = Math.floor(x / segmentWidthInTiles * tileWidthInPx);
        var row = Math.floor(y / segmentHeightInTiles * tileHeightInPx);

        return column + row * this.segmentsPerRow;
      },

      clearSegment: function (position) {
        if (position < 0)
          return;

        if (!this.segmentsCache[position] ||
            !this.segmentsCache[position].loaded)
          return;

        this.segmentsCache[position].loaded = false;

        setTimeout(function () {
          while (this.segmentsCache[position].tiles.length) {
            var tile = this.segmentsCache[position].tiles.pop();

            tile.visible = false;
            tile.attr({ x: -10000, y: -10000 });

            this.tilesCache[tile.gid].push(tile);
          }
        }.bind(this), 10);
      },

      loadSegment: function (position) {
        if (position < 0)
          return;

        if (this.segmentsCache[position] &&
            this.segmentsCache[position].loaded)
          return;

        if (!this.segmentsCache[position])
          this.segmentsCache[position] = {loaded: true, tiles: []};

        setTimeout(function () {
          var tileX =
            (this.currentSegmentLinearPosition % this.segmentsPerRow) *
            this.segmentWidthInTiles;

          var tileY =
            Math.ceil(this.currentSegmentLinearPosition / this.segmentsPerRow) *
            this.segmentHeightInTiles;

          var maxSegmentX = this.segmentWidthInTiles;
          var maxSegmentY = this.segmentHeightInTiles;
          var maxX = this.mapWidthInTiles;
          var maxY = this.mapHeightInTiles;

          var activateTile = function (tileData) {
            var gid = tileData.gid;

            if (!this.tilesCache[gid])
              this.tilesCache[gid] = [];

            var tile;
            if (this.tilesCache[gid].length) {
              tile = this.tilesCache[gid].pop();
              tile.visible = true;
            } else {
              tile = Crafty.e('Tile, Tile' + gid).setGid(gid);
            }
            tile.z = tileData.z;

            return tile;
          }.bind(this);

          for (var y = tileY; y < (tileY + maxSegmentY) && y < maxY && y >= 0; y++) {
            for (var x = tileX; x < (tileX + maxSegmentX) && x < maxX && x >= 0; x++) {
              var tiles = tiledMapEntity.getTilesGid(x, y).map(activateTile);

              for (var i = 0; i < tiles.length; i++) {
                tiles[i].attr({
                  x: x * tileWidthInPx,
                  y: y * tileHeightInPx
                });

                this.segmentsCache[position].tiles.push(tiles[i]);
              }
            }
          }
        }.bind(this), 10);
      },

      clearFarthestSegments: function () {
        var farOffsetY = Math.ceil(this.segmentsOnY / 2) + 1;
        var farOffsetX = Math.ceil(this.segmentsOnX / 2) + 1;

        // clear the row above and below
        for (var x = -farOffsetX; x <= farOffsetX; x++) {
          this.clearSegment(
            this.currentSegmentLinearPosition   +
            (-farOffsetY * this.segmentsPerRow) +
            x
          );

          this.clearSegment(
            this.currentSegmentLinearPosition  +
            (farOffsetY * this.segmentsPerRow) +
            x
          );
        }

        // clear the column behind and ahead
        for (var y = -(farOffsetY - 1); y <= (farOffsetY - 1); y++) {
          this.clearSegment(
            this.currentSegmentLinearPosition +
            (y * this.segmentsPerRow)         +
            farOffsetX
          );

          this.clearSegment(
            this.currentSegmentLinearPosition +
            (y * this.segmentsPerRow)         +
            -farOffsetX
          );
        }
      },

      loadNearestSegments: function () {
        var nearOffsetY = Math.ceil(this.segmentsOnY / 2);
        var nearOffsetX = Math.ceil(this.segmentsOnX / 2);

        for (var y = -nearOffsetY; y <= nearOffsetY; y++)
          for (var x = -nearOffsetX; x <= nearOffsetX; x++)
            this.loadSegment(
              this.currentSegmentLinearPosition +
              y * this.segmentsPerRow +
              x
            );
      }
    };

    return this;
  },

  moveCamera: function (x, y) {
    var newPosition = this.cameraSegment.getSegmentLinearPositionAt(x, y);

    if (this.currentSegmentLinearPosition !== newPosition) {
      this.currentSegmentLinearPosition = newPosition;

      setTimeout(this.cameraSegment.clearFarthestSegments.bind(this.cameraSegment), 0);
      setTimeout(this.cameraSegment.loadNearestSegments.bind(this.cameraSegment), 0);
    }
  }
});
<|endoftext|>


<commit_before>import React from 'react';
import {observer} from 'mobx-react';

const ENTER_KEY = 13;

@observer
export default class TodoEntry extends React.Component {
	render() {
		return (<input
			ref="newField"
			className="new-todo"
			placeholder="What needs to be done?"
			onKeyDown={this.handleNewTodoKeyDown}
			autoFocus={true}
		/>);
	}

	handleNewTodoKeyDown = (event) => {
		if (event.keyCode !== ENTER_KEY) {
			return;
		}

		event.preventDefault();

		var val = React.findDOMNode(this.refs.newField).value.trim();

		if (val) {
			this.props.todoModel.addTodo(val);
			React.findDOMNode(this.refs.newField).value = '';
		}
	};
}

TodoEntry.propTypes = {
	todoModel: React.PropTypes.object.isRequired
};
<commit_msg>fix ReactDOM.findDOMNode<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import {observer} from 'mobx-react';

const ENTER_KEY = 13;

@observer
export default class TodoEntry extends React.Component {
	render() {
		return (<input
			ref="newField"
			className="new-todo"
			placeholder="What needs to be done?"
			onKeyDown={this.handleNewTodoKeyDown}
			autoFocus={true}
		/>);
	}

	handleNewTodoKeyDown = (event) => {
		if (event.keyCode !== ENTER_KEY) {
			return;
		}

		event.preventDefault();

		var val = ReactDOM.findDOMNode(this.refs.newField).value.trim();

		if (val) {
			this.props.todoModel.addTodo(val);
			ReactDOM.findDOMNode(this.refs.newField).value = '';
		}
	};
}

TodoEntry.propTypes = {
	todoModel: React.PropTypes.object.isRequired
};
<|endoftext|>


<commit_before>import _ from 'lodash';
import Component from '../_classes/component/Component';
import Components from '../Components';
import NestedComponent from '../_classes/nested/NestedComponent';
import Node from './Node';
import NativePromise from 'native-promise-only';

export default class TreeComponent extends NestedComponent {
  static schema(...extend) {
    return NestedComponent.schema({
      label: 'Tree',
      key: 'tree',
      type: 'tree',
      clearOnHide: true,
      input: true,
      tree: true,
      components: [],
    }, ...extend);
  }

  static get builderInfo() {
    return {
      title: 'Tree',
      icon: 'indent',
      group: 'data',
      weight: 40,
      schema: TreeComponent.schema(),
    };
  }

  constructor(...args) {
    super(...args);
    this.type = 'tree';
  }

  get emptyValue() {
    return {};
  }

  get viewComponents() {
    if (!this.viewComponentsInstantiated) {
      this.viewComponentsInstantiated = true;
      this._viewComponents = this.createComponents({});
    }

    return this._viewComponents;
  }

  init() {
    if (this.builderMode) {
      return super.init();
    }

    this.components = [];
    this.componentOptions = {
      ...this.options,
      parent: this,
      root: this.root || this,
    };
    this.setRoot();
    this.viewComponentsInstantiated = false;
    this._viewComponents = [];
  }

  destroy() {
    super.destroy();

    if (!this.builderMode) {
      this.removeComponents(this._viewComponents);
    }
  }

  createComponents(data, node) {
    const components = this.componentComponents.map(
      (component) => Components.create(component, this.componentOptions, data),
    );

    if (node) {
      this.checkNode(this.data, node);
    }

    return components;
  }

  removeComponents(components) {
    return components.map((component) => component.destroy());
  }

  render() {
    if (this.builderMode) {
      return super.render();
    }

    return super.render(this.renderTree(this.tree));
  }

  renderTree(node = {}, odd = true) {
    const childNodes = (node.hasChildren && !node.collapsed)
      ? this.renderChildNodes(node.children, !odd)
      : [];
    const content = node.changing
      ? this.renderEdit(node)
      : this.renderView(node);

    return this.renderTemplate('tree', {
      odd,
      childNodes,
      content,
      node,
    });
  }

  renderChildNodes(nodes = [], odd) {
    return nodes.map((node) => this.renderTree(node, odd));
  }

  renderEdit(node = {}) {
    return this.renderTemplate('treeEdit', {
      children: this.renderComponents(node.components),
      node,
    });
  }

  renderView(node = {}) {
    return this.renderTemplate('treeView', {
      values: this.viewComponents.map((component) => {
        component.data = node.data;
        return component.getView(component.dataValue);
      }),
      nodeData: node.data,
      node,
    });
  }

  attach(element) {
    if (this.builderMode) {
      return super.attach(element);
    }

    this.loadRefs(element, {
      root: 'single',
    });

    return NativePromise.all([
      super.attach(element),
      this.attachNode(this.refs.root, this.tree),
    ]);
  }

  attachNode(element, node) {
    if (!element) {
      return NativePromise.resolve();
    }

    let componentsPromise = NativePromise.resolve();
    let childrenPromise = NativePromise.resolve();

    node.refs = _.reduce(
      element.children,
      (refs, child) => (
        child.hasAttribute('ref')
          ? {
            ...refs,
            [child.getAttribute('ref')]: child,
          }
          : refs
      ),
      {},
    );

    if (node.refs.content) {
      this.attachActions(node);
      componentsPromise = this.attachComponents(node);
    }

    if (node.refs.childNodes) {
      childrenPromise = this.attachChildren(node);
    }

    return NativePromise.all([
      componentsPromise,
      childrenPromise,
    ]);
  }

  attachActions(node) {
    this.loadRefs.call(node, node.refs.content, {
      addChild: 'single',
      cancelNode: 'single',
      editNode: 'single',
      removeNode: 'single',
      revertNode: 'single',
      saveNode: 'single',
      toggleNode: 'single',
    });

    if (node.refs.addChild) {
      this.addEventListener(node.refs.addChild, 'click', () => {
        this.addChild(node);
      });
    }

    if (node.refs.cancelNode) {
      this.addEventListener(node.refs.cancelNode, 'click', () => {
        this.cancelNode(node);
      });
    }

    if (node.refs.editNode) {
      this.addEventListener(node.refs.editNode, 'click', () => {
        this.editNode(node);
      });
    }

    if (node.refs.removeNode) {
      this.addEventListener(node.refs.removeNode, 'click', () => {
        this.removeNode(node);
      });
    }

    if (node.refs.revertNode) {
      this.addEventListener(node.refs.revertNode, 'click', () => {
        this.revertNode(node);
      });
    }

    if (node.refs.saveNode) {
      this.addEventListener(node.refs.saveNode, 'click', () => {
        this.saveNode(node);
      });
    }

    if (node.refs.toggleNode) {
      this.addEventListener(node.refs.toggleNode, 'click', () => {
        this.toggleNode(node);
      });
    }
  }

  attachComponents(node, ...args) {
    if (this.builderMode) {
      return super.attachComponents.call(this, node, ...args);
    }

    this.loadRefs.call(node, node.refs.content, {
      nodeEdit: 'single',
    });

    return node.refs.nodeEdit
      ? super.attachComponents(node.refs.nodeEdit, node.components)
      : NativePromise.resolve();
  }

  attachChildren(node) {
    const childElements = node.refs.childNodes.children;

    return NativePromise.all(
      _.map(
        childElements,
        (childElement, index) => this.attachNode(childElement, node.children[index]),
      ),
    );
  }

  setValue(value) {
    const changed = this.updateValue(value);
    this.setRoot();
    return changed;
  }

  addChild(parent) {
    if (this.options.readOnly || parent.new) {
      return;
    }

    this.hook('tree.addChild', {
      parent,
      component: this,
    }, () => {
      const child = parent.addChild();
      this.redraw();

      return child;
    });
  }

  cancelNode(node) {
    if (this.options.readOnly) {
      return;
    }

    this.hook('tree.cancelNode', {
      node,
      component: this,
    }, () => {
      if (node.isRoot) {
        this.removeRoot();
      }
      else {
        node.cancel();
        this.redraw();
      }

      return node;
    });
  }

  editNode(node) {
    if (this.options.readOnly || node.new) {
      return;
    }

    this.hook('tree.editNode', {
      node,
      component: this,
    }, () => {
      node.edit();
      this.redraw();

      return node;
    });
  }

  removeNode(node) {
    if (this.options.readOnly || node.new) {
      return;
    }

    this.hook('tree.removeNode', {
      node,
      component: this,
    }, () => {
      if (node.isRoot) {
        this.removeRoot();
      }
      else {
        node.remove();
        this.updateTree();
      }

      return node;
    });
  }

  revertNode(node) {
    if (this.options.readOnly || !node.revertAvailable) {
      return;
    }

    this.hook('tree.revertNode', {
      node,
      component: this,
    }, () => {
      node.revert();
      this.updateTree();

      return node;
    });
  }

  saveNode(node) {
    if (this.options.readOnly) {
      return;
    }

    this.hook('tree.saveNode', {
      node,
      component: this,
    }, () => {
      node.save();
      this.updateTree();

      return node;
    });
  }

  toggleNode(node) {
    this.hook('tree.toggleNode', {
      node,
      component: this,
    }, () => {
      node.collapsed = !node.collapsed;
      this.redraw();

      return node;
    });
  }

  removeRoot() {
    if (this.options.readOnly) {
      return;
    }

    this.dataValue = this.defaultValue;
    this.setRoot();
    this.redraw();
  }

  setRoot() {
    const value = this.dataValue;
    this.tree = new Node(null, value, {
      isNew: !value.data,
      createComponents: this.createComponents.bind(this),
      checkNode: this.checkNode.bind(this, this.data),
      removeComponents: this.removeComponents,
    });
    this.hook('tree.setRoot', {
      root: this.tree,
      component: this,
    });
  }

  getValue() {
    return this.dataValue;
  }

  updateTree() {
    this.updateValue(this.tree.value);
    this.redraw();
  }

  checkData(data, flags = {}) {
    return this.tree.children.reduce((valid, child) => this.checkNode(data, child, flags) && valid, true);
  }

  checkNode(data, node, flags = {}) {
    return super.checkData(data, flags, node.components);
  }
}

TreeComponent.prototype.hasChanged = Component.prototype.hasChanged;
TreeComponent.prototype.updateValue = Component.prototype.updateValue;
<commit_msg>Fixed Tree component validation.<commit_after>import _ from 'lodash';
import Component from '../_classes/component/Component';
import Components from '../Components';
import NestedComponent from '../_classes/nested/NestedComponent';
import Node from './Node';
import NativePromise from 'native-promise-only';

export default class TreeComponent extends NestedComponent {
  static schema(...extend) {
    return NestedComponent.schema({
      label: 'Tree',
      key: 'tree',
      type: 'tree',
      clearOnHide: true,
      input: true,
      tree: true,
      components: [],
    }, ...extend);
  }

  static get builderInfo() {
    return {
      title: 'Tree',
      icon: 'indent',
      group: 'data',
      weight: 40,
      schema: TreeComponent.schema(),
    };
  }

  constructor(...args) {
    super(...args);
    this.type = 'tree';
  }

  get emptyValue() {
    return {};
  }

  get viewComponents() {
    if (!this.viewComponentsInstantiated) {
      this.viewComponentsInstantiated = true;
      this._viewComponents = this.createComponents({});
    }

    return this._viewComponents;
  }

  init() {
    if (this.builderMode) {
      return super.init();
    }

    this.components = [];
    this.componentOptions = {
      ...this.options,
      parent: this,
      root: this.root || this,
    };
    this.setRoot();
    this.viewComponentsInstantiated = false;
    this._viewComponents = [];
  }

  destroy() {
    super.destroy();

    if (!this.builderMode) {
      this.removeComponents(this._viewComponents);
    }
  }

  createComponents(data, node) {
    const components = this.componentComponents.map(
      (component) => Components.create(component, this.componentOptions, data),
    );

    if (node) {
      this.checkNode(this.data, node);
    }

    return components;
  }

  removeComponents(components) {
    return components.map((component) => component.destroy());
  }

  render() {
    if (this.builderMode) {
      return super.render();
    }

    return super.render(this.renderTree(this.tree));
  }

  renderTree(node = {}, odd = true) {
    const childNodes = (node.hasChildren && !node.collapsed)
      ? this.renderChildNodes(node.children, !odd)
      : [];
    const content = node.changing
      ? this.renderEdit(node)
      : this.renderView(node);

    return this.renderTemplate('tree', {
      odd,
      childNodes,
      content,
      node,
    });
  }

  renderChildNodes(nodes = [], odd) {
    return nodes.map((node) => this.renderTree(node, odd));
  }

  renderEdit(node = {}) {
    return this.renderTemplate('treeEdit', {
      children: this.renderComponents(node.components),
      node,
    });
  }

  renderView(node = {}) {
    return this.renderTemplate('treeView', {
      values: this.viewComponents.map((component) => {
        component.data = node.data;
        component.checkComponentConditions(node.data);
        return component.getView(component.dataValue);
      }),
      nodeData: node.data,
      node,
    });
  }

  attach(element) {
    if (this.builderMode) {
      return super.attach(element);
    }

    this.loadRefs(element, {
      root: 'single',
    });

    return NativePromise.all([
      super.attach(element),
      this.attachNode(this.refs.root, this.tree),
    ]);
  }

  attachNode(element, node) {
    if (!element) {
      return NativePromise.resolve();
    }

    let componentsPromise = NativePromise.resolve();
    let childrenPromise = NativePromise.resolve();

    node.refs = _.reduce(
      element.children,
      (refs, child) => (
        child.hasAttribute('ref')
          ? {
            ...refs,
            [child.getAttribute('ref')]: child,
          }
          : refs
      ),
      {},
    );

    if (node.refs.content) {
      this.attachActions(node);
      componentsPromise = this.attachComponents(node);
    }

    if (node.refs.childNodes) {
      childrenPromise = this.attachChildren(node);
    }

    return NativePromise.all([
      componentsPromise,
      childrenPromise,
    ]);
  }

  attachActions(node) {
    this.loadRefs.call(node, node.refs.content, {
      addChild: 'single',
      cancelNode: 'single',
      editNode: 'single',
      removeNode: 'single',
      revertNode: 'single',
      saveNode: 'single',
      toggleNode: 'single',
    });

    if (node.refs.addChild) {
      this.addEventListener(node.refs.addChild, 'click', () => {
        this.addChild(node);
      });
    }

    if (node.refs.cancelNode) {
      this.addEventListener(node.refs.cancelNode, 'click', () => {
        this.cancelNode(node);
      });
    }

    if (node.refs.editNode) {
      this.addEventListener(node.refs.editNode, 'click', () => {
        this.editNode(node);
      });
    }

    if (node.refs.removeNode) {
      this.addEventListener(node.refs.removeNode, 'click', () => {
        this.removeNode(node);
      });
    }

    if (node.refs.revertNode) {
      this.addEventListener(node.refs.revertNode, 'click', () => {
        this.revertNode(node);
      });
    }

    if (node.refs.saveNode) {
      this.addEventListener(node.refs.saveNode, 'click', () => {
        this.saveNode(node);
      });
    }

    if (node.refs.toggleNode) {
      this.addEventListener(node.refs.toggleNode, 'click', () => {
        this.toggleNode(node);
      });
    }
  }

  attachComponents(node, ...args) {
    if (this.builderMode) {
      return super.attachComponents.call(this, node, ...args);
    }

    this.loadRefs.call(node, node.refs.content, {
      nodeEdit: 'single',
    });

    return node.refs.nodeEdit
      ? super.attachComponents(node.refs.nodeEdit, node.components)
      : NativePromise.resolve();
  }

  attachChildren(node) {
    const childElements = node.refs.childNodes.children;

    return NativePromise.all(
      _.map(
        childElements,
        (childElement, index) => this.attachNode(childElement, node.children[index]),
      ),
    );
  }

  setValue(value) {
    const changed = this.updateValue(value);
    this.setRoot();
    return changed;
  }

  addChild(parent) {
    if (this.options.readOnly || parent.new) {
      return;
    }

    this.hook('tree.addChild', {
      parent,
      component: this,
    }, () => {
      const child = parent.addChild();
      this.redraw();

      return child;
    });
  }

  cancelNode(node) {
    if (this.options.readOnly) {
      return;
    }

    this.hook('tree.cancelNode', {
      node,
      component: this,
    }, () => {
      if (node.isRoot) {
        this.removeRoot();
      }
      else {
        node.cancel();
        this.redraw();
      }

      return node;
    });
  }

  editNode(node) {
    if (this.options.readOnly || node.new) {
      return;
    }

    this.hook('tree.editNode', {
      node,
      component: this,
    }, () => {
      node.edit();
      this.redraw();

      return node;
    });
  }

  removeNode(node) {
    if (this.options.readOnly || node.new) {
      return;
    }

    this.hook('tree.removeNode', {
      node,
      component: this,
    }, () => {
      if (node.isRoot) {
        this.removeRoot();
      }
      else {
        node.remove();
        this.updateTree();
      }

      return node;
    });
  }

  revertNode(node) {
    if (this.options.readOnly || !node.revertAvailable) {
      return;
    }

    this.hook('tree.revertNode', {
      node,
      component: this,
    }, () => {
      node.revert();
      this.updateTree();

      return node;
    });
  }

  saveNode(node) {
    if (this.options.readOnly) {
      return;
    }

    this.hook('tree.saveNode', {
      node,
      component: this,
    }, () => {
      node.save();
      this.updateTree();

      return node;
    });
  }

  toggleNode(node) {
    this.hook('tree.toggleNode', {
      node,
      component: this,
    }, () => {
      node.collapsed = !node.collapsed;
      this.redraw();

      return node;
    });
  }

  removeRoot() {
    if (this.options.readOnly) {
      return;
    }

    this.dataValue = this.defaultValue;
    this.setRoot();
    this.redraw();
  }

  setRoot() {
    const value = this.dataValue;
    this.tree = new Node(null, value, {
      isNew: !value.data,
      createComponents: this.createComponents.bind(this),
      checkNode: this.checkNode.bind(this, this.data),
      removeComponents: this.removeComponents,
    });
    this.hook('tree.setRoot', {
      root: this.tree,
      component: this,
    });
  }

  getValue() {
    return this.dataValue;
  }

  updateTree() {
    this.updateValue(this.tree.value);
    this.redraw();
  }

  checkData(data, flags = {}) {
    return this.checkNode(data, this.tree, flags);
  }

  checkNode(data, node, flags = {}) {
    return node.children.reduce(
      (result, child) => this.checkNode(data, child, flags) && result,
      super.checkData(data, flags, node.components),
    );
  }
}

TreeComponent.prototype.hasChanged = Component.prototype.hasChanged;
TreeComponent.prototype.updateValue = Component.prototype.updateValue;
<|endoftext|>