<commit_before>{
        'type': 'Console', // game or console
        'name': 'Dead Space',
        'authors': ['Visceral Games'],
        'company': ['Eletronics Arts '],
        'year': '2008',
        'date': '13-10-2008', // Day, Month, Year
        'headline': 'Jogo mais violento que conseguiu passar pela censura australiana',
        'resume': [
            'Dead Space é um jogo single-player de Survival Horror, ',
            'onde você o engenheiro Isaac Clarke, um homem comum que se ofereceu',
            'para uma missão aparentemente de rotina para corrigir os sistemas de comunicações',
            'a bordo de uma nave de mineração do espaço profundo, a USG Ishimura, ',
            'na qual estava sua namorada Nicole Brennan. ',
            'Ao chegar a nave não demora muito para que Isaac acorde para um pesadelo',
            'quando ele descobre que a tripulação da nave',
            'foi devastada por uma infestação alienígena, os Necromorphs. ',
            'Ele deve então lutar através do silêncio de morte e da escuridão do espaço profundo',
            'para se manter vivo e além de tudo encontrar Nicole.'
        ].join(''),
        'full_text': [
            'Dead Space é um jogo single-player de Survival Horror, ',
            'onde você o engenheiro Isaac Clarke, um homem comum que se ofereceu',
            'para uma missão aparentemente de rotina para corrigir os sistemas de comunicações',
            'a bordo de uma nave de mineração do espaço profundo, a USG Ishimura, ',
            'na qual estava sua namorada Nicole Brennan. ',
            'Ao chegar a nave não demora muito para que Isaac acorde para um pesadelo',
            'quando ele descobre que a tripulação da nave',
            'foi devastada por uma infestação alienígena, os Necromorphs. ',
            'Ele deve então lutar através do silêncio de morte e da escuridão do espaço profundo',
            'para se manter vivo e além de tudo encontrar Nicole.',
            'O jogo apresenta uma mira \'sobre o ombro\' na perspectiva de terceira pessoa',
            'além disso Isaac pode andar, correr, atirar, socar e pisar',
            'A interface não possui um HUD tradicional. Em vez disso,
            'a informação é retransmitida para o jogador via luzes e',
            'telas translúcidas que pairam sobre armas e armaduras de Isaac.',
            'De acordo com a profissão de Isaac como engenheiro em vez de um soldado,',
            'as armas do jogo são na maior parte improvisadas,',
            'que consistem em uma matriz de um alicate, campos de STASIS e
            'armas rudimentares de energia. O Combate no jogo é complicado ',
            'pelo fato de que a maioria dos Necromorphs não podem ser simplesmente mortos com tiros na cabeça.',
            'Em vez disso, eles devem ser desmembrado que é a melhor maneira mata-los. ',
            'Mesmo assim, eles podem adotar novas posturas e táticas, ',
            'e até mesmo crescer novos membros, com base em onde eles foram feridos. ',
            'Vendeu mais de 1 Milhão de cópias no seu mês de lançamento e ',
            'Teve Nota média de 8.7 nas reviews mundiais.'
        ].join(''),
        'thumbnail': 'thumbnail_picture2.png',
        'main_img': {'name': 'main_picture.png', 'caption': "Capa do Game"},
        'images': [
            {'name': 'picture1.png', 'caption': "Isaac Clarke"},
            {'name': 'picture2.png', 'caption': "Kendra Daniels"},
            {'name': 'picture3.png', 'caption': "Zach Hammond"},
            {'name': 'picture4.png', 'caption': "Nicole Brennan"},
            {'name': 'picture5.png', 'caption': "USG Ishimura"},
            {'name': 'picture6.png', 'caption': "Inventário"},
            {'name': 'picture7.png', 'caption': "Área de Gravidade Zero"},
            {'name': 'picture8.png', 'caption': "Demonstrativo de Combate"},
            {'name': 'picture9.png', 'caption': "Warren Ellis"},
        ],
        'video_gameplay': [
            {'url': 'http://www.youtube.com/watch?v=RQ6hgzzk_o8','caption': "Gameplay Completo do Jogo", 'type': "youtube"},
            {'url': 'http://www.youtube.com/watch?v=wHaZrYX0kAU','caption': "Speed Run do Jogo", 'type': "youtube"} // type: youtube or vimeo
        ],
        'demos': [
                {'url': 'http://www.letsplaysnes.com/play-legend-of-zeldaonline-nes/','caption': "Demo On-line", 'type': "Demo"}
        ],
        'references': [
            {'url': 'http://pt.slideshare.net/marcohenrique3954/the-legend-of-zelda-46649789', 'caption': "Introdução aos Jogos Eletrônicos (UEA) - Slides", 'type': 'slides'},
            {'url': 'http://www.zelda.com.br/tloz', 'caption': "Site Oficial do Jogo"},
            {'url': 'http://zeldawiki.org/The_Legend_of_Zelda_%28Game%29', 'caption': "Zelda Wiki"}
        ]
}
<commit_msg>Update DeadSpace_temp.js<commit_after>{
        'type': 'Console', // game or console
        'name': 'Dead Space',
        'authors': ['Visceral Games'],
        'company': ['Eletronics Arts '],
        'year': '2008',
        'date': '13-10-2008', // Day, Month, Year
        'headline': 'Jogo mais violento que conseguiu passar pela censura australiana',
        'resume': [
            'Dead Space é um jogo single-player de Survival Horror, ',
            'onde você o engenheiro Isaac Clarke, um homem comum que se ofereceu',
            'para uma missão aparentemente de rotina para corrigir os sistemas de comunicações',
            'a bordo de uma nave de mineração do espaço profundo, a USG Ishimura, ',
            'na qual estava sua namorada Nicole Brennan. ',
            'Ao chegar a nave não demora muito para que Isaac acorde para um pesadelo',
            'quando ele descobre que a tripulação da nave',
            'foi devastada por uma infestação alienígena, os Necromorphs. ',
            'Ele deve então lutar através do silêncio de morte e da escuridão do espaço profundo',
            'para se manter vivo e além de tudo encontrar Nicole.'
        ].join(''),
        'full_text': [
            'Dead Space é um jogo single-player de Survival Horror, ',
            'onde você o engenheiro Isaac Clarke, um homem comum que se ofereceu',
            'para uma missão aparentemente de rotina para corrigir os sistemas de comunicações',
            'a bordo de uma nave de mineração do espaço profundo, a USG Ishimura, ',
            'na qual estava sua namorada Nicole Brennan. ',
            'Ao chegar a nave não demora muito para que Isaac acorde para um pesadelo',
            'quando ele descobre que a tripulação da nave',
            'foi devastada por uma infestação alienígena, os Necromorphs. ',
            'Ele deve então lutar através do silêncio de morte e da escuridão do espaço profundo',
            'para se manter vivo e além de tudo encontrar Nicole.',
            'O jogo apresenta uma mira \'sobre o ombro\' na perspectiva de terceira pessoa',
            'além disso Isaac pode andar, correr, atirar, socar e pisar',
            'A interface não possui um HUD tradicional. Em vez disso, 1,
            'a informação é retransmitida para o jogador via luzes e',
            'telas translúcidas que pairam sobre armas e armaduras de Isaac.',
            'De acordo com a profissão de Isaac como engenheiro em vez de um soldado,',
            'as armas do jogo são na maior parte improvisadas,',
            'que consistem em uma matriz de um alicate, campos de STASIS e ',
            'armas rudimentares de energia. O Combate no jogo é complicado ',
            'pelo fato de que a maioria dos Necromorphs não podem ser simplesmente mortos com tiros na cabeça.',
            'Em vez disso, eles devem ser desmembrado que é a melhor maneira mata-los. ',
            'Mesmo assim, eles podem adotar novas posturas e táticas, ',
            'e até mesmo crescer novos membros, com base em onde eles foram feridos. ',
            'Vendeu mais de 1 Milhão de cópias no seu mês de lançamento e ',
            'Teve Nota média de 8.7 nas reviews mundiais.'
        ].join(''),
        'thumbnail': 'thumbnail_picture2.png',
        'main_img': {'name': 'main_picture.png', 'caption': "Capa do Game"},
        'images': [
            {'name': 'picture1.png', 'caption': "Isaac Clarke"},
            {'name': 'picture2.png', 'caption': "Kendra Daniels"},
            {'name': 'picture3.png', 'caption': "Zach Hammond"},
            {'name': 'picture4.png', 'caption': "Nicole Brennan"},
            {'name': 'picture5.png', 'caption': "USG Ishimura"},
            {'name': 'picture6.png', 'caption': "Inventário"},
            {'name': 'picture7.png', 'caption': "Área de Gravidade Zero"},
            {'name': 'picture8.png', 'caption': "Demonstrativo de Combate"},
            {'name': 'picture9.png', 'caption': "Warren Ellis"},
        ],
        'video_gameplay': [
            {'url': 'http://www.youtube.com/watch?v=RQ6hgzzk_o8','caption': "Gameplay Completo do Jogo", 'type': "youtube"},
            {'url': 'http://www.youtube.com/watch?v=wHaZrYX0kAU','caption': "Speed Run do Jogo", 'type': "youtube"} // type: youtube or vimeo
        ],
        'demos': [
                {'url': 'http://www.letsplaysnes.com/play-legend-of-zeldaonline-nes/','caption': "Demo On-line", 'type': "Demo"}
        ],
        'references': [
            {'url': 'http://pt.slideshare.net/marcohenrique3954/the-legend-of-zelda-46649789', 'caption': "Introdução aos Jogos Eletrônicos (UEA) - Slides", 'type': 'slides'},
            {'url': 'http://www.zelda.com.br/tloz', 'caption': "Site Oficial do Jogo"},
            {'url': 'http://zeldawiki.org/The_Legend_of_Zelda_%28Game%29', 'caption': "Zelda Wiki"}
        ]
}
<|endoftext|>


<commit_before>import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import autobind from 'autobind-decorator';
import { Link } from 'react-router'
import {Card,CardTitle,CardText} from 'material-ui/Card';
import Divider from 'material-ui/Divider';
import {List, ListItem} from 'material-ui/List';
import {Tabs, Tab} from 'material-ui/Tabs';
import map from '../map';
import Chip from 'material-ui/Chip';
import RaisedButton  from 'material-ui/RaisedButton';

function removeplayer(){

}

class Game extends React.Component {

  constructor(props) {
    super(props);
    this.state = {menuOpen: false, tab: 'game'};
  }
  startgame(){
  }
  @autobind
  tabChange(tab){
    this.setState({
      tab: tab,
    });
  };

  render() {
    return (

        <Card>
          <CardTitle title={this.props.games.game.game + " ("+this.props.games.session+")"}/>
          <Tabs value={this.state.tab}onChange={this.tabChange} >
            <Tab label="Game" value="game">

             {(() => {
                    switch (this.props.games.game.game){
                      case "Mafia":   return "ayy";
                      case "Spyfall": return "lmao";
                      default:      return "Error";
                    }
                  })()}

            </Tab>
            <Tab label="Players" value="players">

                <List>
                  {_.map(this.props.games.game.members, (member, key) => (
                    <ListItem primaryText={member} />
                  ))}
                </List>

            </Tab>
          </Tabs>
        </Card>

    );
  }
}

export default map(Game);
<commit_msg>why this no work<commit_after>import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import autobind from 'autobind-decorator';
import { Link } from 'react-router'
import {Card,CardTitle,CardText} from 'material-ui/Card';
import Divider from 'material-ui/Divider';
import {List, ListItem} from 'material-ui/List';
import {Tabs, Tab} from 'material-ui/Tabs';
import map from '../map';
import Chip from 'material-ui/Chip';
import RaisedButton  from 'material-ui/RaisedButton';

function removeplayer(){

}

class Game extends React.Component {

  constructor(props) {
    super(props);
    this.state = {menuOpen: false, tab: 'game'};

  }
  startgame(){
  }
  @autobind
  tabChange(tab){
    this.setState({
      tab: tab,
    });
  };

  render() {
var number = 0;
    return (

        <Card>
          <CardTitle title={this.props.games.game.game + " ("+this.props.games.session+")"}/>
          <Tabs value={this.state.tab}onChange={this.tabChange} >
            <Tab label="Game" value="game">

              Number of players in current lobby : '{React.Children.count(this.props.games.game.members)}' // <- why this no work

             {(() => {
                    switch (this.props.games.game.game){
                      case "Mafia":   return "ayy";
                      case "Spyfall": return "lmao";

                      default:      return "Error";
                    }
                  })()}

            </Tab>
            <Tab label="Players" value="players">

                <List >

                  {_.map(this.props.games.game.members, (member, key) => (
                    <ListItem primaryText={member} />
                  ))}

                </List>

            </Tab>
          </Tabs>
        </Card>

    );

  }
}

export default map(Game);
<|endoftext|>


<commit_before>;(function ( $, window, document, undefined ) {

  var pluginName = 'bazeValidate';

  /**
   * Plugin's default settings
   * @config {string} classInvalid
   * @config {string} classValid
   * @config {string} classMsg
   * @config {string} msgEmpty
   * @config {string} msgEmail
   * @config {string} msgNumber
   */
  var defaults = {
    classInvalid: 'form-input--error',
    classValid  : 'form-input--success',
    classMsg    : 'form-msg-error',

    msgEmpty    : 'This field is required.',
    msgEmail    : 'Invalid email address.',
    msgNumber   : 'Input must be number.',
    msgExceedMin: 'Minimum number is %s',
    msgExceedMax: 'Maximum number is %s'
  };

  /**
   * Represents the plugin instance
   * @param {DOM Object} element - The DOM Object
   * @param {Object} options - User options
   */
  function Plugin ( element, options ) {
    this.element    = element;
    this.$element   = $(element);
    this.settings   = $.extend( {}, defaults, options );
    this._defaults  = defaults;
    this._name      = pluginName;

    this.init();
  }

  Plugin.prototype.init = function () {
    /**
     * Set novalidate attribute to prevent browser validation
     */
    this.element.setAttribute('novalidate', '');

    /**
     * set aria-required attribute to each required inputs
     */
    this.$element.find('[required]').attr('aria-required', 'true');

    var userOpts = this.settings;

    /**
     * @param {jQuery object} form
     */
    var clearAllMessages = function ( form ) {
      var msgs = form.find('.' + userOpts.classMsg);

      $(msgs).remove();
    };

    /**
     * @param {jQuery object} field
     * @param {string} message
     */
    var addMessage = function ( field, message ) {
      var hasMsg  = field.parent().find('.' + userOpts.classMsg),
          id      = getUID(),
          msg     = $(document.createElement('span'));

      /**
       * Remove existing message
       */
      if ( hasMsg.length ) {
        hasMsg.remove();
      }

      /**
       * Add aria-describedBy and aria-invalid to invalid field
       */
      field.attr({
        'aria-describedBy': id,
        'aria-invalid': 'true'
      });

      /**
       * Place message after input element
       */
      msg
        .addClass( userOpts.classMsg )
        .attr('id', id)
        .text( message )
        .insertAfter( field );
    };

    /**
     * @param {jQuery object} fields
     */
    var resetFields = function ( fields ) {
      fields
        .removeAttr('aria-invalid aria-describedBy')
        .removeClass( userOpts.classInvalid )
        .removeClass( userOpts.classValid );
    };

    /**
     * @param {jQuery object} fields
     * @return {boolean}
     */
    var validateEmpty = function ( fields ) {
      var allIsWell = true;

      fields.each( function () {
        var $field  = $(this),
            value   = $field.val();

        if ( value === '' || value === null || $.trim(value) === '' ) {
          $field.addClass( userOpts.classInvalid );
          addMessage( $field, userOpts.msgEmpty );

          allIsWell = false;
        } else {
          $field.addClass( userOpts.classValid );
        }
      });

      return allIsWell;
    };

    /**
     * @param {jQuery object} fields
     * @return {boolean}
     */
    var validateEmail = function ( fields ) {
      var allIsWell = true;

      for (var i = 0, j = fields.length; i < j; i++) {
        var el    = fields[i],
            $el   = $(el),
            value = el.value,

            /**
             * el.type return text in IE8, so use getAttribute instead
             */
            type  = el.getAttribute('type');

        /**
         * Ignore if input type is not email
         */
        if ( type !== 'email' ) {
          continue;
        }

        if ( !isEmailValid( value ) ) {
          resetFields( $el );
          $el.addClass( userOpts.classInvalid );
          addMessage( $el, userOpts.msgEmail );

          allIsWell = false;
        }
      }

      return allIsWell;
    };

    /**
     * @param {jQuery object} fields
     * @return {boolean}
     */
    var validateNumeric = function ( fields ) {
      var allIsWell = true;

      for (var i = 0, j = fields.length; i < j; i++) {
        var el      = fields[i],
            $el     = $(el),
            value   = el.value,

            /**
             * el.type return text in IE8, so use getAttribute instead
             */
            type    = el.getAttribute('type'),
            min     = el.getAttribute('min') || false,
            max     = el.getAttribute('max') || false,
            nValue  = Math.floor(value),
            nMin    = Math.floor(min),
            nMax    = Math.floor(max);

        /**
         * Ignore if input type is not number
         */
        if ( type !== 'number' ) {
          continue;
        }

        if ( !isNumber( value ) ) {
          resetFields( $el );
          $el.addClass( userOpts.classInvalid );
          addMessage( $el, userOpts.msgNumber );

          allIsWell = false;
        } else {

          if ( !!min && nValue < nMin ) {
            resetFields( $el );
            $el.addClass( userOpts.classInvalid );
            addMessage( $el, vsprintf(userOpts.msgExceedMin, [min]));

            allIsWell = false;
          } else if ( !!max && nValue > nMax ) {
            resetFields( $el );
            $el.addClass( userOpts.classInvalid );
            addMessage( $el, vsprintf(userOpts.msgExceedMax, [max]));

            allIsWell = false;
          }

        }
      }

      return allIsWell;
    };

    var validateFields = function ( evt ) {
      var $this   = $(this),
          fields  = $this.find('[required]'),
          isOK    = true,
          focusedField,
          msg;

      resetFields( fields );
      clearAllMessages( $this );

      isOK = validateEmpty( fields );

      if ( !isOK ) evt.preventDefault();

      isOK = validateEmail( fields );

      if ( !isOK ) evt.preventDefault();

      isOK = validateNumeric( fields );

      if ( !isOK ) {
        evt.preventDefault();

        $this.find('.' + userOpts.classInvalid).eq(0).focus();
      }
    };

    /**
     * Attach validateFields on form submit
     */
    this.$element.on('submit', validateFields);

    /**
     * Remove validateFields from submit event
     */
    this.$element.on('bazevalidate.destroy', function () {
      var $this = $(this);

      $this
        .off('submit', validateFields)
        .removeAttr('novalidate');
      $.removeData( $this[0], 'plugin_' + pluginName );
    });
  };

  /**
   * @param {string} email
   * @return {boolean}
   */
  function isEmailValid( email ) {
    // http://badsyntax.co/post/javascript-email-validation-rfc822
    return /^([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22))*\x40([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d))*$/.test( email );
  }

  function isNumber( n ) {
    return !isNaN(parseFloat(n)) && isFinite(n);
  }

  /**
   * @return {string} unique ID
   */
  function getUID() {
    var randInt = Math.floor((new Date).getTime()) + Math.floor((Math.random() * 100));
    var UID = 'BV' + randInt;

    return UID;
  }

  $.fn[ pluginName ] = function ( options ) {
    this.each(function() {
      if ( !$.data( this, "plugin_" + pluginName ) ) {
        $.data( this, "plugin_" + pluginName, new Plugin( this, options ) );
      }
    });

    return this;
  };

})( jQuery, window, document );
<commit_msg>code optimization and documentation<commit_after>;(function ( $, window, document, undefined ) {

  var pluginName = 'bazeValidate';

  /**
   * Plugin's default settings
   * @config {string} classInvalid
   * @config {string} classValid
   * @config {string} classMsg
   * @config {string} msgEmpty
   * @config {string} msgEmail
   * @config {string} msgNumber
   */
  var defaults = {
    classInvalid: 'form-input--error',
    classValid  : 'form-input--success',
    classMsg    : 'form-msg-error',

    msgEmpty    : 'This field is required.',
    msgEmail    : 'Invalid email address.',
    msgNumber   : 'Input must be number.',
    msgExceedMin: 'Minimum number is %s',
    msgExceedMax: 'Maximum number is %s'
  };

  /**
   * Represents the plugin instance
   * @param {DOM Object} element - The DOM Object
   * @param {Object} options - User options
   */
  function Plugin ( element, options ) {
    this.element    = element;
    this.$element   = $(element);
    this.settings   = $.extend( {}, defaults, options );
    this._defaults  = defaults;
    this._name      = pluginName;

    this.init();
  }

  Plugin.prototype.init = function () {
    var userOpts = this.settings;

    /**
     * Set novalidate attribute to prevent browser validation
     */
    this.element.setAttribute('novalidate', '');

    /**
     * set aria-required attribute to each required inputs
     */
    this.$element.find('[required]').attr('aria-required', 'true');

    /**
     * @param {jQuery object} form
     */
    var clearAllMessages = function ( form ) {
      var msgs = form.find('.' + userOpts.classMsg);

      $(msgs).remove();
    };

    /**
     * @param {jQuery object} field
     * @param {string} message
     */
    var addMessage = function ( field, message ) {
      var hasMsg  = field.parent().find('.' + userOpts.classMsg),
          id      = getUID(),
          msg     = $(document.createElement('span'));

      /**
       * Remove existing message
       */
      if ( hasMsg.length ) {
        hasMsg.remove();
      }

      /**
       * Add aria-describedBy and aria-invalid to invalid field
       */
      field.attr({
        'aria-describedBy': id,
        'aria-invalid': 'true'
      });

      /**
       * Place message after input element
       */
      msg
        .addClass( userOpts.classMsg )
        .attr('id', id)
        .text( message )
        .insertAfter( field );
    };

    /**
     * @param {jQuery object} fields
     */
    var resetFields = function ( fields ) {
      fields
        .removeAttr('aria-invalid aria-describedBy')
        .removeClass( userOpts.classInvalid )
        .removeClass( userOpts.classValid );
    };

    /**
     * @param {jQuery object} fields
     * @return {boolean}
     */
    var validateEmpty = function ( fields ) {
      var allIsWell = true;

      fields.each( function () {
        var $field  = $(this),
            value   = $field.val();

        if ( value === '' || value === null || $.trim(value) === '' ) {
          $field.addClass( userOpts.classInvalid );
          addMessage( $field, userOpts.msgEmpty );

          allIsWell = false;
        } else {
          $field.addClass( userOpts.classValid );
        }
      });

      return allIsWell;
    };

    /**
     * @param {jQuery object} fields
     * @return {boolean}
     */
    var validateEmail = function ( fields ) {
      var allIsWell = true;

      for (var i = 0, j = fields.length; i < j; i++) {
        var el    = fields[i],
            $el   = $(el),
            value = el.value,

            /**
             * el.type return text in IE8, so use getAttribute instead
             */
            type  = el.getAttribute('type');

        /**
         * Ignore if input type is not email
         */
        if ( type !== 'email' ) {
          continue;
        }

        if ( !isEmailValid( value ) ) {
          resetFields( $el );
          $el.addClass( userOpts.classInvalid );
          addMessage( $el, userOpts.msgEmail );

          allIsWell = false;
        }
      }

      return allIsWell;
    };

    /**
     * @param {jQuery object} fields
     * @return {boolean}
     */
    var validateNumeric = function ( fields ) {
      var allIsWell = true;

      for (var i = 0, j = fields.length; i < j; i++) {
        var el      = fields[i],
            $el     = $(el),
            value   = el.value,

            /**
             * el.type return text in IE8, so use getAttribute instead
             */
            type    = el.getAttribute('type'),
            min     = el.getAttribute('min') || false,
            max     = el.getAttribute('max') || false,
            nValue  = Math.floor(value),
            nMin    = Math.floor(min),
            nMax    = Math.floor(max);

        /**
         * Ignore if input type is not number
         */
        if ( type !== 'number' ) {
          continue;
        }

        if ( !isNumber( value ) ) {
          resetFields( $el );
          $el.addClass( userOpts.classInvalid );
          addMessage( $el, userOpts.msgNumber );

          allIsWell = false;
        } else {

          if ( !!min && nValue < nMin ) {
            resetFields( $el );
            $el.addClass( userOpts.classInvalid );
            addMessage( $el, vsprintf(userOpts.msgExceedMin, [min]));

            allIsWell = false;
          } else if ( !!max && nValue > nMax ) {
            resetFields( $el );
            $el.addClass( userOpts.classInvalid );
            addMessage( $el, vsprintf(userOpts.msgExceedMax, [max]));

            allIsWell = false;
          }

        }
      }

      return allIsWell;
    };

    var validateFields = function ( evt ) {
      var $this   = $(this),
          fields  = $this.find('[required]'),
          isOK    = true,
          focusedField,
          msg;

      resetFields( fields );
      clearAllMessages( $this );

      isOK = validateEmpty( fields );

      if ( !isOK ) evt.preventDefault();

      isOK = validateEmail( fields );

      if ( !isOK ) evt.preventDefault();

      isOK = validateNumeric( fields );

      if ( !isOK ) {
        evt.preventDefault();

        $this.find('.' + userOpts.classInvalid).eq(0).focus();
      }
    };

    /**
     * Attach validateFields on form submit
     */
    this.$element.on('submit', validateFields);

    /**
     * Remove validateFields from submit event
     */
    this.$element.on('bazevalidate.destroy', function () {
      var $this = $(this);

      $this
        .off('submit', validateFields)
        .removeAttr('novalidate');
      $.removeData( $this[0], 'plugin_' + pluginName );
    });
  };

  /**
   * @param {string} email
   * @return {boolean}
   */
  function isEmailValid( email ) {
    // http://badsyntax.co/post/javascript-email-validation-rfc822
    return /^([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22))*\x40([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d))*$/.test( email );
  }

  /**
   * @param {string||number} n
   * @return {boolean}
   */
  function isNumber( n ) {
    return !isNaN(parseFloat(n)) && isFinite(n);
  }

  /**
   * @return {string} unique ID
   */
  function getUID() {
    var randInt = Math.floor((new Date).getTime()) + Math.floor((Math.random() * 100));
    var UID = 'BV' + randInt;

    return UID;
  }

  $.fn[ pluginName ] = function ( options ) {
    this.each(function() {
      if ( !$.data( this, "plugin_" + pluginName ) ) {
        $.data( this, "plugin_" + pluginName, new Plugin( this, options ) );
      }
    });

    return this;
  };

})( jQuery, window, document );
<|endoftext|>


<commit_before>/**
 * @author Joppe Aarts <joppe@zicht.nl>
 * @copyright Zicht Online <http://zicht.nl>
 */

import {Params} from 'framework/request/params';

/**
 * @class Request
 */
export class Request {
    /**
     * @param {string} uri
     */
    constructor(uri) {
        this.params = new Params();
        this.params.setUri(uri);
    }
}<commit_msg>setUri method added for Request<commit_after>/**
 * @author Joppe Aarts <joppe@zicht.nl>
 * @copyright Zicht Online <http://zicht.nl>
 */

import {Params} from 'framework/request/Params';

/**
 * @class Request
 */
export class Request {
    constructor() {
        this.uri = '';
        this.params = new Params();
    }

    /**
     * @param {string} uri
     */
    setUri(uri) {
        let quotPos = uri.indexOf('?');

        this.uri = uri.substring(0, -1 === quotPos ? uri.length : quotPos);
        this.params.setUri(uri);
    }
}<|endoftext|>


<commit_before>describe('Inverted Index', () => {
  describe('Read book data', () => {
    it('should check that the file uploaded is a valid JSON file', () => {
      expect(myInvertedIndex.readBookData([])).toBeFalsy();
    });

    it('should check that the file uploaded is not empty', () => {
      expect(myInvertedIndex.readBookData(book)).tobeTruthy();
    });
  });

  describe('Populate Index', () => {
    it('should verify that the index is created once the JSON file has been read', () => {
      expect(myInvertedIndex.createIndex('books.json')).toBeTruthy();
    });

    it('should verify that the index maps the string keys to the correct objects in the JSON array', () => {
      expect(myInvertedIndex.getIndex('books.json').alice).toEqual([0]);
    });
  });

  describe('Search Index', () => {
    it('should return an array of correct objects that contains the search terms', () => {
      expect(myInvertedIndex.searchIndex('alice fellowship', 'books.json').toEqual({'books.json': { alice: [ 0 ], fellowship: [1] } }));
    });
    it('should go through all indexed files if a filename is not passed', () => {
      expect(myInvertedIndex.searchIndex('alice fellowship').toEqual({'books.json': { alice: [ 0 ], fellowship: [1] } }));
    });
  });
});
<commit_msg>modify test file<commit_after>/* Test Setup */
const myInvertedIndex = new InvertedIndex();

const book = require('./../books.json');
const emptyBook = require('./../empty-book.json');
const invalidBook = require('./../bad-book.json');

myInvertedIndex.files['book.json'] = book;

describe('Inverted Index', () => {
  describe('Read book data', () => {
    it('should check that the file uploaded is a valid JSON file', () => {
      expect(InvertedIndexUtilities.readBookData(invalidBook)).toEqual(false);
    });

    it('should check that the file uploaded is not empty', () => {
      expect(InvertedIndexUtilities.readBookData(emptyBook)).toEqual(false);
    });
  });

  describe('Populate Index', () => {
    it('should verify that the index is created once the JSON file has been read', () => {
      const index = myInvertedIndex.createIndex('book.json');
      expect(index['book.json']).toBeDefined();
    });

    it('should verify that the index maps the string keys to the correct objects in the JSON array', () => {
      const index = myInvertedIndex.getIndex('book.json');
      expect(myInvertedIndex.getIndex('book.json').and).toEqual([0, 1]);
    });
  });

  describe('Search Index', () => {
    it('should return an array of correct objects that contains the search terms', () => {
      expect(myInvertedIndex.searchIndex('alice fellowship', ['book.json'])).toEqual({'book.json': {alice: [0], fellowship: [1]}});
    });

    it('should go through all indexed files if a filename is not passed', () => {
      expect(myInvertedIndex.searchIndex('fellowship')).toEqual({'book.json': {fellowship: [1] } });
    });
  });
});

<|endoftext|>


<commit_before>const invertedIndex = new InvertedIndex();
const books = require('../books.json');
const empty = require('../emptyBook.json');
const invalid = require('../invalidBook.json');
const little = require('../littleBook.json');
describe("Inverted Index", () => {

  /**
   * Test suite to ensure the validateFile method returns an object of
   * the correct index mapping
   */

  describe('Read book data', () => {
    it('Should ensure file content is actually a valid JSON array', () => {
      expect(InvertedIndex.validateFile(books)).toEqual(true);
      console.log(books);
    });

    it('Should return false for invalid JSON file', () => {
      expect(InvertedIndex.validateFile(invalid)).toEqual(false);
    });

    it('Should ensure that JSON array is not empty', () => {
      expect(InvertedIndex.validateFile(empty)).toEqual(false);
    });
  });
  /*
   * Populate Index Test Suite
   */

  describe('Populate Index', () => {
    invertedIndex.createIndex('books.json', books);

    it('Should ensure that index is created once the file has been read', () => {
      expect(invertedIndex.indices['books.json']).toBeDefined();
    });

    it('Should map the string keys to the correct objects', () => {
      expect(invertedIndex.indices['books.json'].terms.alice).toEqual([1]);
      expect(invertedIndex.indices['books.json'].terms.and).toEqual([1, 2]);
      expect(invertedIndex.indices['books.json'].terms.lord).toEqual([2]);
    });

    invertedIndex.createIndex('littleBook.json', little);
    it('Should return an accurate index of the content of the json file', () => {
      expect(invertedIndex.getIndex('littleBook.json').terms.is).toEqual([1, 2]);
    });

  });

  /**
   * Test suite to ensure the getIndex method returns an object of
   * the correct index mapping
   */

  describe('Get index', () => {
    it('should return an object when value is found', () => {
      const indexedFile = invertedIndex.getIndex('books.json');
      expect(typeof(indexedFile) === 'object').toBeTruthy();
    });

    it('should contain valid indexed words and position', () => {
      expect(invertedIndex.getIndex('books.json').terms.alice).toEqual([1]);
      expect(invertedIndex.getIndex('books.json').terms.and).toEqual([1, 2]);
      expect(invertedIndex.getIndex('books.json').terms.lord).toEqual([2]);
    });
  });

  /**
   * Test suite to ensure the searchIndex method returns an object of
   * the correct index mapping
   */

  describe('Search Index', () => {
    invertedIndex.searchIndex('../books.json', 'alice');
    it('Should return correct index of the search term', () => {
      expect(invertedIndex.searchIndex('books.json', 'alice, a')[0]).toEqual({
        terms: {
          alice: [1],
          a: [1, 2]
        },
        count: 2,
        fileName: 'books.json'
      });
    });

    it('Should return books.json:[] when no result is found',
      () => {
        expect(invertedIndex.searchIndex('books.json', 'along')).toEqual([undefined]);
      });

    it('Should return correct index in an array search terms', () => {
      expect(invertedIndex.searchIndex('books.json', 'alice, [hole,[a]]')[0]).toEqual({
        terms: {
          alice: [1],
          hole: [1],
          a: [1, 2]
        },
        count: 2,
        fileName: 'books.json'
      });
    });
  });
});
<commit_msg>refactor(test): ensure all tests meet requirement<commit_after>/* eslint-disable no-unused-vars*/
/* eslint-disable no-undef*/
/* eslint-disable no-dupe-keys*/
/* eslint-disable no-multi-assign*/
const invertedIndex = new InvertedIndex();
const books = require('../books.json');
const empty = require('../emptyBook.json');
const invalid = require('../invalidBook.json');
const little = require('../littleBook.json');
describe("Inverted Index", () => {

  /**
   * Test suite to ensure the validateFile method returns an object of
   * the correct index mapping
   */

  describe('Read book data', () => {
    it('Should ensure file content is actually a valid JSON array', () => {
      expect(InvertedIndex.validateFile(books)).toEqual(true);
    });

    it('Should return false for invalid JSON file', () => {
      expect(InvertedIndex.validateFile(invalid)).toEqual(false);
    });

    it('Should ensure that JSON array is not empty', () => {
      expect(InvertedIndex.validateFile(empty)).toEqual(false);
    });
  });

  /*
   * Populate Index Test Suite
   */

  describe('Populate Index', () => {
    invertedIndex.createIndex('books.json', books);

    it('Should ensure that index is created once the file has been read', () => {
      expect(invertedIndex.indices['books.json']).toBeDefined();
    });

    it('Should map the string keys to the correct objects', () => {
      expect(invertedIndex.indices['books.json'].terms.alice).toEqual([1]);
      expect(invertedIndex.indices['books.json'].terms.and).toEqual([1, 2]);
      expect(invertedIndex.indices['books.json'].terms.lord).toEqual([2]);
    });

    invertedIndex.createIndex('littleBook.json', little);
    it('Should return an accurate index of the content of the json file', () => {
      expect(invertedIndex.getIndex('littleBook.json').terms.is).toEqual([1, 2]);
    });

  });

  /**
   * Test suite to ensure the getIndex method returns an object of
   * the correct index mapping
   */

  describe('Get index', () => {
    it('Should return an object when value is found', () => {
      const indexedFile = invertedIndex.getIndex('books.json');
      expect(typeof(indexedFile) === 'object').toBeTruthy();
    });

    it('Should contain valid indexed words and position', () => {
      expect(invertedIndex.getIndex('books.json').terms.alice).toEqual([1]);
      expect(invertedIndex.getIndex('books.json').terms.and).toEqual([1, 2]);
      expect(invertedIndex.getIndex('books.json').terms.lord).toEqual([2]);
    });
  });

  /**
   * Test suite to ensure the tokenizer method returns an object of
   * the correct index mapping
   */
  describe('Tokenizer', () => {
    it('Should return an array when a string is passed', () => {
      expect(InvertedIndex.tokenizer('This is yemi')).toEqual(['this', 'is', 'yemi']);
    });
    it('Should return an array when a recursive array is passed', () => {
      expect(InvertedIndex.tokenizer('books.json', ['a', 'alice'], 'book', 'me'))
        .toEqual(['books', 'json']);
    });
  });

  /**
   * Test suite to ensure the searchIndex method returns an object of
   * the correct index mapping
   */

  describe('Search Index', () => {
    invertedIndex.searchIndex('../books.json', 'alice');
    it('Should return correct index of the search term', () => {
      expect(invertedIndex.searchIndex('books.json', 'alice, a')[0]).toEqual({
        terms: {
          alice: [1],
          a: [1, 2]
        },
        count: 2,
        fileName: 'books.json'
      });
    });

    it('Should return books.json:[] when no result is found',
      () => {
        expect(invertedIndex.searchIndex('books.json', 'along')).toEqual(false);
      });

    it('Should return correct index in an array search terms', () => {
      expect(invertedIndex.searchIndex('books.json', 'alice, [hole,[a]]')[0]).toEqual({
        terms: {
          alice: [1],
          hole: [1],
          a: [1, 2]
        },
        count: 2,
        fileName: 'books.json'
      });
    });
    it('Should ensure searchIndex can handle a number of varied search terms', () => {
      expect(invertedIndex.searchIndex('littleBook.json', '[is, [ali, book, me, [help, me, out]]]')).toEqual([{
        terms: {
          is: [1, 2],
          ali: [1],
          me: [2]
        },
        count: 2,
        fileName: 'littleBook.json'
      }]);
    });
    it('Should go through all indexed terms if fileName is not passed', () => {
      expect(invertedIndex.searchIndex(null, 'alice, ali')).toEqual([{
        terms: {
          alice: [1]
        },
        count: 2,
        fileName: 'books.json'
      }, {
        terms: {
          ali: [1]
        },
        count: 2,
        fileName: 'littleBook.json'
      }])
    })
  });
});
<|endoftext|>


<commit_before>//Author: Ming Qin at Yahoo! Inc.
//Forked from Mike Bostock's [D3 Sankey plugin](https://github.com/d3/d3-plugins/tree/master/sankey)

d3.sankey = function() {
  var sankey = {},
      nodeWidth = 24,
      nodePadding = 8,
      size = [1, 1],
      nodes = [],
      flows = [],
      links = [],
      linkDict = {},
      dflows = [], //dynamic links
      dlinks = [],
      dlinkDict = {},
      ky = 0;

  sankey.nodeWidth = function(_) {
    if (!arguments.length) return nodeWidth;
    nodeWidth = +_;
    return sankey;
  };

  sankey.nodePadding = function(_) {
    if (!arguments.length) return nodePadding;
    nodePadding = +_;
    return sankey;
  };

  sankey.nodes = function(_) {
    if (!arguments.length) return nodes;
    nodes = _;
    return sankey;
  };

  sankey.links = function(_) {
    if (!arguments.length) return links;
    links = _;
    return sankey;
  };

  sankey.size = function(_) {
    if (!arguments.length) return size;
    size = _;
    return sankey;
  };

  sankey.layout = function(iterations) {
    computeNodeLinks();
    computeNodeValues();
    computeNodeBreadths();
    computeNodeDepths(iterations);
    computeLinkDepths();
    return sankey;
  };

  sankey.relayout = function() {
    computeLinkDepths();
    computeDlinks();
    // console.log(links[0].dy,links[0].sy,links[0].ty);
    return sankey;
  };

  sankey.link = function() {
    var curvature = 0.5;

    function link(d) {
      var x0 = d.source.x + d.source.dx,
          x1 = d.target.x,
          xi = d3.interpolateNumber(x0, x1),
          x2 = xi(curvature),
          x3 = xi(1 - curvature),
          y0 = d.source.y + d.sy + d.dy / 2,
          y1 = d.target.y + d.ty + d.dy / 2;
      return "M" + x0 + "," + y0 +
             "C" + x2 + "," + y0 +
             " " + x3 + "," + y1 +
             " " + x1 + "," + y1;
    }

    link.curvature = function(_) {
      if (!arguments.length) return curvature;
      curvature = +_;
      return link;
    };

    return link;
  };

  // Populate the sourceLinks and targetLinks for each node.
  // Also, if the source and target are not objects, assume they are indices.
  function computeNodeLinks() {
    nodes.forEach(function(node) {
      node.sourceLinks = [];
      node.targetLinks = [];
    });
    links.forEach(function(link) {
      var source = link.source,
          target = link.target;
      // if (typeof source === "number") source = link.source = nodes[link.source];
      // if (typeof target === "number") target = link.target = nodes[link.target];
      source.sourceLinks.push(link);
      target.targetLinks.push(link);
    });
  }

  // Compute the value (size) of each node by summing the associated links.
  function computeNodeValues() {
    nodes.forEach(function(node) {
      node.value = Math.max(
        d3.sum(node.sourceLinks, value),
        d3.sum(node.targetLinks, value)
      );
    });
  }

  // Iteratively assign the breadth (x-position) for each node.
  // Nodes are assigned the maximum breadth of incoming neighbors plus one;
  // nodes with no incoming links are assigned breadth zero, while
  // nodes with no outgoing links are assigned the maximum breadth.
  function computeNodeBreadths() {
      var remainingNodes = nodes,
          nextNodes,
          x = 0;

      function pick_node(node) {
          node.x = x;
          node.dx = nodeWidth;
          node.sourceLinks.forEach(push_if_didnt);
      }

      function push_if_didnt(link) {
          if (nextNodes.indexOf(link.target) < 0) {
              nextNodes.push(link.target);
          }
      }

      while (remainingNodes.length) {
          nextNodes = [];
          remainingNodes.forEach(pick_node);
          remainingNodes = nextNodes;
          ++x;
      }

      //
      moveSinksRight(x);
      scaleNodeBreadths((size[0] - nodeWidth) / (x - 1));
  }

  function moveSourcesRight() {
    nodes.forEach(function(node) {
      if (!node.targetLinks.length) {
        node.x = d3.min(node.sourceLinks, function(d) { return d.target.x; }) - 1;
      }
    });
  }

  function moveSinksRight(x) {
    nodes.forEach(function(node) {
      if (!node.sourceLinks.length) {
        node.x = x - 1;
      }
    });
  }

  function scaleNodeBreadths(kx) {
    nodes.forEach(function(node) {
      node.x *= kx;
    });
  }

  function computeNodeDepths(iterations) {
    var nodesByBreadth = d3.nest()
        .key(function(d) { return d.x; })
        .sortKeys(d3.ascending)
        .entries(nodes)
        .map(function(d) { return d.values; });

    //
    initializeNodeDepth();
    resolveCollisions();
    for (var alpha = 1; iterations > 0; --iterations) {
      relaxRightToLeft(alpha *= 0.99);
      resolveCollisions();
      relaxLeftToRight(alpha);
      resolveCollisions();
    }

    function initializeNodeDepth() {
      ky = d3.min(nodesByBreadth, function(nodes) {
        return (size[1] - (nodes.length - 1) * nodePadding) / d3.sum(nodes, value);
      });

      nodesByBreadth.forEach(function(nodes) {
        nodes.forEach(function(node, i) {
          node.y = i;
          node.dy = node.value * ky;
        });
      });

      links.forEach(function(link) {
        link.dy = link.value * ky;
      });
    }

    function relaxLeftToRight(alpha) {
      nodesByBreadth.forEach(function(nodes, breadth) {
        nodes.forEach(function(node) {
          if (node.targetLinks.length) {
            var y = d3.sum(node.targetLinks, weightedSource) / d3.sum(node.targetLinks, value);
            node.y += (y - center(node)) * alpha;
          }
        });
      });

      function weightedSource(link) {
        return center(link.source) * link.value;
      }
    }

    function relaxRightToLeft(alpha) {
      nodesByBreadth.slice().reverse().forEach(function(nodes) {
        nodes.forEach(function(node) {
          if (node.sourceLinks.length) {
            var y = d3.sum(node.sourceLinks, weightedTarget) / d3.sum(node.sourceLinks, value);
            node.y += (y - center(node)) * alpha;
          }
        });
      });

      function weightedTarget(link) {
        return center(link.target) * link.value;
      }
    }

    function resolveCollisions() {
      nodesByBreadth.forEach(function(nodes) {
        var node,
            dy,
            y0 = 0,
            n = nodes.length,
            i;

        // Push any overlapping nodes down.
        nodes.sort(ascendingDepth);
        for (i = 0; i < n; ++i) {
          node = nodes[i];
          dy = y0 - node.y;
          if (dy > 0) node.y += dy;
          y0 = node.y + node.dy + nodePadding;
        }

        // If the bottommost node goes outside the bounds, push it back up.
        dy = y0 - nodePadding - size[1];
        if (dy > 0) {
          y0 = node.y -= dy;

          // Push any overlapping nodes back up.
          for (i = n - 2; i >= 0; --i) {
            node = nodes[i];
            dy = node.y + node.dy + nodePadding - y0;
            if (dy > 0) node.y -= dy;
            y0 = node.y;
          }
        }
      });
    }
  }

  function ascendingDepth(a, b) {
    return a.y - b.y;
  }

  function computeLinkDepths() {
    nodes.forEach(function(node) {
      node.sourceLinks.sort(ascendingTargetDepth);
      node.targetLinks.sort(ascendingSourceDepth);
    });
    nodes.forEach(function(node) {
      var sy = 0, ty = 0;
      node.sourceLinks.forEach(function(link) {
        link.sy = sy;
        sy += link.dy;
      });
      node.targetLinks.forEach(function(link) {
        link.ty = ty;
        ty += link.dy;
      });
    });
  }

  function ascendingSourceDepth(a, b) {
    return a.source.y - b.source.y;
  }

  function ascendingTargetDepth(a, b) {
    return a.target.y - b.target.y;
  }

  function center(node) {
    return node.y + node.dy / 2;
  }

  function value(link) {
    return link.value;
  }

  //////////////////////////////
  // Ming : for the dynamic links
  ////////////////////////////

  //will modify linkDict, links, flows
  sankey.flows = function(_) {
    flows = _;
    if (!nodes.length) console.error('sankey.nodes() must be called before flows()');
    linkDict = {};

    flows.forEach(function (f, ind) {

      //normalize nodes in f.thru
      f.thru = f.thru.map(function (n) {
        if (typeof n === "number"){
          return nodes[n];
        } else if (typeof n === "object"){
          return n;
        } else {
          console.error('not supported node type');
          return null;
        }
      });

      //build index in nodes, pointing back to f
      f.thru.forEach(function (n) {
        if (!n.flows){
          n.flows = {};
        }
        n.flows[ind] = true;
      });

      //extract links
      for (var i = 0; i < f.thru.length - 1; i++) {
        var key = stPair(f.thru[i], f.thru[i + 1]);
        if (linkDict[key]) {
          linkDict[key].value += f.value;
          linkDict[key].flows.push(f);
        } else {
          linkDict[key] = {
            source: f.thru[i],
            target: f.thru[i + 1],
            value: f.value,
            flows: [f],
          };
        }

      }
    });
    nodes.forEach(function (n) {
      var sets = n.flows;
      n.flows = [];
      for (var i in sets){
        n.flows.push(flows[i]);
      }
    });

    links = [];
    for (var key in linkDict) {
      var l = linkDict[key];
      links.push(l);
    }

    return sankey;
  };

  //will modify dlinks
  sankey.dflows = function(_) {
    dflows = _;
    dlinkDict = {};
    dflows.forEach(function (f) {
      for (var i = 0; i < f.thru.length - 1; i++) {
        var key = stPair(f.thru[i], f.thru[i + 1]);
        if (dlinkDict[key]) {
          dlinkDict[key].value += f.value;
        } else {
          dlinkDict[key] = {
            source: f.thru[i],
            target: f.thru[i + 1],
            value: f.value,
            sy: linkDict[key].sy,
            ty: linkDict[key].ty,
          };
        }
      }
    });
    dlinks = [];
    for (var key in dlinkDict) {
      var l = dlinkDict[key];
      l.dy = l.value * ky;
      dlinks.push(dlinkDict[key]);
    }
    this.relayout();
    return sankey;
  };

  sankey.dlinks = function() {
    return dlinks;
  };

  function stPair(s, t) {
    if (typeof s === 'number') {
      return nodes[s].name + '|' + nodes[t].name ;
    } else if (typeof s === 'object') {
      return s.name + '|' + t.name;
    } else if (typeof s === 'string'){
      return s + '|' + t;
    } else {
      console.error('wrong type');
    }
  }

  function computeDlinks() {
    // dlinks.forEach(function (l) {
    //   var slink = linkDict[stPair(l.source, l.target)];
    //   l.sy = slink.sy;
    //   l.ty = slink.ty;
    // });

    dflows.forEach(function (f) {
      for (var i = 1; i < f.thru.length - 1; i++) {
        var center, commonBot, commonTop, ddy0, ddy1, dsy1, dty0, dy0, dy1,
          key0, key1, link0, link1, dlink0, dlink1, childsy1, ty0;
        key0 = stPair(f.thru[i - 1], f.thru[i]);
        key1 = stPair(f.thru[i], f.thru[i + 1]);
        link0 = linkDict[key0];
        link1 = linkDict[key1];
        dlink0 = dlinkDict[key0];
        dlink1 = dlinkDict[key1];
        ty0 = link0.ty;
        dy0 = link0.dy;
        sy1 = link1.sy;
        dy1 = link1.dy;
        ddy0 = dlink0.dy;
        ddy1 = dlink1.dy;
        // compute the ideal position of both links on two sides
        commonTop = Math.max(ty0, sy1);
        commonBot = Math.min(ty0 + dy0, sy1 + dy1);
        center = (commonTop + commonBot) / 2;
        dty0 = center - (ddy0 / 2);
        dsy1 = center - (ddy1 / 2);
        // limit the position
        dty0 = Math.max(dty0, ty0);
        dty0 = Math.min(dty0, ty0 + dy0 - ddy0);
        dsy1 = Math.max(dsy1, sy1);
        dsy1 = Math.min(dsy1, sy1 + dy1 - ddy1);
        // set y
        dlink0.ty = dty0;
        dlink1.sy = dsy1;
        if (!dlink0.sy){
          dlink0.sy = link0.sy - (link0.ty - dlink0.ty);
        }
        dlink1.ty = link1.ty - (link1.sy - dlink1.sy);
      }
    });
  }

  return sankey;
};
<commit_msg>reverse the order of dflows. This solves a lot of broken links visually maybe because the nodes are basically sorted from the bigger ones to smaller<commit_after>//Author: Ming Qin at Yahoo! Inc.
//Forked from Mike Bostock's [D3 Sankey plugin](https://github.com/d3/d3-plugins/tree/master/sankey)

d3.sankey = function() {
  var sankey = {},
      nodeWidth = 24,
      nodePadding = 8,
      size = [1, 1],
      nodes = [],
      flows = [],
      links = [],
      linkDict = {},
      dflows = [], //dynamic links
      dlinks = [],
      dlinkDict = {},
      ky = 0;

  sankey.nodeWidth = function(_) {
    if (!arguments.length) return nodeWidth;
    nodeWidth = +_;
    return sankey;
  };

  sankey.nodePadding = function(_) {
    if (!arguments.length) return nodePadding;
    nodePadding = +_;
    return sankey;
  };

  sankey.nodes = function(_) {
    if (!arguments.length) return nodes;
    nodes = _;
    return sankey;
  };

  sankey.links = function(_) {
    if (!arguments.length) return links;
    links = _;
    return sankey;
  };

  sankey.size = function(_) {
    if (!arguments.length) return size;
    size = _;
    return sankey;
  };

  sankey.layout = function(iterations) {
    computeNodeLinks();
    computeNodeValues();
    computeNodeBreadths();
    computeNodeDepths(iterations);
    computeLinkDepths();
    return sankey;
  };

  sankey.relayout = function() {
    computeLinkDepths();
    computeDlinks();
    // console.log(links[0].dy,links[0].sy,links[0].ty);
    return sankey;
  };

  sankey.link = function() {
    var curvature = 0.5;

    function link(d) {
      var x0 = d.source.x + d.source.dx,
          x1 = d.target.x,
          xi = d3.interpolateNumber(x0, x1),
          x2 = xi(curvature),
          x3 = xi(1 - curvature),
          y0 = d.source.y + d.sy + d.dy / 2,
          y1 = d.target.y + d.ty + d.dy / 2;
      return "M" + x0 + "," + y0 +
             "C" + x2 + "," + y0 +
             " " + x3 + "," + y1 +
             " " + x1 + "," + y1;
    }

    link.curvature = function(_) {
      if (!arguments.length) return curvature;
      curvature = +_;
      return link;
    };

    return link;
  };

  // Populate the sourceLinks and targetLinks for each node.
  // Also, if the source and target are not objects, assume they are indices.
  function computeNodeLinks() {
    nodes.forEach(function(node) {
      node.sourceLinks = [];
      node.targetLinks = [];
    });
    links.forEach(function(link) {
      var source = link.source,
          target = link.target;
      // if (typeof source === "number") source = link.source = nodes[link.source];
      // if (typeof target === "number") target = link.target = nodes[link.target];
      source.sourceLinks.push(link);
      target.targetLinks.push(link);
    });
  }

  // Compute the value (size) of each node by summing the associated links.
  function computeNodeValues() {
    nodes.forEach(function(node) {
      node.value = Math.max(
        d3.sum(node.sourceLinks, value),
        d3.sum(node.targetLinks, value)
      );
    });
  }

  // Iteratively assign the breadth (x-position) for each node.
  // Nodes are assigned the maximum breadth of incoming neighbors plus one;
  // nodes with no incoming links are assigned breadth zero, while
  // nodes with no outgoing links are assigned the maximum breadth.
  function computeNodeBreadths() {
      var remainingNodes = nodes,
          nextNodes,
          x = 0;

      function pick_node(node) {
          node.x = x;
          node.dx = nodeWidth;
          node.sourceLinks.forEach(push_if_didnt);
      }

      function push_if_didnt(link) {
          if (nextNodes.indexOf(link.target) < 0) {
              nextNodes.push(link.target);
          }
      }

      while (remainingNodes.length) {
          nextNodes = [];
          remainingNodes.forEach(pick_node);
          remainingNodes = nextNodes;
          ++x;
      }

      //
      moveSinksRight(x);
      scaleNodeBreadths((size[0] - nodeWidth) / (x - 1));
  }

  function moveSourcesRight() {
    nodes.forEach(function(node) {
      if (!node.targetLinks.length) {
        node.x = d3.min(node.sourceLinks, function(d) { return d.target.x; }) - 1;
      }
    });
  }

  function moveSinksRight(x) {
    nodes.forEach(function(node) {
      if (!node.sourceLinks.length) {
        node.x = x - 1;
      }
    });
  }

  function scaleNodeBreadths(kx) {
    nodes.forEach(function(node) {
      node.x *= kx;
    });
  }

  function computeNodeDepths(iterations) {
    var nodesByBreadth = d3.nest()
        .key(function(d) { return d.x; })
        .sortKeys(d3.ascending)
        .entries(nodes)
        .map(function(d) { return d.values; });

    //
    initializeNodeDepth();
    resolveCollisions();
    for (var alpha = 1; iterations > 0; --iterations) {
      relaxRightToLeft(alpha *= 0.99);
      resolveCollisions();
      relaxLeftToRight(alpha);
      resolveCollisions();
    }

    function initializeNodeDepth() {
      ky = d3.min(nodesByBreadth, function(nodes) {
        return (size[1] - (nodes.length - 1) * nodePadding) / d3.sum(nodes, value);
      });

      nodesByBreadth.forEach(function(nodes) {
        nodes.forEach(function(node, i) {
          node.y = i;
          node.dy = node.value * ky;
        });
      });

      links.forEach(function(link) {
        link.dy = link.value * ky;
      });
    }

    function relaxLeftToRight(alpha) {
      nodesByBreadth.forEach(function(nodes, breadth) {
        nodes.forEach(function(node) {
          if (node.targetLinks.length) {
            var y = d3.sum(node.targetLinks, weightedSource) / d3.sum(node.targetLinks, value);
            node.y += (y - center(node)) * alpha;
          }
        });
      });

      function weightedSource(link) {
        return center(link.source) * link.value;
      }
    }

    function relaxRightToLeft(alpha) {
      nodesByBreadth.slice().reverse().forEach(function(nodes) {
        nodes.forEach(function(node) {
          if (node.sourceLinks.length) {
            var y = d3.sum(node.sourceLinks, weightedTarget) / d3.sum(node.sourceLinks, value);
            node.y += (y - center(node)) * alpha;
          }
        });
      });

      function weightedTarget(link) {
        return center(link.target) * link.value;
      }
    }

    function resolveCollisions() {
      nodesByBreadth.forEach(function(nodes) {
        var node,
            dy,
            y0 = 0,
            n = nodes.length,
            i;

        // Push any overlapping nodes down.
        nodes.sort(ascendingDepth);
        for (i = 0; i < n; ++i) {
          node = nodes[i];
          dy = y0 - node.y;
          if (dy > 0) node.y += dy;
          y0 = node.y + node.dy + nodePadding;
        }

        // If the bottommost node goes outside the bounds, push it back up.
        dy = y0 - nodePadding - size[1];
        if (dy > 0) {
          y0 = node.y -= dy;

          // Push any overlapping nodes back up.
          for (i = n - 2; i >= 0; --i) {
            node = nodes[i];
            dy = node.y + node.dy + nodePadding - y0;
            if (dy > 0) node.y -= dy;
            y0 = node.y;
          }
        }
      });
    }
  }

  function ascendingDepth(a, b) {
    return a.y - b.y;
  }

  function computeLinkDepths() {
    nodes.forEach(function(node) {
      node.sourceLinks.sort(ascendingTargetDepth);
      node.targetLinks.sort(ascendingSourceDepth);
    });
    nodes.forEach(function(node) {
      var sy = 0, ty = 0;
      node.sourceLinks.forEach(function(link) {
        link.sy = sy;
        sy += link.dy;
      });
      node.targetLinks.forEach(function(link) {
        link.ty = ty;
        ty += link.dy;
      });
    });
  }

  function ascendingSourceDepth(a, b) {
    return a.source.y - b.source.y;
  }

  function ascendingTargetDepth(a, b) {
    return a.target.y - b.target.y;
  }

  function center(node) {
    return node.y + node.dy / 2;
  }

  function value(link) {
    return link.value;
  }

  //////////////////////////////
  // Ming : for the dynamic links
  ////////////////////////////

  //will modify linkDict, links, flows
  sankey.flows = function(_) {
    flows = _;
    if (!nodes.length) console.error('sankey.nodes() must be called before flows()');
    linkDict = {};

    flows.forEach(function (f, ind) {

      //normalize nodes in f.thru
      f.thru = f.thru.map(function (n) {
        if (typeof n === "number"){
          return nodes[n];
        } else if (typeof n === "object"){
          return n;
        } else {
          console.error('not supported node type');
          return null;
        }
      });

      //build index in nodes, pointing back to f
      f.thru.forEach(function (n) {
        if (!n.flows){
          n.flows = {};
        }
        n.flows[ind] = true;
      });

      //extract links
      for (var i = 0; i < f.thru.length - 1; i++) {
        var key = stPair(f.thru[i], f.thru[i + 1]);
        if (linkDict[key]) {
          linkDict[key].value += f.value;
          linkDict[key].flows.push(f);
        } else {
          linkDict[key] = {
            source: f.thru[i],
            target: f.thru[i + 1],
            value: f.value,
            flows: [f],
          };
        }

      }
    });
    nodes.forEach(function (n) {
      var sets = n.flows;
      n.flows = [];
      for (var i in sets){
        n.flows.push(flows[i]);
      }
    });

    links = [];
    for (var key in linkDict) {
      var l = linkDict[key];
      links.push(l);
    }

    return sankey;
  };

  //will modify dlinks
  sankey.dflows = function(_) {
    dflows = _;
    dlinkDict = {};
    dflows.forEach(function (f) {
      for (var i = 0; i < f.thru.length - 1; i++) {
        var key = stPair(f.thru[i], f.thru[i + 1]);
        if (dlinkDict[key]) {
          dlinkDict[key].value += f.value;
        } else {
          dlinkDict[key] = {
            source: f.thru[i],
            target: f.thru[i + 1],
            value: f.value,
            sy: linkDict[key].sy,
            ty: linkDict[key].ty,
          };
        }
      }
    });
    dlinks = [];
    for (var key in dlinkDict) {
      var l = dlinkDict[key];
      l.dy = l.value * ky;
      dlinks.push(dlinkDict[key]);
    }
    this.relayout();
    return sankey;
  };

  sankey.dlinks = function() {
    return dlinks;
  };

  function stPair(s, t) {
    if (typeof s === 'number') {
      return nodes[s].name + '|' + nodes[t].name ;
    } else if (typeof s === 'object') {
      return s.name + '|' + t.name;
    } else if (typeof s === 'string'){
      return s + '|' + t;
    } else {
      console.error('wrong type');
    }
  }

  function computeDlinks() {
    // dflows.reverse().forEach(function (f) {
    for (var k = dflows.length-1 ; k>=0; k--){
      var f = dflows[k];
      for (var i = 1; i < f.thru.length - 1; i++) {
        var center, commonBot, commonTop, ddy0, ddy1, dsy1, dty0, dy0, dy1,
          key0, key1, link0, link1, dlink0, dlink1, childsy1, ty0;
        key0 = stPair(f.thru[i - 1], f.thru[i]);
        key1 = stPair(f.thru[i], f.thru[i + 1]);
        link0 = linkDict[key0];
        link1 = linkDict[key1];
        dlink0 = dlinkDict[key0];
        dlink1 = dlinkDict[key1];
        ty0 = link0.ty;
        dy0 = link0.dy;
        sy1 = link1.sy;
        dy1 = link1.dy;
        ddy0 = dlink0.dy;
        ddy1 = dlink1.dy;
        // compute the ideal position of both links on two sides
        commonTop = Math.max(ty0, sy1);
        commonBot = Math.min(ty0 + dy0, sy1 + dy1);
        center = (commonTop + commonBot) / 2;
        dty0 = center - (ddy0 / 2);
        dsy1 = center - (ddy1 / 2);
        // limit the position
        dty0 = Math.max(dty0, ty0);
        dty0 = Math.min(dty0, ty0 + dy0 - ddy0);
        dsy1 = Math.max(dsy1, sy1);
        dsy1 = Math.min(dsy1, sy1 + dy1 - ddy1);
        // set y
        dlink0.ty = dty0;
        dlink1.sy = dsy1;
        if (!dlink0.sy){
          dlink0.sy = link0.sy - (link0.ty - dlink0.ty);
        }
        dlink1.ty = link1.ty - (link1.sy - dlink1.sy);
      }
    }
  }

  return sankey;
};
<|endoftext|>


<commit_before>/*
 * This file is part of Workout Manager.
 *
 * Workout Manager is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Workout Manager is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 */

/*
 * This file provides integration to Ubuntu's Unity interface with WebApps.
 *
 * For more details look at:
 * - http://developer.ubuntu.com/api/ubuntu-12.04/javascript/index.html
 * - http://developer.ubuntu.com/api/ubuntu-12.04/javascript/unity-web-api-reference.html
 * - http://developer.ubuntu.com/resources/app-developer-cookbook/unity/integrating-tumblr-to-your-desktop/
 */

// helper function, taken from https://bazaar.launchpad.net/~webapps/webapps-applications/trunk/view/head:/common/utils.js.in
function evalInPageContext(func) {
    var script = document.createElement('script');
    script.appendChild(document.createTextNode('(' + func + ')();'));
    (document.body || document.head || document.documentElement).appendChild(script);
}

// helper function, taken from https://bazaar.launchpad.net/~webapps/webapps-applications/trunk/view/head:/common/utils.js.in
function makeRedirector(link) {
    return function () {
        evalInPageContext('function() {window.location = "' + link + '";}');
    };
}

// Do the actual integration, not much to do though
function unityReady() {
    Unity.Launcher.removeActions();
    Unity.Launcher.addAction("Workouts", makeRedirector('http://gargancjan.lem:8000/workout/overview'));
    Unity.Launcher.addAction("Weight chart", makeRedirector('http://gargancjan.lem:8000/weight/overview/'));
    Unity.Launcher.addAction("Add weight entry", makeRedirector('http://gargancjan.lem:8000/weight/add/'));
    Unity.Launcher.addAction("Nutrition plans", makeRedirector('http://gargancjan.lem:8000/nutrition/overview/'));
}

// If we are using Ubuntu, call the Init method for Unity, otherwise, do nothing
try
{
    var Unity = external.getUnityObject(1);

    // Commented out till I make it work reliably
    /*
    Unity.init({name: "Workout Manager",
            iconUrl: "http://developer.ubuntu.com/wp-content/uploads/2012/08/icon1.png",
            onInit: unityReady,
            homepage: "http://gargancjan.lem:8000/"});
    */
}
catch(err)
{

}
<commit_msg>Update URL in unity files<commit_after>/*
 * This file is part of Workout Manager.
 *
 * Workout Manager is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Workout Manager is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 */

/*
 * This file provides integration to Ubuntu's Unity interface with WebApps.
 *
 * For more details look at:
 * - http://developer.ubuntu.com/api/ubuntu-12.04/javascript/index.html
 * - http://developer.ubuntu.com/api/ubuntu-12.04/javascript/unity-web-api-reference.html
 * - http://developer.ubuntu.com/resources/app-developer-cookbook/unity/integrating-tumblr-to-your-desktop/
 */

// helper function, taken from https://bazaar.launchpad.net/~webapps/webapps-applications/trunk/view/head:/common/utils.js.in
function evalInPageContext(func) {
    var script = document.createElement('script');
    script.appendChild(document.createTextNode('(' + func + ')();'));
    (document.body || document.head || document.documentElement).appendChild(script);
}

// helper function, taken from https://bazaar.launchpad.net/~webapps/webapps-applications/trunk/view/head:/common/utils.js.in
function makeRedirector(link) {
    return function () {
        evalInPageContext('function() {window.location = "' + link + '";}');
    };
}

// Do the actual integration, not much to do though
function unityReady() {
    Unity.Launcher.removeActions();
    Unity.Launcher.addAction("Workouts", makeRedirector('http://wger.de/workout/overview'));
    Unity.Launcher.addAction("Weight chart", makeRedirector('http://wger.de/weight/overview/'));
    Unity.Launcher.addAction("Add weight entry", makeRedirector('http://wger.de/weight/add/'));
    Unity.Launcher.addAction("Nutrition plans", makeRedirector('http://wger.de/nutrition/overview/'));
}

// If we are using Ubuntu, call the Init method for Unity, otherwise, do nothing
try
{
    var Unity = external.getUnityObject(1);

    // Commented out till I make it work reliably
    /*
    Unity.init({name: "Workout Manager",
            iconUrl: "http://developer.ubuntu.com/wp-content/uploads/2012/08/icon1.png",
            onInit: unityReady,
            homepage: "http://gargancjan.lem:8000/"});
    */
}
catch(err)
{

}
<|endoftext|>


<commit_before>function RestInPlaceEditor(e) {
  this.element = jQuery(e);
  this.initOptions();
  this.bindForm();

  this.element.bind('click', {editor: this}, this.clickHandler);
}

RestInPlaceEditor.prototype = {
  // Public Interface Functions //////////////////////////////////////////////

  activate : function() {
    this.oldValue = this.element.html();
    this.element.unbind('click', this.clickHandler)
    this.activateForm();
  },

  abort : function() {
    this.element
      .html(this.oldValue)
      .bind('click', {editor: this}, this.clickHandler);
  },

  update : function() {
    var editor = this;
    editor.ajax({
      "type"       : "post",
      "data"       : editor.requestData(),
      "success"    : function(){
        editor.ajax({
          "dataType" : 'json',
          "success"  : function(data){ editor.loadSuccessCallback(data) }
        });
      }
    });
    editor.element.html("saving...");
  },

  activateForm : function() {
    alert("The form was not properly initialized. activateForm is unbound");
  },

  // Helper Functions ////////////////////////////////////////////////////////

  initOptions : function() {
    // Try parent supplied info
    var self = this;
    self.element.parents().each(function(){
      self.url           = self.url           || jQuery(this).attr("data-url");
      self.formType      = self.formType      || jQuery(this).attr("data-formtype");
      self.objectName    = self.objectName    || jQuery(this).attr("data-object");
      self.attributeName = self.attributeName || jQuery(this).attr("data-attribute");
    });
    // Try Rails-id based if parents did not explicitly supply something
    self.element.parents().each(function(){
      var res;
      if (res = this.id.match(/^(\w+)_(\d+)$/i)) {
        self.objectName = self.objectName || res[1];
      }
    });
    // Load own attributes (overrides all others)
    self.url           = self.element.attr("data-url")       || self.url      || document.location.pathname;
    self.formType      = self.element.attr("data-formtype")  || self.formtype || "input";
    self.objectName    = self.element.attr("data-object")    || self.objectName;
    self.attributeName = self.element.attr("data-attribute") || self.attributeName;
  },

  bindForm : function() {
    this.activateForm = RestInPlaceEditor.forms[this.formType].activateForm;
    this.getValue     = RestInPlaceEditor.forms[this.formType].getValue;
  },

  getValue : function() {
    alert("The form was not properly initialized. getValue is unbound");
  },

  /* Generate the data sent in the POST request */
  requestData : function() {
    //jq14: data as JS object, not string.
    var data = "_method=put";
    data += "&"+this.objectName+'['+this.attributeName+']='+encodeURIComponent(this.getValue());
    if (window.rails_authenticity_token) {
      data += "&authenticity_token="+encodeURIComponent(window.rails_authenticity_token);
    }
    return data;
  },

  ajax : function(options) {
    options.url = this.url;
    return jQuery.ajax(options);
  },

  // Handlers ////////////////////////////////////////////////////////////////

  loadSuccessCallback : function(data) {
    //jq14: data as JS object, not string.
    if (jQuery.fn.jquery < "1.4") data = eval('(' + data + ')' );
    this.element.html(data[this.objectName][this.attributeName]);
    this.element.bind('click', {editor: this}, this.clickHandler);
  },

  clickHandler : function(event) {
    event.data.editor.activate();
  }
};

RestInPlaceEditor.forms = {
  "input" : {
    /* is bound to the editor and called to replace the element's content with a form for editing data */
    activateForm : function() {
      this.element.html('<form action="javascript:void(0)" style="display:inline;"><input type="text" value="' + jQuery.trim(this.oldValue) + '"></form>');
      this.element.find('input')[0].select();
      this.element.find("form")
        .bind('submit', {editor: this}, RestInPlaceEditor.forms.input.submitHandler);
      this.element.find("input")
        .bind('blur',   {editor: this}, RestInPlaceEditor.forms.input.inputBlurHandler);
    },

    getValue :  function() {
      return this.element.find("input").val();
    },

    inputBlurHandler : function(event) {
      event.data.editor.abort();
    },

    submitHandler : function(event) {
      event.data.editor.update();
      return false;
    }
  },

  "textarea" : {
    /* is bound to the editor and called to replace the element's content with a form for editing data */
    activateForm : function() {
      this.element.html('<form action="javascript:void(0)" style="display:inline;"><textarea>' + jQuery.trim(this.oldValue) + '</textarea></form>');
      this.element.find('textarea')[0].select();
      this.element.find("textarea")
        .bind('blur', {editor: this}, RestInPlaceEditor.forms.textarea.blurHandler);
    },

    getValue :  function() {
      return this.element.find("textarea").val();
    },

    blurHandler : function(event) {
      event.data.editor.update();
    }

  }
};

jQuery.fn.rest_in_place = function() {
  this.each(function(){
    jQuery(this).data('restInPlaceEditor', new RestInPlaceEditor(this));
  })
  return this;
};<commit_msg>Add 'active' class for CSS styling when the form is active<commit_after>function RestInPlaceEditor(e) {
  this.element = jQuery(e);
  this.initOptions();
  this.bindForm();

  this.element.bind('click', {editor: this}, this.clickHandler);
}

RestInPlaceEditor.prototype = {
  // Public Interface Functions //////////////////////////////////////////////

  activate : function() {
    this.oldValue = this.element.html();
    this.element.addClass('active');
    this.element.unbind('click', this.clickHandler)
    this.activateForm();
  },

  abort : function() {
    this.element
      .html(this.oldValue)
      .removeClass('active')
      .bind('click', {editor: this}, this.clickHandler);
  },

  update : function() {
    var editor = this;
    editor.ajax({
      "type"       : "post",
      "data"       : editor.requestData(),
      "success"    : function(){
        editor.ajax({
          "dataType" : 'json',
          "success"  : function(data){ editor.loadSuccessCallback(data) }
        });
        editor.element.removeClass('active');
      }
    });
    editor.element.html("saving...");
  },

  activateForm : function() {
    alert("The form was not properly initialized. activateForm is unbound");
  },

  // Helper Functions ////////////////////////////////////////////////////////

  initOptions : function() {
    // Try parent supplied info
    var self = this;
    self.element.parents().each(function(){
      self.url           = self.url           || jQuery(this).attr("data-url");
      self.formType      = self.formType      || jQuery(this).attr("data-formtype");
      self.objectName    = self.objectName    || jQuery(this).attr("data-object");
      self.attributeName = self.attributeName || jQuery(this).attr("data-attribute");
    });
    // Try Rails-id based if parents did not explicitly supply something
    self.element.parents().each(function(){
      var res;
      if (res = this.id.match(/^(\w+)_(\d+)$/i)) {
        self.objectName = self.objectName || res[1];
      }
    });
    // Load own attributes (overrides all others)
    self.url           = self.element.attr("data-url")       || self.url      || document.location.pathname;
    self.formType      = self.element.attr("data-formtype")  || self.formtype || "input";
    self.objectName    = self.element.attr("data-object")    || self.objectName;
    self.attributeName = self.element.attr("data-attribute") || self.attributeName;
  },

  bindForm : function() {
    this.activateForm = RestInPlaceEditor.forms[this.formType].activateForm;
    this.getValue     = RestInPlaceEditor.forms[this.formType].getValue;
  },

  getValue : function() {
    alert("The form was not properly initialized. getValue is unbound");
  },

  /* Generate the data sent in the POST request */
  requestData : function() {
    //jq14: data as JS object, not string.
    var data = "_method=put";
    data += "&"+this.objectName+'['+this.attributeName+']='+encodeURIComponent(this.getValue());
    if (window.rails_authenticity_token) {
      data += "&authenticity_token="+encodeURIComponent(window.rails_authenticity_token);
    }
    return data;
  },

  ajax : function(options) {
    options.url = this.url;
    return jQuery.ajax(options);
  },

  // Handlers ////////////////////////////////////////////////////////////////

  loadSuccessCallback : function(data) {
    //jq14: data as JS object, not string.
    if (jQuery.fn.jquery < "1.4") data = eval('(' + data + ')' );
    this.element.html(data[this.objectName][this.attributeName]);
    this.element.bind('click', {editor: this}, this.clickHandler);
  },

  clickHandler : function(event) {
    event.data.editor.activate();
  }
};

RestInPlaceEditor.forms = {
  "input" : {
    /* is bound to the editor and called to replace the element's content with a form for editing data */
    activateForm : function() {
      this.element.html('<form action="javascript:void(0)" style="display:inline;"><input type="text" value="' + jQuery.trim(this.oldValue) + '"></form>');
      this.element.find('input')[0].select();
      this.element.find("form")
        .bind('submit', {editor: this}, RestInPlaceEditor.forms.input.submitHandler);
      this.element.find("input")
        .bind('blur',   {editor: this}, RestInPlaceEditor.forms.input.inputBlurHandler);
    },

    getValue :  function() {
      return this.element.find("input").val();
    },

    inputBlurHandler : function(event) {
      event.data.editor.abort();
    },

    submitHandler : function(event) {
      event.data.editor.update();
      return false;
    }
  },

  "textarea" : {
    /* is bound to the editor and called to replace the element's content with a form for editing data */
    activateForm : function() {
      this.element.html('<form action="javascript:void(0)" style="display:inline;"><textarea>' + jQuery.trim(this.oldValue) + '</textarea></form>');
      this.element.find('textarea')[0].select();
      this.element.find("textarea")
        .bind('blur', {editor: this}, RestInPlaceEditor.forms.textarea.blurHandler);
    },

    getValue :  function() {
      return this.element.find("textarea").val();
    },

    blurHandler : function(event) {
      event.data.editor.update();
    }

  }
};

jQuery.fn.rest_in_place = function() {
  this.each(function(){
    jQuery(this).data('restInPlaceEditor', new RestInPlaceEditor(this));
  })
  return this;
};<|endoftext|>