<commit_before>import GLContext from './GLContext';
import MutableTexture from '../textures/MutableTexture';
import GLExtensionsManager from './GLExtensionsManager';
import RenderPass from '../../middle_level/expressions/RenderPath';

let singleton = Symbol();
let singletonEnforcer = Symbol();

export default class GLBoostContext {
  constructor(enforcer) {
    if (enforcer !== singletonEnforcer) {
      throw new Error('This is a Singleton class. get the instance using \'getInstance\' static method.');
    }

    this._glBoostObjects = {};
  }

  static getInstance() {
    if (!this[singleton]) {
      this[singleton] = new GLBoostContext(singletonEnforcer);
    }
    return this[singleton];
  }

  registerGLBoostObject(glBoostObject) {
    this._glBoostObjects[glBoostObject.toString()] = glBoostObject;
  }

  printGLBoostObjects() {
    var objects = this._glBoostObjects;
    console.log('========== GLBoost Object Lists [begin] ==========');
    for (var key in objects) {
      if (objects.hasOwnProperty(key)) {
        console.log(key);
      }
    }
    console.log('========== GLBoost Object Lists [end] ==========');
  }

  /**
   * en: create textures as render target. (and attach it to framebuffer object internally.)

   * ja:レンダーターゲットとしてテクスチャを作成します（内部的にframebuffer objectにアタッチされます）。
   * @param {number} width en: width of texture. ja: テクスチャの幅
   * @param {number} height en: height of texture. ja: テクスチャの高さ
   * @param {number} textureNum en: the number of creation. ja:テクスチャを作る個数
   * @param {HTMLCanvas|string} canvas [en] canvas or canvas' id string. [ja] canvasまたはcanvasのid文字列
   * @returns {Array} en: an array of created textures. ja:作成されたテクスチャの配列
   */
  createTexturesForRenderTarget(width, height, textureNum, canvas = GLBoost.CURRENT_CANVAS_ID) {
    this._glContext = GLContext.getInstance(canvas);
    var gl = this._glContext.gl;

    var glem = GLExtensionsManager.getInstance(this._glContext);

    // Create FBO
    var fbo = this._glContext.createFramebuffer(GLBoostContext.name);
    gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
    fbo.width = width ? width : canvas.width;
    fbo.height = height ? height : canvas.height;

    var renderTargetTextures = [];
    for(let i=0; i<textureNum; i++) {
      let texture = new MutableTexture(fbo.width, fbo.height);
      texture.fbo = fbo;
      renderTargetTextures.push(texture);
    }

    // Create RenderBuffer
    var renderbuffer = this._glContext.createRenderbuffer(GLBoostContext.name);
    gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
    gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, fbo.width, fbo.height);

    // Attach Buffers
    renderTargetTextures.forEach((texture, i)=>{
      var glTexture = texture.glTextureResource;
      var attachimentId = glem.colorAttachiment(gl, i);
      texture.colorAttachiment = attachimentId;
      gl.framebufferTexture2D(gl.FRAMEBUFFER, attachimentId, gl.TEXTURE_2D, glTexture, 0);
    });
    gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbuffer);

    gl.bindRenderbuffer(gl.RENDERBUFFER, null);
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);

    return renderTargetTextures;
  }

  createDepthTexturesForRenderTarget(width, height, canvas = GLBoost.CURRENT_CANVAS_ID) {
    this._glContext = GLContext.getInstance(canvas);
    var gl = this._glContext.gl;

    var glem = GLExtensionsManager.getInstance(this._glContext);

    // Create FBO
    var fbo = this._glContext.createFramebuffer(GLBoostContext.name);
    gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
    fbo.width = width ? width : canvas.width;
    fbo.height = height ? height : canvas.height;

    let depthTexture = new MutableTexture(fbo.width, fbo.height, canvas);
    depthTexture.fbo = fbo;

    // Attach Buffers
    var glTexture = depthTexture.glTextureResource;
    var attachimentId = gl.DEPTH_ATTACHMENT;
    depthTexture.colorAttachment = attachimentId;
    gl.framebufferTexture2D(gl.FRAMEBUFFER, attachimentId, gl.TEXTURE_2D, glTexture, 0);

    gl.bindFramebuffer(gl.FRAMEBUFFER, null);

    return depthTexture;
  }

  createRenderPasses(number, canvas = GLBoost.CURRENT_CANVAS_ID) {
    this._glContext = GLContext.getInstance(canvas);

    var renderPasses = [];
    for (let i=0; i<number; i++) {
      renderPasses.push(new RenderPass(this._glContext.gl));
    }

    return renderPasses;
  }
}

GLBoost['GLBoostContext'] = GLBoostContext;
<commit_msg>Fix misspelled words.<commit_after>import GLContext from './GLContext';
import MutableTexture from '../textures/MutableTexture';
import GLExtensionsManager from './GLExtensionsManager';
import RenderPath from '../../middle_level/expressions/RenderPath';

let singleton = Symbol();
let singletonEnforcer = Symbol();

export default class GLBoostContext {
  constructor(enforcer) {
    if (enforcer !== singletonEnforcer) {
      throw new Error('This is a Singleton class. get the instance using \'getInstance\' static method.');
    }

    this._glBoostObjects = {};
  }

  static getInstance() {
    if (!this[singleton]) {
      this[singleton] = new GLBoostContext(singletonEnforcer);
    }
    return this[singleton];
  }

  registerGLBoostObject(glBoostObject) {
    this._glBoostObjects[glBoostObject.toString()] = glBoostObject;
  }

  printGLBoostObjects() {
    var objects = this._glBoostObjects;
    console.log('========== GLBoost Object Lists [begin] ==========');
    for (var key in objects) {
      if (objects.hasOwnProperty(key)) {
        console.log(key);
      }
    }
    console.log('========== GLBoost Object Lists [end] ==========');
  }

  /**
   * en: create textures as render target. (and attach it to framebuffer object internally.)

   * ja:レンダーターゲットとしてテクスチャを作成します（内部的にframebuffer objectにアタッチされます）。
   * @param {number} width en: width of texture. ja: テクスチャの幅
   * @param {number} height en: height of texture. ja: テクスチャの高さ
   * @param {number} textureNum en: the number of creation. ja:テクスチャを作る個数
   * @param {HTMLCanvas|string} canvas [en] canvas or canvas' id string. [ja] canvasまたはcanvasのid文字列
   * @returns {Array} en: an array of created textures. ja:作成されたテクスチャの配列
   */
  createTexturesForRenderTarget(width, height, textureNum, canvas = GLBoost.CURRENT_CANVAS_ID) {
    this._glContext = GLContext.getInstance(canvas);
    var gl = this._glContext.gl;

    var glem = GLExtensionsManager.getInstance(this._glContext);

    // Create FBO
    var fbo = this._glContext.createFramebuffer(GLBoostContext.name);
    gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
    fbo.width = width ? width : canvas.width;
    fbo.height = height ? height : canvas.height;

    var renderTargetTextures = [];
    for(let i=0; i<textureNum; i++) {
      let texture = new MutableTexture(fbo.width, fbo.height);
      texture.fbo = fbo;
      renderTargetTextures.push(texture);
    }

    // Create RenderBuffer
    var renderbuffer = this._glContext.createRenderbuffer(GLBoostContext.name);
    gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
    gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, fbo.width, fbo.height);

    // Attach Buffers
    renderTargetTextures.forEach((texture, i)=>{
      var glTexture = texture.glTextureResource;
      var attachimentId = glem.colorAttachiment(gl, i);
      texture.colorAttachiment = attachimentId;
      gl.framebufferTexture2D(gl.FRAMEBUFFER, attachimentId, gl.TEXTURE_2D, glTexture, 0);
    });
    gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbuffer);

    gl.bindRenderbuffer(gl.RENDERBUFFER, null);
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);

    return renderTargetTextures;
  }

  createDepthTexturesForRenderTarget(width, height, canvas = GLBoost.CURRENT_CANVAS_ID) {
    this._glContext = GLContext.getInstance(canvas);
    var gl = this._glContext.gl;

    var glem = GLExtensionsManager.getInstance(this._glContext);

    // Create FBO
    var fbo = this._glContext.createFramebuffer(GLBoostContext.name);
    gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
    fbo.width = width ? width : canvas.width;
    fbo.height = height ? height : canvas.height;

    let depthTexture = new MutableTexture(fbo.width, fbo.height, canvas);
    depthTexture.fbo = fbo;

    // Attach Buffers
    var glTexture = depthTexture.glTextureResource;
    var attachimentId = gl.DEPTH_ATTACHMENT;
    depthTexture.colorAttachment = attachimentId;
    gl.framebufferTexture2D(gl.FRAMEBUFFER, attachimentId, gl.TEXTURE_2D, glTexture, 0);

    gl.bindFramebuffer(gl.FRAMEBUFFER, null);

    return depthTexture;
  }

  createRenderPasses(number, canvas = GLBoost.CURRENT_CANVAS_ID) {
    this._glContext = GLContext.getInstance(canvas);

    var renderPaths = [];
    for (let i=0; i<number; i++) {
      renderPaths.push(new RenderPath(this._glContext.gl));
    }

    return renderPaths;
  }
}

GLBoost['GLBoostContext'] = GLBoostContext;
<|endoftext|>


<commit_before>var ExtractTextPlugin = require("extract-text-webpack-plugin");
var CleanCSSPlugin = require("less-plugin-clean-css");
var AutoprefixPlugin = require("less-plugin-autoprefix");
var path = require('path');

/*
 * Capitalize drive letter on windows as workaround for
 * webpack bug.
 * https://github.com/webpack/webpack/issues/4530
 */
var outputPath = path.resolve(__dirname, 'src/');
outputPath = outputPath.charAt(0).toUpperCase() + outputPath.slice(1);

module.exports = {
    entry: [
        "./src/js/main.ts",
        "./src/style.less"
    ],
    output: {
        path: outputPath,
        filename: "main-build.js"
    },
    resolve: {
        extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
    },
    plugins: [
        new ExtractTextPlugin("style.css")
    ],
    module: {
        loaders: [
            { test: /\.tsx?$/, loader: "ts-loader" },
            {
                test: /\.css$/,
                loader: ExtractTextPlugin.extract({ use: 'css-loader' })
            },
            {
                test: /\.less$/,
                loader: ExtractTextPlugin.extract({
                    use: [
                        {
                            loader: "css-loader",
                            options: { url: false }
                        },
                        {
                            loader: "less-loader",
                            options: {
                                plugins: [
                                    new CleanCSSPlugin({advanced: true}),
                                    new AutoprefixPlugin()
                                ]
                            }
                        }
                    ]
                })
            }
        ]
    }
};
<commit_msg>* added inline less plugin to rewrite ../node_modules path to vendor-assets/<commit_after>var ExtractTextPlugin = require("extract-text-webpack-plugin");
var CleanCSSPlugin = require("less-plugin-clean-css");
var AutoprefixPlugin = require("less-plugin-autoprefix");
var path = require('path');

/*
 * Capitalize drive letter on windows as workaround for
 * webpack bug.
 * https://github.com/webpack/webpack/issues/4530
 */
var outputPath = path.resolve(__dirname, 'src/');
outputPath = outputPath.charAt(0).toUpperCase() + outputPath.slice(1);

module.exports = {
    entry: [
        "./src/js/main.ts",
        "./src/style.less"
    ],
    output: {
        path: outputPath,
        filename: "main-build.js"
    },
    resolve: {
        extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
    },
    plugins: [
        new ExtractTextPlugin("style.css")
    ],
    module: {
        loaders: [
            { test: /\.tsx?$/, loader: "ts-loader" },
            {
                test: /\.css$/,
                loader: ExtractTextPlugin.extract({ use: 'css-loader' })
            },
            {
                test: /\.less$/,
                loader: ExtractTextPlugin.extract({
                    use: [
                        {
                            loader: "css-loader",
                            options: { url: false }
                        },
                        {
                            loader: "less-loader",
                            options: {
                                plugins: [
                                    {
                                        // inline less plugin to rewrite ../node_modules directory, which
                                        // is not in theme path, to vendor-assets/ this is meant to be
                                        // used in combination with copy-webpack-plugin
                                        install: function(less, pluginManager) {
                                            pluginManager.addPostProcessor({
                                                process: function(css) {
                                                    return css.replace(/\.\.\/node_modules\//g, 'vendor-assets/');
                                                }
                                            });
                                        }
                                    },
                                    new CleanCSSPlugin({advanced: true}),
                                    new AutoprefixPlugin()
                                ]
                            }
                        }
                    ]
                })
            }
        ]
    }
};
<|endoftext|>


<commit_before>//TODO remove class valid/noValid

$(document).ready(function(){

  //variables
  var nom = $("#nom");
  var cognom = $("#cognom");
  var email = $("#email");
  var telefon = $("#telf");

  $(function() {
    $( "#datepicker" ).datepicker(
    {
      dateFormat: "dd-mm-yy"
    });

  });

   //Comprova si el NOM es correcte
   nom.on("blur",function(){
    var $this = $(this);
    var regex = /^[A-Za-z]{2,20}$/;
    var valor = $this.val();

    var errPara = document.createElement("p");
    var errText = document.createTextNode("Mínim 2 caràcters i màxim 20 caràcters");
    errPara.appendChild(errText);

    if(!regex.test(valor)){
      $this.addClass("noValid");
      var divErr = document.getElementById("errNom");
      if (divErr.firstChild) {
        divErr.removeChild(divErr.lastChild);
      }
      divErr.appendChild(errPara);

      if ($this.hasClass("valid")) {
        $this.removeClass("valid");
      };
    } else{
      $this.addClass("valid");

      var divErr = document.getElementById("errNom");
      divErr.removeChild(divErr.lastChild);

      if ($this.hasClass("noValid")) {
        $this.removeClass("noValid");
      };
    }
  });

   //Comprova si el COGNOM es correcte
   cognom.on("blur",function(){
    var $this = $(this);
    var regex = /^[A-Z a-z]{3,20}$/;
    var valor = $this.val();

    var errPara = document.createElement("p");
    var errText = document.createTextNode("Mínim 3 caràcters i màxim 30 caràcters");
    errPara.appendChild(errText);

    if(!regex.test(valor)){
      $this.addClass("noValid");
      var divErr = document.getElementById("errCognom");
      if (divErr.firstChild) {
        divErr.removeChild(divErr.lastChild);
      }
      divErr.appendChild(errPara);

      if ($this.hasClass("valid")) {
        $this.removeClass("valid");
      };
    } else{
      $this.addClass("valid");

      var divErr = document.getElementById("errCognom");
      divErr.removeChild(divErr.lastChild);

      if ($this.hasClass("noValid")) {
        $this.removeClass("noValid");
      };
    }
  });

    //Comprova si l'EMAIL es valid
    email.on("blur",function(){
      var $this = $(this);
      var regex = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
      var valor = $this.val();

      var errPara = document.createElement("p");
      var errText = document.createTextNode("Introdueix un correu vàlid 'exemple@exemple.com'");
      errPara.appendChild(errText);

      if(!regex.test(valor)){
        $this.addClass("noValid");
        var divErr = document.getElementById("errMail");
        if (divErr.firstChild) {
          divErr.removeChild(divErr.lastChild);
        }
        divErr.appendChild(errPara);

        if ($this.hasClass("valid")) {
          $this.removeClass("valid");
        };
      } else{
        $this.addClass("valid");

        var divErr = document.getElementById("errMail");
        divErr.removeChild(divErr.lastChild);

        if ($this.hasClass("noValid")) {
          $this.removeClass("noValid");
        };
      }
    });

    telefon.on("blur",function(){
      var $this = $(this);
      var regex = /(\+376[0-9]{6})$/i;
      var valor = $this.val();

      var errPara = document.createElement("p");
      var errText = document.createTextNode("Introdueix un telèfon de 6 números.");
      errPara.appendChild(errText);

      if(!regex.test(valor)){
        $this.addClass("noValid");
        var divErr = document.getElementById("errTelf");
        if (divErr.firstChild) {
          divErr.removeChild(divErr.lastChild);
        }
        divErr.appendChild(errPara);

        if ($this.hasClass("valid")) {
          $this.removeClass("valid");
        };
      } else{
        $this.addClass("valid");

        var divErr = document.getElementById("errTelf");
        divErr.removeChild(divErr.lastChild);

        if ($this.hasClass("noValid")) {
          $this.removeClass("noValid");
        };
      }
    });

    //show modal when inputs are valid and button
    //is clicked
    // $(".submit").on("click",function(){
    //   if(name.val() !== "Name" && name.val() !== "" &&
    //    email.val() !== "Email" &&
    //    email.val() !== "" &&
    //    comment.val() !== "Comments" &&
    //    comment.val()!== ""){

    //       //remove invalid/valid classes
    //     name.removeClass().addClass("input");
    //     email.removeClass().addClass("input");
    //     comment.removeClass().addClass("input");

    //       //modal box
    //       modal_name.text(name.val());
    //       modal.slideDown("medium")
    //       .delay(2000).slideUp("fast");

    //       //put default text back
    //       name.val("Name");
    //       email.val("Email");
    //       comment.val("Comments");

    //       return false;

    //     } else{

    //       return false; }
    //     });

});
<commit_msg>- Afegit validació de Banc (andorra) i detecció de Crèdit o AndBank<commit_after>//TODO remove class valid/noValid

$(document).ready(function(){

  //variables
  var nom = $("#nom");
  var cognom = $("#cognom");
  var email = $("#email");
  var telefon = $("#telf");
  var banc = $("#banc");

  $(function() {
    $( "#datepicker" ).datepicker(
    {
      dateFormat: "dd-mm-yy"
    });

  });

   //Comprova si el NOM es correcte
   nom.on("blur",function(){
    var $this = $(this);
    var regex = /^[A-Za-z]{2,20}$/;
    var valor = $this.val();

    var errPara = document.createElement("p");
    var errText = document.createTextNode("Mínim 2 caràcters i màxim 20 caràcters");
    errPara.appendChild(errText);

    if(!regex.test(valor)){
      $this.addClass("noValid");
      var divErr = document.getElementById("errNom");
      if (divErr.firstChild) {
        divErr.removeChild(divErr.lastChild);
      }
      divErr.appendChild(errPara);

      if ($this.hasClass("valid")) {
        $this.removeClass("valid");
      };
    } else{
      $this.addClass("valid");

      var divErr = document.getElementById("errNom");
      divErr.removeChild(divErr.lastChild);

      if ($this.hasClass("noValid")) {
        $this.removeClass("noValid");
      };
    }
  });

   //Comprova si el COGNOM es correcte
   cognom.on("blur",function(){
    var $this = $(this);
    var regex = /^[A-Z a-z]{3,20}$/;
    var valor = $this.val();

    var errPara = document.createElement("p");
    var errText = document.createTextNode("Mínim 3 caràcters i màxim 30 caràcters");
    errPara.appendChild(errText);

    if(!regex.test(valor)){
      $this.addClass("noValid");
      var divErr = document.getElementById("errCognom");
      if (divErr.firstChild) {
        divErr.removeChild(divErr.lastChild);
      }
      divErr.appendChild(errPara);

      if ($this.hasClass("valid")) {
        $this.removeClass("valid");
      };
    } else{
      $this.addClass("valid");

      var divErr = document.getElementById("errCognom");
      divErr.removeChild(divErr.lastChild);

      if ($this.hasClass("noValid")) {
        $this.removeClass("noValid");
      };
    }
  });

    //Comprova si l'EMAIL es valid
    email.on("blur",function(){
      var $this = $(this);
      var regex = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
      var valor = $this.val();

      var errPara = document.createElement("p");
      var errText = document.createTextNode("Introdueix un correu vàlid 'exemple@exemple.com'");
      errPara.appendChild(errText);

      if(!regex.test(valor)){
        $this.addClass("noValid");
        var divErr = document.getElementById("errMail");
        if (divErr.firstChild) {
          divErr.removeChild(divErr.lastChild);
        }
        divErr.appendChild(errPara);

        if ($this.hasClass("valid")) {
          $this.removeClass("valid");
        };
      } else{
        $this.addClass("valid");

        var divErr = document.getElementById("errMail");
        divErr.removeChild(divErr.lastChild);

        if ($this.hasClass("noValid")) {
          $this.removeClass("noValid");
        };
      }
    });

    telefon.on("blur",function(){
      var $this = $(this);
      var regex = /(\+376[0-9]{6})$/i;
      var valor = $this.val();

      var errPara = document.createElement("p");
      var errText = document.createTextNode("Introdueix un telèfon de 6 números.");
      errPara.appendChild(errText);

      if(!regex.test(valor)){
        $this.addClass("noValid");
        var divErr = document.getElementById("errTelf");
        if (divErr.firstChild) {
          divErr.removeChild(divErr.lastChild);
        }
        divErr.appendChild(errPara);

        if ($this.hasClass("valid")) {
          $this.removeClass("valid");
        };
      } else{
        $this.addClass("valid");

        var divErr = document.getElementById("errTelf");
        divErr.removeChild(divErr.lastChild);

        if ($this.hasClass("noValid")) {
          $this.removeClass("noValid");
        };
      }
    });

    banc.on("blur",function(){
      var $this = $(this);
      var regex = /AD[0-9]{2}000(1|3)[0-9]{16}/i;
      var regAndBank = /AD[0-9]{2}0001[0-9]{16}/i;
      var regCredit = /AD[0-9]{2}0003[0-9]{16}/i;

      var bankPara = document.createElement("p");
      var andBank = document.createTextNode("AndBank");
      var credit = document.createTextNode("Crèdit Andorrà");
      var valor = $this.val();

      var errPara = document.createElement("p");
      var errText = document.createTextNode("Introdueix un IBAN vàlid (ADCC BBBB SSSS ZZZZ ZZZZ ZZZZ).");
      errPara.appendChild(errText);

      if(!regex.test(valor)){
        $this.addClass("noValid");
        var divErr = document.getElementById("errBanc");
        if (divErr.firstChild) {
          divErr.removeChild(divErr.lastChild);
        }
        divErr.appendChild(errPara);

        if ($this.hasClass("valid")) {
          $this.removeClass("valid");
        };
      } else{
        $this.addClass("valid");
        var divErr = document.getElementById("errBanc");
        divErr.removeChild(divErr.lastChild);

        if(regAndBank.test(valor)){
          bankPara.appendChild(andBank);
          divErr.appendChild(bankPara);
        }
        if(regCredit.test(valor)){
          bankPara.appendChild(credit);
          divErr.appendChild(bankPara);
        }

        if ($this.hasClass("noValid")) {
          $this.removeClass("noValid");
        };
      }
    });

    //show modal when inputs are valid and button
    //is clicked
    // $(".submit").on("click",function(){
    //   if(name.val() !== "Name" && name.val() !== "" &&
    //    email.val() !== "Email" &&
    //    email.val() !== "" &&
    //    comment.val() !== "Comments" &&
    //    comment.val()!== ""){

    //       //remove invalid/valid classes
    //     name.removeClass().addClass("input");
    //     email.removeClass().addClass("input");
    //     comment.removeClass().addClass("input");

    //       //modal box
    //       modal_name.text(name.val());
    //       modal.slideDown("medium")
    //       .delay(2000).slideUp("fast");

    //       //put default text back
    //       name.val("Name");
    //       email.val("Email");
    //       comment.val("Comments");

    //       return false;

    //     } else{

    //       return false; }
    //     });

});
<|endoftext|>


<commit_before>import React from 'react';
import classnames from 'classnames';
import { themr } from 'react-css-themr';
import { INPUT } from '../identifiers.js';
import InjectedFontIcon from '../font_icon/FontIcon.js';

const factory = (FontIcon) => {
  class Input extends React.Component {
    static propTypes = {
      children: React.PropTypes.any,
      className: React.PropTypes.string,
      disabled: React.PropTypes.bool,
      error: React.PropTypes.string,
      floating: React.PropTypes.bool,
      hint: React.PropTypes.string,
      icon: React.PropTypes.oneOfType([
        React.PropTypes.string,
        React.PropTypes.element
      ]),
      label: React.PropTypes.string,
      maxLength: React.PropTypes.number,
      multiline: React.PropTypes.bool,
      name: React.PropTypes.string,
      onBlur: React.PropTypes.func,
      onChange: React.PropTypes.func,
      onFocus: React.PropTypes.func,
      onKeyPress: React.PropTypes.func,
      required: React.PropTypes.bool,
      theme: React.PropTypes.shape({
        bar: React.PropTypes.string,
        counter: React.PropTypes.string,
        disabled: React.PropTypes.string,
        error: React.PropTypes.string,
        errored: React.PropTypes.string,
        hidden: React.PropTypes.string,
        hint: React.PropTypes.string,
        icon: React.PropTypes.string,
        input: React.PropTypes.string,
        inputElement: React.PropTypes.string,
        required: React.PropTypes.string,
        withIcon: React.PropTypes.string
      }),
      type: React.PropTypes.string,
      value: React.PropTypes.any
    };

    static defaultProps = {
      className: '',
      hint: '',
      disabled: false,
      floating: true,
      multiline: false,
      required: false,
      type: 'text'
    };

    componentDidMount () {
      if (this.props.multiline) {
        window.addEventListener('resize', this.handleAutoresize);
        this.handleAutoresize();
      }
    }

    componentWillReceiveProps (nextProps) {
      if (!this.props.multiline && nextProps.multiline) {
        window.addEventListener('resize', this.handleAutoresize);
      } else if (this.props.multiline && !nextProps.multiline) {
        window.removeEventListener('resize', this.handleAutoresize);
      }
    }

    componentDidUpdate () {
      // resize the textarea, if nessesary
      if (this.props.multiline) this.handleAutoresize();
    }

    componentWillUnmount () {
      if (this.props.multiline) window.removeEventListener('resize', this.handleAutoresize);
    }

    handleChange = (event) => {
      const { onChange, multiline, maxLength } = this.props;
      const valueFromEvent = event.target.value;

      // Trim value to maxLength if that exists (only on multiline inputs).
      // Note that this is still required even tho we have the onKeyPress filter
      // because the user could paste smt in the textarea.
      const haveToTrim = (multiline && maxLength && event.target.value.length > maxLength);
      const value = haveToTrim ? valueFromEvent.substr(0, maxLength) : valueFromEvent;

      // propagate to to store and therefore to the input
      if (onChange) onChange(value, event);
    };

    handleAutoresize = () => {
      const element = this.refs.input;
      // compute the height difference between inner height and outer height
      const style = getComputedStyle(element, null);
      const heightOffset = style.boxSizing === 'content-box'
        ? -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom))
        : parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);

      // resize the input to its content size
      element.style.height = 'auto';
      element.style.height = `${element.scrollHeight + heightOffset}px`;
    }

    blur () {
      this.refs.input.blur();
    }

    focus () {
      this.refs.input.focus();
    }

    onKeyPress = (event) => {
      // prevent insertion of more characters if we're a multiline input
      // and maxLength exists
      const { multiline, maxLength, onKeyPress } = this.props;
      if (multiline && maxLength) {
        // check if smt is selected, in which case the newly added charcter would
        // replace the selected characters, so the length of value doesn't actually
        // increase.
        const isReplacing = event.target.selectionEnd - event.target.selectionStart;
        const value = event.target.value;

        if (!isReplacing && value.length === maxLength) {
          event.preventDefault();
          event.stopPropagation();
          return;
        }
      }

      if (onKeyPress) onKeyPress(event);
    }

    render () {
      const { children, disabled, error, floating, hint, icon,
              name, label: labelText, maxLength, multiline, required,
              theme, type, value, onKeyPress, ...others} = this.props;
      const length = maxLength && value ? value.length : 0;
      const labelClassName = classnames(theme.label, {[theme.fixed]: !floating});

      const className = classnames(theme.input, {
        [theme.disabled]: disabled,
        [theme.errored]: error,
        [theme.hidden]: type === 'hidden',
        [theme.withIcon]: icon
      }, this.props.className);

      const valuePresent = value !== null
        && value !== undefined
        && value !== ''
        && !(typeof value === Number && isNaN(value));

      const inputElementProps = {
        ...others,
        className: classnames(theme.inputElement, {[theme.filled]: valuePresent}),
        onChange: this.handleChange,
        ref: 'input',
        role: 'input',
        name,
        disabled,
        required,
        type,
        value
      };
      if (!multiline) {
        inputElementProps.maxLength = maxLength;
        inputElementProps.onKeyPress = onKeyPress;
      } else {
        inputElementProps.rows = 1;
        inputElementProps.onKeyPress = this.onKeyPress;
      }

      const InputElement = React.createElement(multiline ? 'textarea' : 'input', inputElementProps);

      return (

          {InputElement}
          {icon ? <FontIcon className={theme.icon} value={icon} /> : null}

          {labelText
            ?
                {labelText}
                {required ?  *  : null}

            : null}
          {hint ? {hint} : null}
          {error ? {error} : null}
          {maxLength ? {length}/{maxLength} : null}
          {children}

      );
    }
  }

  return Input;
};

const Input = factory(InjectedFontIcon);
export default themr(INPUT, null, { withRef: true })(Input);
export { factory as inputFactory };
export { Input };
<commit_msg>Change method name to match lib convention<commit_after>import React from 'react';
import classnames from 'classnames';
import { themr } from 'react-css-themr';
import { INPUT } from '../identifiers.js';
import InjectedFontIcon from '../font_icon/FontIcon.js';

const factory = (FontIcon) => {
  class Input extends React.Component {
    static propTypes = {
      children: React.PropTypes.any,
      className: React.PropTypes.string,
      disabled: React.PropTypes.bool,
      error: React.PropTypes.string,
      floating: React.PropTypes.bool,
      hint: React.PropTypes.string,
      icon: React.PropTypes.oneOfType([
        React.PropTypes.string,
        React.PropTypes.element
      ]),
      label: React.PropTypes.string,
      maxLength: React.PropTypes.number,
      multiline: React.PropTypes.bool,
      name: React.PropTypes.string,
      onBlur: React.PropTypes.func,
      onChange: React.PropTypes.func,
      onFocus: React.PropTypes.func,
      onKeyPress: React.PropTypes.func,
      required: React.PropTypes.bool,
      theme: React.PropTypes.shape({
        bar: React.PropTypes.string,
        counter: React.PropTypes.string,
        disabled: React.PropTypes.string,
        error: React.PropTypes.string,
        errored: React.PropTypes.string,
        hidden: React.PropTypes.string,
        hint: React.PropTypes.string,
        icon: React.PropTypes.string,
        input: React.PropTypes.string,
        inputElement: React.PropTypes.string,
        required: React.PropTypes.string,
        withIcon: React.PropTypes.string
      }),
      type: React.PropTypes.string,
      value: React.PropTypes.any
    };

    static defaultProps = {
      className: '',
      hint: '',
      disabled: false,
      floating: true,
      multiline: false,
      required: false,
      type: 'text'
    };

    componentDidMount () {
      if (this.props.multiline) {
        window.addEventListener('resize', this.handleAutoresize);
        this.handleAutoresize();
      }
    }

    componentWillReceiveProps (nextProps) {
      if (!this.props.multiline && nextProps.multiline) {
        window.addEventListener('resize', this.handleAutoresize);
      } else if (this.props.multiline && !nextProps.multiline) {
        window.removeEventListener('resize', this.handleAutoresize);
      }
    }

    componentDidUpdate () {
      // resize the textarea, if nessesary
      if (this.props.multiline) this.handleAutoresize();
    }

    componentWillUnmount () {
      if (this.props.multiline) window.removeEventListener('resize', this.handleAutoresize);
    }

    handleChange = (event) => {
      const { onChange, multiline, maxLength } = this.props;
      const valueFromEvent = event.target.value;

      // Trim value to maxLength if that exists (only on multiline inputs).
      // Note that this is still required even tho we have the onKeyPress filter
      // because the user could paste smt in the textarea.
      const haveToTrim = (multiline && maxLength && event.target.value.length > maxLength);
      const value = haveToTrim ? valueFromEvent.substr(0, maxLength) : valueFromEvent;

      // propagate to to store and therefore to the input
      if (onChange) onChange(value, event);
    };

    handleAutoresize = () => {
      const element = this.refs.input;
      // compute the height difference between inner height and outer height
      const style = getComputedStyle(element, null);
      const heightOffset = style.boxSizing === 'content-box'
        ? -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom))
        : parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);

      // resize the input to its content size
      element.style.height = 'auto';
      element.style.height = `${element.scrollHeight + heightOffset}px`;
    }

    handleKeyPress = (event) => {
      // prevent insertion of more characters if we're a multiline input
      // and maxLength exists
      const { multiline, maxLength, onKeyPress } = this.props;
      if (multiline && maxLength) {
        // check if smt is selected, in which case the newly added charcter would
        // replace the selected characters, so the length of value doesn't actually
        // increase.
        const isReplacing = event.target.selectionEnd - event.target.selectionStart;
        const value = event.target.value;

        if (!isReplacing && value.length === maxLength) {
          event.preventDefault();
          event.stopPropagation();
          return;
        }
      }

      if (onKeyPress) onKeyPress(event);
    };

    blur () {
      this.refs.input.blur();
    }

    focus () {
      this.refs.input.focus();
    }

    render () {
      const { children, disabled, error, floating, hint, icon,
              name, label: labelText, maxLength, multiline, required,
              theme, type, value, onKeyPress, ...others} = this.props;
      const length = maxLength && value ? value.length : 0;
      const labelClassName = classnames(theme.label, {[theme.fixed]: !floating});

      const className = classnames(theme.input, {
        [theme.disabled]: disabled,
        [theme.errored]: error,
        [theme.hidden]: type === 'hidden',
        [theme.withIcon]: icon
      }, this.props.className);

      const valuePresent = value !== null
        && value !== undefined
        && value !== ''
        && !(typeof value === Number && isNaN(value));

      const inputElementProps = {
        ...others,
        className: classnames(theme.inputElement, {[theme.filled]: valuePresent}),
        onChange: this.handleChange,
        ref: 'input',
        role: 'input',
        name,
        disabled,
        required,
        type,
        value
      };
      if (!multiline) {
        inputElementProps.maxLength = maxLength;
        inputElementProps.onKeyPress = onKeyPress;
      } else {
        inputElementProps.rows = 1;
        inputElementProps.onKeyPress = this.handleKeyPress;
      }

      return (

          {React.createElement(multiline ? 'textarea' : 'input', inputElementProps)}
          {icon ? <FontIcon className={theme.icon} value={icon} /> : null}

          {labelText
            ?
                {labelText}
                {required ?  *  : null}

            : null}
          {hint ? {hint} : null}
          {error ? {error} : null}
          {maxLength ? {length}/{maxLength} : null}
          {children}

      );
    }
  }

  return Input;
};

const Input = factory(InjectedFontIcon);
export default themr(INPUT, null, { withRef: true })(Input);
export { factory as inputFactory };
export { Input };
<|endoftext|>


<commit_before>'use strict';

var mongoose = require('mongoose'),
    fmt = require('fmt'),
    _ = require('lodash'),
    Broker = require('./schema').Broker;

// Find Broker by id
exports.broker = function(req, res, next, id) {
    Broker.load(id, function(err, broker) {
        if (err) return next(err);
        if (!broker) return next(new Error('Failed to load Broker: ' + id));
        req.broker = broker;
        next();
    });
};

//List all Broker
exports.all = function(req, res) {
    var opts = [{
        path: 'creator',
        select: 'name'
    }];
    Broker
        .find()
        .sort('-created')
        .populate(opts)
        .exec(function(err, brokers) {
            if (!err) {
                res.jsonp(brokers);
            } else {
                return res.send(err);
            }
        });
};

//List active Broker
exports.active = function(req, res) {
    var opts = [{
        path: 'creator',
        select: 'name'
    }];
    Broker
        .find()
        .where('status').equals('active')
        .sort('-created')
        .populate(opts)
        .exec(function(err, brokers) {
            if (!err) {
                res.jsonp(brokers);
            } else {
                return res.send(err);
            }
        });
};

//Show Broker
exports.show = function(req, res) {
    res.jsonp(req.broker);
};

//Update Broker
exports.update = function(req, res) {
    var updateBroker = req.broker;
    updateBroker = _.extend(updateBroker, req.body);

    updateBroker.save(function(err) {
        if (err) {
            return res.send('login', {
                errors: err.errors,
                updateBroker: updateBroker
            });
        } else {
            res.jsonp(updateBroker);
        }
    });
};
// Create Broker
exports.create = function(req, res) {
    var request = req.body;
    var newBroker = new Broker(request);
    var validFrom = request.valid_from;
    var validTo = request.valid_to;
    newBroker.creator = req.user;
    if(validFrom){
        newBroker.valid_from = new Date(req.body.valid_from);
    }
    if(validTo){
        newBroker.valid_to = new Date(req.body.valid_to);
    }
    newBroker.save(function(err) {
        if (!err) {
            res.jsonp(newBroker);
        } else {
            return res.send(err);
        }
    });
};

<commit_msg>fixed lint issues<commit_after>'use strict';

var mongoose = require('mongoose'),
    fmt = require('fmt'),
    _ = require('lodash'),
    Broker = require('./schema').Broker;

// Find Broker by id
exports.broker = function(req, res, next, id) {
    Broker.load(id, function(err, broker) {
        if (err) return next(err);
        if (!broker) return next(new Error('Failed to load Broker: ' + id));
        req.broker = broker;
        next();
    });
};

//List all Broker
exports.all = function(req, res) {
    var opts = [{
        path: 'creator',
        select: 'name'
    }];
    Broker
        .find()
        .sort('-created')
        .populate(opts)
        .exec(function(err, brokers) {
            if (!err) {
                res.jsonp(brokers);
            } else {
                return res.send(err);
            }
        });
};

//List active Broker
exports.active = function(req, res) {
    var opts = [{
        path: 'creator',
        select: 'name'
    }];
    Broker
        .find()
        .where('status').equals('active')
        .sort('-created')
        .populate(opts)
        .exec(function(err, brokers) {
            if (!err) {
                res.jsonp(brokers);
            } else {
                return res.send(err);
            }
        });
};

//Show Broker
exports.show = function(req, res) {
    res.jsonp(req.broker);
};

//Update Broker
exports.update = function(req, res) {
    var updateBroker = req.broker;
    updateBroker = _.extend(updateBroker, req.body);

    updateBroker.save(function(err) {
        if (err) {
            return res.send('login', {
                errors: err.errors,
                updateBroker: updateBroker
            });
        } else {
            res.jsonp(updateBroker);
        }
    });
};
// Create Broker
exports.create = function(req, res) {
    var request = req.body;
    var newBroker = new Broker(request);
    var validFrom = request.valid_from;
    var validTo = request.valid_to;
    newBroker.creator = req.user;
    if (validFrom) {
        newBroker.valid_from = new Date(req.body.valid_from);
    }
    if (validTo) {
        newBroker.valid_to = new Date(req.body.valid_to);
    }
    newBroker.save(function(err) {
        if (!err) {
            res.jsonp(newBroker);
        } else {
            return res.send(err);
        }
    });
};
<|endoftext|>


<commit_before>//TODO remove class valid/noValid

$(document).ready(function(){

  //variables
  var nom = $("#nom");
  cognom = $("#cognom");
  email = $("#email");
  comment = $(".palabras textarea");

   //Comprova si el NOM esta buit
   nom.on("blur",function(){
    var $this = $(this);
    if($this.val().length === 0 ||
     $this.val() === "Nom"){
      $this.addClass("noValid");
    $this.val("");
  } else{
    $this.addClass("valid");
  }
});

   cognom.on("blur",function(){
    var $this = $(this);
    if($this.val().length === 0 ||
     $this.val() === "Nom"){
      $this.addClass("noValid");
    $this.val("");
  } else{
    $this.addClass("valid");
  }
});

    //Comprova si el EMAIL esta buit
    email.on("blur",function(){
      var $this = $(this);
      if($this.val().length === 0 ||
       $this.val() === "Email"){
        $this.addClass("noValid");
    }
  });

    //Comprova si l'EMAIL es valid
    email.on("blur",function(){
      var $this = $(this);
      if($this.val().indexOf("." && "@") > -1){
       $this.addClass("valid");
     } else{
      $this.addClass("noValid");
      $this.val("Email");
    }
  });

    //check if textarea is empty
    comment.on("blur",function(){
      var $this = $(this);
      if($this.val() === ""){
        $this.addClass("noValid");
        $this.val("Comments");
      } else{
        $this.addClass("valid");
      }
    });

    //clear inputs on click
    $(".input").on("focus",function(){
      $(this).val("");
    });

    //show modal when inputs are valid and button
    //is clicked
    $(".submit").on("click",function(){
      if(name.val() !== "Name" && name.val() !== "" &&
       email.val() !== "Email" &&
       email.val() !== "" &&
       comment.val() !== "Comments" &&
       comment.val()!== ""){

          //remove invalid/valid classes
        name.removeClass().addClass("input");
        email.removeClass().addClass("input");
        comment.removeClass().addClass("input");

          //modal box
          modal_name.text(name.val());
          modal.slideDown("medium")
          .delay(2000).slideUp("fast");

          //put default text back
          name.val("Name");
          email.val("Email");
          comment.val("Comments");

          return false;

        } else{

          return false; }
        });

    $.datepicker.formatDate( "dd-mm-yy", new Date( 2007, 7 - 1, 26 ) );

    $(function() {
    $( "#datepicker" ).datepicker();
  });

  });
<commit_msg>Afegits detalls (var de variables, prova de removeclass("valid")<commit_after>//TODO remove class valid/noValid

$(document).ready(function(){

  //variables
  var nom = $("#nom");
  var cognom = $("#cognom");
  var email = $("#email");
  var comment = $(".palabras textarea");

   //Comprova si el NOM esta buit
   nom.on("blur",function(){
    var $this = $(this);
    if($this.val().length === 0 ||
     $this.val() === "Nom"){
      $this.addClass("noValid");
      $this.removeClass("Valid");
    $this.val("");
  } else{
    $this.addClass("valid");
  }
});

   cognom.on("blur",function(){
    var $this = $(this);
    if($this.val().length === 0 ||
     $this.val() === "Nom"){
      $this.addClass("noValid");
    $this.val("");
  } else{
    $this.addClass("valid");
  }
});

    //Comprova si el EMAIL esta buit
    email.on("blur",function(){
      var $this = $(this);
      if($this.val().length === 0 ||
       $this.val() === "Email"){
        $this.addClass("noValid");
    }
  });

    //Comprova si l'EMAIL es valid
    email.on("blur",function(){
      var $this = $(this);
      if($this.val().indexOf("." && "@") > -1){
       $this.addClass("valid");
     } else{
      $this.addClass("noValid");
      $this.val("Email");
    }
  });

    //check if textarea is empty
    comment.on("blur",function(){
      var $this = $(this);
      if($this.val() === ""){
        $this.addClass("noValid");
        $this.val("Comments");
      } else{
        $this.addClass("valid");
      }
    });

    //clear inputs on click
    $(".input").on("focus",function(){
      $(this).val("");
    });

    //show modal when inputs are valid and button
    //is clicked
    $(".submit").on("click",function(){
      if(name.val() !== "Name" && name.val() !== "" &&
       email.val() !== "Email" &&
       email.val() !== "" &&
       comment.val() !== "Comments" &&
       comment.val()!== ""){

          //remove invalid/valid classes
        name.removeClass().addClass("input");
        email.removeClass().addClass("input");
        comment.removeClass().addClass("input");

          //modal box
          modal_name.text(name.val());
          modal.slideDown("medium")
          .delay(2000).slideUp("fast");

          //put default text back
          name.val("Name");
          email.val("Email");
          comment.val("Comments");

          return false;

        } else{

          return false; }
        });

    $.datepicker.formatDate( "dd-mm-yy", new Date( 2007, 7 - 1, 26 ) );

    $(function() {
    $( "#datepicker" ).datepicker();
  });

  });
<|endoftext|>


<commit_before>import React, { Component, createElement } from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import omit from 'lodash.omit';
import {
  IconChevronUpSmallOutline,
  IconChevronDownSmallOutline,
  IconWarningBadgedSmallFilled,
} from '@teamleader/ui-icons';
import InputMetaPropTypes from './InputMetaPropTypes';
import Box from '../box';
import Button from '../button';
import Counter from '../counter';
import { TextSmall } from '../typography';
import theme from './theme.css';

export default class Input extends Component {
  static propTypes = {
    autoFocus: PropTypes.bool,
    bold: PropTypes.bool,
    className: PropTypes.string,
    connectedLeft: PropTypes.element,
    connectedRight: PropTypes.element,
    counter: PropTypes.number,
    disabled: PropTypes.bool,
    format: PropTypes.func,
    helpText: PropTypes.string,
    icon: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
    iconPlacement: PropTypes.oneOf(['left', 'right']),
    id: PropTypes.string,
    inverse: PropTypes.bool,
    max: PropTypes.number,
    min: PropTypes.number,
    meta: InputMetaPropTypes,
    onBlur: PropTypes.func,
    onChange: PropTypes.func,
    onFocus: PropTypes.func,
    placeholder: PropTypes.string,
    precision: PropTypes.number,
    readOnly: PropTypes.bool,
    size: PropTypes.oneOf(['small', 'medium', 'large']),
    step: PropTypes.number,
    type: PropTypes.string,
    value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  };

  static defaultProps = {
    iconPlacement: 'left',
    inverse: false,
    disabled: false,
    placeholder: '',
    precision: null,
    min: -9007199254740991,
    max: 9007199254740991,
    readOnly: false,
    size: 'medium',
    step: 1,
  };

  constructor(props) {
    super(props);

    this.handleChange = ::this.handleChange;
    this.handleIncreaseValue = ::this.handleIncreaseValue;
    this.handleDecreaseValue = ::this.handleDecreaseValue;

    this.state = {
      value: props.type === 'number' ? Number(props.value) || '' : props.value || '',
    };
  }

  componentWillUpdate(props, state) {
    if (props.onChange && state.value) {
      props.onChange(state.value);
    }
  }

  handleChange(event) {
    const value = event.target.value;

    this.setState(() => ({
      value: this.props.type === 'number' ? Number(value) : value,
    }));
  }

  handleIncreaseValue() {
    this.step(1);
  }

  handleDecreaseValue() {
    this.step(-1);
  }

  format(number) {
    const { format, precision } = this.props;

    let formattedNumber = this.toNumber(number);

    if (precision !== null) {
      formattedNumber = number.toFixed(precision);
    }

    formattedNumber += '';

    if (format) {
      return format(formattedNumber);
    }

    return formattedNumber;
  }

  step(n) {
    const { step } = this.props;

    const number = this.toNumber((this.state.value || 0) + step * n);

    if (number !== this.state.value) {
      this.setState({ value: number });
      return true;
    }

    return false;
  }

  toNumber(number) {
    const { max, min, precision } = this.props;

    let float = parseFloat(number);

    if (isNaN(float) || !isFinite(float)) {
      float = 0;
    }

    const q = Math.pow(10, precision === null ? 10 : precision);

    float = Math.min(Math.max(float, min), max);
    float = Math.round(float * q) / q;

    return float;
  }

  renderInput() {
    const { autoFocus, bold, disabled, id, max, min, onBlur, onFocus, placeholder, readOnly, step, type } = this.props;
    const classNames = cx(theme['input'], {
      [theme['is-bold']]: bold,
    });

    const props = {
      autoFocus,
      className: classNames,
      disabled: disabled,
      id,
      max,
      min,
      onBlur: onBlur,
      onChange: this.handleChange,
      onFocus: onFocus,
      placeholder,
      readOnly,
      step,
      type,
      value: type === 'number' && this.state.value ? this.format(this.state.value) : this.state.value,
    };

    return <input {...props} />;
  }

  renderCounter() {
    if (this.props.counter) {
      return <Counter className={theme.counter} count={this.props.counter} color="ruby" size="small" />;
    }
  }

  renderHelpText() {
    const { helpText, inverse } = this.props;

    if (helpText) {
      return (
        <TextSmall color={inverse ? 'white' : 'neutral'} marginTop={1} soft>
          {helpText}
        </TextSmall>
      );
    }
  }

  renderSpinnerControls() {
    const { disabled, readOnly, type } = this.props;

    const props = {
      disabled: disabled || readOnly,
    };

    if (type === 'number') {
      return (

          <Button
            className={theme['spinner-up']}
            icon={<IconChevronUpSmallOutline />}
            onClick={this.handleIncreaseValue}
            {...props}
          />
          <Button
            className={theme['spinner-down']}
            icon={<IconChevronDownSmallOutline />}
            onClick={this.handleDecreaseValue}
            {...props}
          />

      );
    }
  }

  renderValidationMessage() {
    return (
      <Box marginTop={2}>
        <IconWarningBadgedSmallFilled className={theme['validation-icon']} />
        <TextSmall className={theme['validation-text']} element="span" marginLeft={1}>
          {this.props.meta.error}
        </TextSmall>
      </Box>
    );
  }

  render() {
    const {
      className,
      connectedLeft,
      connectedRight,
      counter,
      disabled,
      icon,
      iconPlacement,
      inverse,
      size,
      type,
      meta,
      readOnly,
      ...others
    } = this.props;

    const classNames = cx(
      theme.wrapper,
      theme[`is-${size}`],
      {
        [theme[`has-icon-${iconPlacement}`]]: icon,
        [theme['has-counter']]: counter,
        [theme['has-error']]: Boolean(meta && meta.error),
        [theme['has-connected-left']]: connectedLeft,
        [theme['has-connected-right']]: connectedRight,
        [theme['is-inverse']]: inverse,
        [theme['is-numeric']]: type === 'number',
        [theme['is-disabled']]: disabled,
        [theme['is-read-only']]: readOnly,
      },
      className,
    );

    const inputWrapperClassnames = cx(theme['input-wrapper'], {
      [theme['has-error']]: Boolean(meta && meta.error),
    });

    const rest = omit(others, [
      'bold',
      'id',
      'helpText',
      'onBlur',
      'onChange',
      'onFocus',
      'placeholder',
      'step',
      'value',
    ]);

    return (
      <Box className={classNames} {...rest}>

          {connectedLeft}

            {icon &&
              createElement(icon, {
                className: theme.icon,
              })}
            {this.renderInput()}
            {this.renderCounter()}
            {this.renderSpinnerControls()}

          {connectedRight}

        {meta && meta.error ? this.renderValidationMessage() : this.renderHelpText()}
      </Box>
    );
  }
}
<commit_msg>Omit props that are meant for the input and not for the wrapper<commit_after>import React, { Component, createElement } from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import omit from 'lodash.omit';
import {
  IconChevronUpSmallOutline,
  IconChevronDownSmallOutline,
  IconWarningBadgedSmallFilled,
} from '@teamleader/ui-icons';
import InputMetaPropTypes from './InputMetaPropTypes';
import Box from '../box';
import Button from '../button';
import Counter from '../counter';
import { TextSmall } from '../typography';
import theme from './theme.css';

export default class Input extends Component {
  static propTypes = {
    autoFocus: PropTypes.bool,
    bold: PropTypes.bool,
    className: PropTypes.string,
    connectedLeft: PropTypes.element,
    connectedRight: PropTypes.element,
    counter: PropTypes.number,
    disabled: PropTypes.bool,
    format: PropTypes.func,
    helpText: PropTypes.string,
    icon: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
    iconPlacement: PropTypes.oneOf(['left', 'right']),
    id: PropTypes.string,
    inverse: PropTypes.bool,
    max: PropTypes.number,
    min: PropTypes.number,
    meta: InputMetaPropTypes,
    onBlur: PropTypes.func,
    onChange: PropTypes.func,
    onFocus: PropTypes.func,
    placeholder: PropTypes.string,
    precision: PropTypes.number,
    readOnly: PropTypes.bool,
    size: PropTypes.oneOf(['small', 'medium', 'large']),
    step: PropTypes.number,
    type: PropTypes.string,
    value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  };

  static defaultProps = {
    iconPlacement: 'left',
    inverse: false,
    disabled: false,
    placeholder: '',
    precision: null,
    min: -9007199254740991,
    max: 9007199254740991,
    readOnly: false,
    size: 'medium',
    step: 1,
  };

  constructor(props) {
    super(props);

    this.handleChange = ::this.handleChange;
    this.handleIncreaseValue = ::this.handleIncreaseValue;
    this.handleDecreaseValue = ::this.handleDecreaseValue;

    this.state = {
      value: props.type === 'number' ? Number(props.value) || '' : props.value || '',
    };
  }

  componentWillUpdate(props, state) {
    if (props.onChange && state.value) {
      props.onChange(state.value);
    }
  }

  handleChange(event) {
    const value = event.target.value;

    this.setState(() => ({
      value: this.props.type === 'number' ? Number(value) : value,
    }));
  }

  handleIncreaseValue() {
    this.step(1);
  }

  handleDecreaseValue() {
    this.step(-1);
  }

  format(number) {
    const { format, precision } = this.props;

    let formattedNumber = this.toNumber(number);

    if (precision !== null) {
      formattedNumber = number.toFixed(precision);
    }

    formattedNumber += '';

    if (format) {
      return format(formattedNumber);
    }

    return formattedNumber;
  }

  step(n) {
    const { step } = this.props;

    const number = this.toNumber((this.state.value || 0) + step * n);

    if (number !== this.state.value) {
      this.setState({ value: number });
      return true;
    }

    return false;
  }

  toNumber(number) {
    const { max, min, precision } = this.props;

    let float = parseFloat(number);

    if (isNaN(float) || !isFinite(float)) {
      float = 0;
    }

    const q = Math.pow(10, precision === null ? 10 : precision);

    float = Math.min(Math.max(float, min), max);
    float = Math.round(float * q) / q;

    return float;
  }

  renderInput() {
    const { autoFocus, bold, disabled, id, max, min, onBlur, onFocus, placeholder, readOnly, step, type } = this.props;
    const classNames = cx(theme['input'], {
      [theme['is-bold']]: bold,
    });

    const props = {
      autoFocus,
      className: classNames,
      disabled: disabled,
      id,
      max,
      min,
      onBlur: onBlur,
      onChange: this.handleChange,
      onFocus: onFocus,
      placeholder,
      readOnly,
      step,
      type,
      value: type === 'number' && this.state.value ? this.format(this.state.value) : this.state.value,
    };

    return <input {...props} />;
  }

  renderCounter() {
    if (this.props.counter) {
      return <Counter className={theme.counter} count={this.props.counter} color="ruby" size="small" />;
    }
  }

  renderHelpText() {
    const { helpText, inverse } = this.props;

    if (helpText) {
      return (
        <TextSmall color={inverse ? 'white' : 'neutral'} marginTop={1} soft>
          {helpText}
        </TextSmall>
      );
    }
  }

  renderSpinnerControls() {
    const { disabled, readOnly, type } = this.props;

    const props = {
      disabled: disabled || readOnly,
    };

    if (type === 'number') {
      return (

          <Button
            className={theme['spinner-up']}
            icon={<IconChevronUpSmallOutline />}
            onClick={this.handleIncreaseValue}
            {...props}
          />
          <Button
            className={theme['spinner-down']}
            icon={<IconChevronDownSmallOutline />}
            onClick={this.handleDecreaseValue}
            {...props}
          />

      );
    }
  }

  renderValidationMessage() {
    return (
      <Box marginTop={2}>
        <IconWarningBadgedSmallFilled className={theme['validation-icon']} />
        <TextSmall className={theme['validation-text']} element="span" marginLeft={1}>
          {this.props.meta.error}
        </TextSmall>
      </Box>
    );
  }

  render() {
    const {
      className,
      connectedLeft,
      connectedRight,
      counter,
      disabled,
      icon,
      iconPlacement,
      inverse,
      size,
      type,
      meta,
      readOnly,
      ...others
    } = this.props;

    const classNames = cx(
      theme.wrapper,
      theme[`is-${size}`],
      {
        [theme[`has-icon-${iconPlacement}`]]: icon,
        [theme['has-counter']]: counter,
        [theme['has-error']]: Boolean(meta && meta.error),
        [theme['has-connected-left']]: connectedLeft,
        [theme['has-connected-right']]: connectedRight,
        [theme['is-inverse']]: inverse,
        [theme['is-numeric']]: type === 'number',
        [theme['is-disabled']]: disabled,
        [theme['is-read-only']]: readOnly,
      },
      className,
    );

    const inputWrapperClassnames = cx(theme['input-wrapper'], {
      [theme['has-error']]: Boolean(meta && meta.error),
    });

    const rest = omit(others, [
      'bold',
      'format',
      'id',
      'helpText',
      'max',
      'min',
      'onBlur',
      'onChange',
      'onFocus',
      'placeholder',
      'precision',
      'step',
      'value',
    ]);

    return (
      <Box className={classNames} {...rest}>

          {connectedLeft}

            {icon &&
              createElement(icon, {
                className: theme.icon,
              })}
            {this.renderInput()}
            {this.renderCounter()}
            {this.renderSpinnerControls()}

          {connectedRight}

        {meta && meta.error ? this.renderValidationMessage() : this.renderHelpText()}
      </Box>
    );
  }
}
<|endoftext|>


<commit_before>const _ = require('underscore');

const AbilityLimit = require('./abilitylimit.js');
const CostReducer = require('./costreducer.js');
const PlayableLocation = require('./playablelocation.js');
const CannotRestriction = require('./cannotrestriction.js');
const ImmunityRestriction = require('./immunityrestriction.js');

function cardCannotEffect(type) {
    return function(predicate) {
        let restriction = new CannotRestriction(type, predicate);
        return {
            apply: function(card) {
                card.addAbilityRestriction(restriction);
            },
            unapply: function(card) {
                card.removeAbilityRestriction(restriction);
            }
        };
    };
}

function playerCannotEffect(type) {
    return function(predicate) {
        let restriction = new CannotRestriction(type, predicate);
        return {
            apply: function(player) {
                player.abilityRestrictions.push(restriction);
            },
            unapply: function(player) {
                player.abilityRestrictions = _.reject(player.abilityRestrictions, r => r === restriction);
            }
        };
    };
}

const Effects = {
    all: function(effects) {
        let stateDependentEffects = _.filter(effects, effect => effect.isStateDependent);
        return {
            apply: function(card, context) {
                _.each(effects, effect => effect.apply(card, context));
            },
            reapply: function(card, context) {
                _.each(stateDependentEffects, effect => {
                    if(effect.reapply) {
                        effect.reapply(card, context);
                    } else {
                        effect.unapply(card, context);
                        effect.apply(card, context);
                    }
                });
            },
            unapply: function(card, context) {
                _.each(effects, effect => effect.unapply(card, context));
            },
            isStateDependent: (stateDependentEffects.length !== 0)
        };
    },
    cannotBeDeclaredAsAttacker: cardCannotEffect('declareAsAttacker'),
    cannotBeDeclaredAsDefender: cardCannotEffect('declareAsDefender'),
    cannotParticipateAsAttacker: cardCannotEffect('participateAsAttacker'),
    cannotParticipateAsDefender: cardCannotEffect('participateAsDefender'),
    doesNotBowAsAttacker: function () {
        return {
            apply: function(card) {
                card.conflictOptions.doesNotBowAs.attacker = true;
            },
            unapply: function(card) {
                card.conflictOptions.doesNotBowAs.attacker = false;
            }
        };
    },
    doesNotBowAsDefender: function () {
        return {
            apply: function(card) {
                card.conflictOptions.doesNotBowAs.defender = true;
            },
            unapply: function(card) {
                card.conflictOptions.doesNotBowAs.defender = false;
            }
        };
    },
    modifyMilitarySkill: function(value) {
        return {
            apply: function(card) {
                card.modifyMilitarySkill(value, true);
            },
            unapply: function(card) {
                card.modifyMilitarySkill(-value, false);
            }
        };
    },
    modifyPoliticalSkill: function(value) {
        return {
            apply: function(card) {
                card.modifyPoliticalSkill(value, true);
            },
            unapply: function(card) {
                card.modifyPoliticalSkill(-value, false);
            }
        };
    },
    modifyGlory: function(value) {
        return {
            apply: function(card) {
                card.modifyGlory(value, true);
            },
            unapply: function(card) {
                card.modifyGlory(-value, false);
            }
        };
    },
    dynamicMilitarySkill: function(calculate) {
        return {
            apply: function(card, context) {
                context.dynamicMilitarySkill = context.dynamicMilitarySkill || {};
                context.dynamicMilitarySkill[card.uuid] = calculate(card, context) || 0;
                card.modifyMilitarySkill(context.dynamicMilitarySkill[card.uuid], true);
            },
            reapply: function(card, context) {
                let currentMilitarySkill = context.dynamicMilitarySkill[card.uuid];
                let newMilitarySkill = calculate(card, context) || 0;
                context.dynamicMilitarySkill[card.uuid] = newMilitarySkill;
                card.modifyMilitarySkill(newMilitarySkill - currentMilitarySkill, true);
            },
            unapply: function(card, context) {
                card.modifyMilitarySkill(-context.dynamicMilitarySkill[card.uuid], false);
                delete context.dynamicMilitarySkill[card.uuid];
            },
            isStateDependent: true
        };
    },
    dynamicPoliticalSkill: function(calculate) {
        return {
            apply: function(card, context) {
                context.dynamicPoliticalSkill = context.dynamicPoliticalSkill || {};
                context.dynamicPoliticalSkill[card.uuid] = calculate(card, context) || 0;
                card.modifyPoliticalSkill(context.dynamicPoliticalSkill[card.uuid], true);
            },
            reapply: function(card, context) {
                let currentPoliticalSkill = context.dynamicPoliticalSkill[card.uuid];
                let newPoliticalSkill = calculate(card, context) || 0;
                context.dynamicPoliticalSkill[card.uuid] = newPoliticalSkill;
                card.modifyPoliticalSkill(newPoliticalSkill - currentPoliticalSkill, true);
            },
            unapply: function(card, context) {
                card.modifyPoliticalSkill(-context.dynamicPoliticalSkill[card.uuid], false);
                delete context.dynamicPoliticalSkill[card.uuid];
            },
            isStateDependent: true
        };
    },
    discardByPoliticalSkill: {
        apply: function(card, context) {
            if(card.getPoliticalSkill() <= 0) {
                card.controller.discardCardFromPlay(card);
                context.game.addMessage('{0} is killed as its political is 0', card);
            }
        },
        unapply: function() {
            // nothing happens when this effect expires.
        },
        isStateDependent: true
    },
    addKeyword: function(keyword) {
        return {
            apply: function(card) {
                card.addKeyword(keyword);
            },
            unapply: function(card) {
                card.removeKeyword(keyword);
            }
        };
    },
    removeKeyword: function(keyword) {
        return {
            apply: function(card) {
                card.removeKeyword(keyword);
            },
            unapply: function(card) {
                card.addKeyword(keyword);
            }
        };
    },
    addMultipleKeywords: function(keywords) {
        return {
            apply: function(card) {
                _.each(keywords, keyword => card.addKeyword(keyword));
            },
            unapply: function(card) {
                _.each(keywords, keyword => card.removeKeyword(keyword));
            }
        };
    },
    removeAllKeywords: function() {
        return [
            this.removeKeyword('ancestral'),
            this.removeKeyword('restricted'),
            this.removeKeyword('limited'),
            this.removeKeyword('sincerity'),
            this.removeKeyword('pride'),
            this.removeKeyword('covert')
        ];
    },
    addTrait: function(trait) {
        return {
            apply: function(card) {
                card.addTrait(trait);
            },
            unapply: function(card) {
                card.removeTrait(trait);
            }
        };
    },
    addFaction: function(faction) {
        return {
            apply: function(card) {
                card.addFaction(faction);
            },
            unapply: function(card) {
                card.removeFaction(faction);
            }
        };
    },
    blank: {
        apply: function(card) {
            card.setBlank();
        },
        unapply: function(card) {
            card.clearBlank();
        }
    },
    discardIfStillInPlay: function() {
        return {
            apply: function(card, context) {
                context.discardIfStillInPlay = context.discardIfStillInPlay || [];
                context.discardIfStillInPlay.push(card);
            },
            unapply: function(card, context) {
                if(card.location === 'play area' && context.discardIfStillInPlay.includes(card)) {
                    context.discardIfStillInPlay = _.reject(context.discardIfStillInPlay, c => c === card);
                    card.controller.discardCardFromPlay(card);
                    context.game.addMessage('{0} discards {1} at the end of the phase because of {2}', context.source.controller, card, context.source);
                }
            }
        };
    },
    returnToHandIfStillInPlay: function() {
        return {
            apply: function(card, context) {
                context.returnToHandIfStillInPlay = context.returnToHandIfStillInPlay || [];
                context.returnToHandIfStillInPlay.push(card);
            },
            unapply: function(card, context) {
                if(card.location === 'play area' && context.returnToHandIfStillInPlay.includes(card)) {
                    context.returnToHandIfStillInPlay = _.reject(context.returnToHandIfStillInPlay, c => c === card);
                    card.controller.returnCardToHand(card);
                    context.game.addMessage('{0} returns {1} to hand at the end of the phase because of {2}', context.source.controller, card, context.source);
                }
            }
        };
    },
    moveToBottomOfDeckIfStillInPlay: function() {
        return {
            apply: function(card, context) {
                context.moveToBottomOfDeckIfStillInPlay = context.moveToBottomOfDeckIfStillInPlay || [];
                context.moveToBottomOfDeckIfStillInPlay.push(card);
            },
            unapply: function(card, context) {
                if(card.location === 'play area' && context.moveToBottomOfDeckIfStillInPlay.includes(card)) {
                    context.moveToBottomOfDeckIfStillInPlay = _.reject(context.moveToBottomOfDeckIfStillInPlay, c => c === card);
                    card.owner.moveCardToBottomOfDeck(card);
                    context.game.addMessage('{0} moves {1} to the bottom of its owner\'s deck at the end of the phase because of {2}', context.source.controller, card, context.source);
                }
            }
        };
    },
    immuneTo: function(cardCondition) {
        let restriction = new ImmunityRestriction(cardCondition);
        return {
            apply: function(card) {
                card.addAbilityRestriction(restriction);
            },
            unapply: function(card) {
                card.removeAbilityRestriction(restriction);
            }
        };
    },
    takeControl: function(newController) {
        return {
            apply: function(card, context) {
                context.takeControl = context.takeControl || {};
                context.takeControl[card.uuid] = { originalController: card.controller };
                context.game.takeControl(newController, card);
                context.game.addMessage('{0} uses {1} to take control of {2}', context.source.controller, context.source, card);
            },
            unapply: function(card, context) {
                context.game.takeControl(context.takeControl[card.uuid].originalController, card);
                delete context.takeControl[card.uuid];
            }
        };
    },
    cannotBeDiscarded: cardCannotEffect('discardFromPlay'),
    cannotRemoveFate: cardCannotEffect('removeFate'),
    cannotPlay: playerCannotEffect('play'),
    cardCannotTriggerAbilities: cardCannotEffect('triggerAbilities'),
    cannotBeTargeted: cardCannotEffect('target'),
    cannotBeBowed: cardCannotEffect('bow'),
    cannotBeMovedIntoConflict: cardCannotEffect('moveToConflict'),
    cannotBeSentHome: cardCannotEffect('sendHome'),
    cannotMoveCharactersIntoConflict: playerCannotEffect('moveToConflict'),
    playerCannotTriggerCardAbilities: playerCannotEffect('triggerAbilities'),
    cannotBecomeDishonored: cardCannotEffect('becomeDishonored'),
    increaseLimitOnAbilities: function(amount) {
        return {
            apply: function(card) {
                _.each(card.abilities.actions, ability => {
                    if(ability.limit) {
                        ability.limit.modifyMax(amount);
                    }
                });
                _.each(card.abilities.reactions, ability => {
                    if(ability.limit) {
                        ability.limit.modifyMax(amount);
                    }
                });
            },
            unapply: function(card) {
                _.each(card.abilities.actions, ability => {
                    if(ability.limit) {
                        ability.limit.modifyMax(-amount);
                    }
                });
                _.each(card.abilities.reactions, ability => {
                    if(ability.limit) {
                        ability.limit.modifyMax(-amount);
                    }
                });
            }
        };
    },
    canPlayFromOwn: function(location) {
        return {
            apply: function(player, context) {
                let playableLocation = new PlayableLocation('play', player, location);
                context.canPlayFromOwn = playableLocation;
                player.playableLocations.push(playableLocation);
            },
            unapply: function(player, context) {
                player.playableLocations = _.reject(player.playableLocations, l => l === context.canPlayFromOwn);
                delete context.canPlayFromOwn;
            }
        };
    },
    reduceCost: function(properties) {
        return {
            apply: function(player, context) {
                context.reducers = context.reducers || [];
                var reducer = new CostReducer(context.game, context.source, properties);
                context.reducers.push(reducer);
                player.addCostReducer(reducer);
            },
            unapply: function(player, context) {
                if(context.reducers.length > 0) {
                    _.each(context.reducers, reducer => player.removeCostReducer(reducer));
                }
            }
        };
    },
    reduceNextCardCost: function(playingTypes, amount, match) {
        return this.reduceCost({
            playingTypes: playingTypes,
            amount: amount,
            match: match,
            limit: AbilityLimit.fixed(1)
        });
    },
    reduceNextPlayedCardCost: function(amount, match) {
        return this.reduceNextCardCost('play', amount, match);
    },
    reduceFirstCardCostEachRound: function(playingTypes, amount, match) {
        return this.reduceCost({
            playingTypes: playingTypes,
            amount: amount,
            match: match,
            limit: AbilityLimit.perRound(1)
        });
    },
    reduceFirstPlayedCardCostEachRound: function(amount, match) {
        return this.reduceFirstCardCostEachRound('play', amount, match);
    },
    increaseCost: function(properties) {
        properties.amount = -properties.amount;
        return this.reduceCost(properties);
    }
};

module.exports = Effects;
<commit_msg>changes does not bow to return to original value and not to false.<commit_after>const _ = require('underscore');

const AbilityLimit = require('./abilitylimit.js');
const CostReducer = require('./costreducer.js');
const PlayableLocation = require('./playablelocation.js');
const CannotRestriction = require('./cannotrestriction.js');
const ImmunityRestriction = require('./immunityrestriction.js');

function cardCannotEffect(type) {
    return function(predicate) {
        let restriction = new CannotRestriction(type, predicate);
        return {
            apply: function(card) {
                card.addAbilityRestriction(restriction);
            },
            unapply: function(card) {
                card.removeAbilityRestriction(restriction);
            }
        };
    };
}

function playerCannotEffect(type) {
    return function(predicate) {
        let restriction = new CannotRestriction(type, predicate);
        return {
            apply: function(player) {
                player.abilityRestrictions.push(restriction);
            },
            unapply: function(player) {
                player.abilityRestrictions = _.reject(player.abilityRestrictions, r => r === restriction);
            }
        };
    };
}

const Effects = {
    all: function(effects) {
        let stateDependentEffects = _.filter(effects, effect => effect.isStateDependent);
        return {
            apply: function(card, context) {
                _.each(effects, effect => effect.apply(card, context));
            },
            reapply: function(card, context) {
                _.each(stateDependentEffects, effect => {
                    if(effect.reapply) {
                        effect.reapply(card, context);
                    } else {
                        effect.unapply(card, context);
                        effect.apply(card, context);
                    }
                });
            },
            unapply: function(card, context) {
                _.each(effects, effect => effect.unapply(card, context));
            },
            isStateDependent: (stateDependentEffects.length !== 0)
        };
    },
    cannotBeDeclaredAsAttacker: cardCannotEffect('declareAsAttacker'),
    cannotBeDeclaredAsDefender: cardCannotEffect('declareAsDefender'),
    cannotParticipateAsAttacker: cardCannotEffect('participateAsAttacker'),
    cannotParticipateAsDefender: cardCannotEffect('participateAsDefender'),
    doesNotBowAsAttacker: function () {
        return {
            apply: function(card, context) {
                context.doesNotBowAsDefender[card.uuid] = card.conflictOptions.doesNotBowAs.attacker;
                card.conflictOptions.doesNotBowAs.attacker = true;
            },
            unapply: function(card, context) {
                card.conflictOptions.doesNotBowAs.attacker = context.doesNotBowAsAttacker[card.uuid];
                delete context.doesNotBowAsAttacker[card.uuid];
            }
        };
    },
    doesNotBowAsDefender: function () {
        return {
            apply: function(card, context) {
                context.doesNotBowAsDefender[card.uuid] = card.conflictOptions.doesNotBowAs.defender;
                card.conflictOptions.doesNotBowAs.defender = true;
            },
            unapply: function(card, context) {
                card.conflictOptions.doesNotBowAs.defender = context.doesNotBowAsDefender[card.uuid];
                delete context.doesNotBowAsDefender[card.uuid];
            }
        };
    },
    modifyMilitarySkill: function(value) {
        return {
            apply: function(card) {
                card.modifyMilitarySkill(value, true);
            },
            unapply: function(card) {
                card.modifyMilitarySkill(-value, false);
            }
        };
    },
    modifyPoliticalSkill: function(value) {
        return {
            apply: function(card) {
                card.modifyPoliticalSkill(value, true);
            },
            unapply: function(card) {
                card.modifyPoliticalSkill(-value, false);
            }
        };
    },
    modifyGlory: function(value) {
        return {
            apply: function(card) {
                card.modifyGlory(value, true);
            },
            unapply: function(card) {
                card.modifyGlory(-value, false);
            }
        };
    },
    dynamicMilitarySkill: function(calculate) {
        return {
            apply: function(card, context) {
                context.dynamicMilitarySkill = context.dynamicMilitarySkill || {};
                context.dynamicMilitarySkill[card.uuid] = calculate(card, context) || 0;
                card.modifyMilitarySkill(context.dynamicMilitarySkill[card.uuid], true);
            },
            reapply: function(card, context) {
                let currentMilitarySkill = context.dynamicMilitarySkill[card.uuid];
                let newMilitarySkill = calculate(card, context) || 0;
                context.dynamicMilitarySkill[card.uuid] = newMilitarySkill;
                card.modifyMilitarySkill(newMilitarySkill - currentMilitarySkill, true);
            },
            unapply: function(card, context) {
                card.modifyMilitarySkill(-context.dynamicMilitarySkill[card.uuid], false);
                delete context.dynamicMilitarySkill[card.uuid];
            },
            isStateDependent: true
        };
    },
    dynamicPoliticalSkill: function(calculate) {
        return {
            apply: function(card, context) {
                context.dynamicPoliticalSkill = context.dynamicPoliticalSkill || {};
                context.dynamicPoliticalSkill[card.uuid] = calculate(card, context) || 0;
                card.modifyPoliticalSkill(context.dynamicPoliticalSkill[card.uuid], true);
            },
            reapply: function(card, context) {
                let currentPoliticalSkill = context.dynamicPoliticalSkill[card.uuid];
                let newPoliticalSkill = calculate(card, context) || 0;
                context.dynamicPoliticalSkill[card.uuid] = newPoliticalSkill;
                card.modifyPoliticalSkill(newPoliticalSkill - currentPoliticalSkill, true);
            },
            unapply: function(card, context) {
                card.modifyPoliticalSkill(-context.dynamicPoliticalSkill[card.uuid], false);
                delete context.dynamicPoliticalSkill[card.uuid];
            },
            isStateDependent: true
        };
    },
    discardByPoliticalSkill: {
        apply: function(card, context) {
            if(card.getPoliticalSkill() <= 0) {
                card.controller.discardCardFromPlay(card);
                context.game.addMessage('{0} is killed as its political is 0', card);
            }
        },
        unapply: function() {
            // nothing happens when this effect expires.
        },
        isStateDependent: true
    },
    addKeyword: function(keyword) {
        return {
            apply: function(card) {
                card.addKeyword(keyword);
            },
            unapply: function(card) {
                card.removeKeyword(keyword);
            }
        };
    },
    removeKeyword: function(keyword) {
        return {
            apply: function(card) {
                card.removeKeyword(keyword);
            },
            unapply: function(card) {
                card.addKeyword(keyword);
            }
        };
    },
    addMultipleKeywords: function(keywords) {
        return {
            apply: function(card) {
                _.each(keywords, keyword => card.addKeyword(keyword));
            },
            unapply: function(card) {
                _.each(keywords, keyword => card.removeKeyword(keyword));
            }
        };
    },
    removeAllKeywords: function() {
        return [
            this.removeKeyword('ancestral'),
            this.removeKeyword('restricted'),
            this.removeKeyword('limited'),
            this.removeKeyword('sincerity'),
            this.removeKeyword('pride'),
            this.removeKeyword('covert')
        ];
    },
    addTrait: function(trait) {
        return {
            apply: function(card) {
                card.addTrait(trait);
            },
            unapply: function(card) {
                card.removeTrait(trait);
            }
        };
    },
    addFaction: function(faction) {
        return {
            apply: function(card) {
                card.addFaction(faction);
            },
            unapply: function(card) {
                card.removeFaction(faction);
            }
        };
    },
    blank: {
        apply: function(card) {
            card.setBlank();
        },
        unapply: function(card) {
            card.clearBlank();
        }
    },
    discardIfStillInPlay: function() {
        return {
            apply: function(card, context) {
                context.discardIfStillInPlay = context.discardIfStillInPlay || [];
                context.discardIfStillInPlay.push(card);
            },
            unapply: function(card, context) {
                if(card.location === 'play area' && context.discardIfStillInPlay.includes(card)) {
                    context.discardIfStillInPlay = _.reject(context.discardIfStillInPlay, c => c === card);
                    card.controller.discardCardFromPlay(card);
                    context.game.addMessage('{0} discards {1} at the end of the phase because of {2}', context.source.controller, card, context.source);
                }
            }
        };
    },
    returnToHandIfStillInPlay: function() {
        return {
            apply: function(card, context) {
                context.returnToHandIfStillInPlay = context.returnToHandIfStillInPlay || [];
                context.returnToHandIfStillInPlay.push(card);
            },
            unapply: function(card, context) {
                if(card.location === 'play area' && context.returnToHandIfStillInPlay.includes(card)) {
                    context.returnToHandIfStillInPlay = _.reject(context.returnToHandIfStillInPlay, c => c === card);
                    card.controller.returnCardToHand(card);
                    context.game.addMessage('{0} returns {1} to hand at the end of the phase because of {2}', context.source.controller, card, context.source);
                }
            }
        };
    },
    moveToBottomOfDeckIfStillInPlay: function() {
        return {
            apply: function(card, context) {
                context.moveToBottomOfDeckIfStillInPlay = context.moveToBottomOfDeckIfStillInPlay || [];
                context.moveToBottomOfDeckIfStillInPlay.push(card);
            },
            unapply: function(card, context) {
                if(card.location === 'play area' && context.moveToBottomOfDeckIfStillInPlay.includes(card)) {
                    context.moveToBottomOfDeckIfStillInPlay = _.reject(context.moveToBottomOfDeckIfStillInPlay, c => c === card);
                    card.owner.moveCardToBottomOfDeck(card);
                    context.game.addMessage('{0} moves {1} to the bottom of its owner\'s deck at the end of the phase because of {2}', context.source.controller, card, context.source);
                }
            }
        };
    },
    immuneTo: function(cardCondition) {
        let restriction = new ImmunityRestriction(cardCondition);
        return {
            apply: function(card) {
                card.addAbilityRestriction(restriction);
            },
            unapply: function(card) {
                card.removeAbilityRestriction(restriction);
            }
        };
    },
    takeControl: function(newController) {
        return {
            apply: function(card, context) {
                context.takeControl = context.takeControl || {};
                context.takeControl[card.uuid] = { originalController: card.controller };
                context.game.takeControl(newController, card);
                context.game.addMessage('{0} uses {1} to take control of {2}', context.source.controller, context.source, card);
            },
            unapply: function(card, context) {
                context.game.takeControl(context.takeControl[card.uuid].originalController, card);
                delete context.takeControl[card.uuid];
            }
        };
    },
    cannotBeDiscarded: cardCannotEffect('discardFromPlay'),
    cannotRemoveFate: cardCannotEffect('removeFate'),
    cannotPlay: playerCannotEffect('play'),
    cardCannotTriggerAbilities: cardCannotEffect('triggerAbilities'),
    cannotBeTargeted: cardCannotEffect('target'),
    cannotBeBowed: cardCannotEffect('bow'),
    cannotBeMovedIntoConflict: cardCannotEffect('moveToConflict'),
    cannotBeSentHome: cardCannotEffect('sendHome'),
    cannotMoveCharactersIntoConflict: playerCannotEffect('moveToConflict'),
    playerCannotTriggerCardAbilities: playerCannotEffect('triggerAbilities'),
    cannotBecomeDishonored: cardCannotEffect('becomeDishonored'),
    increaseLimitOnAbilities: function(amount) {
        return {
            apply: function(card) {
                _.each(card.abilities.actions, ability => {
                    if(ability.limit) {
                        ability.limit.modifyMax(amount);
                    }
                });
                _.each(card.abilities.reactions, ability => {
                    if(ability.limit) {
                        ability.limit.modifyMax(amount);
                    }
                });
            },
            unapply: function(card) {
                _.each(card.abilities.actions, ability => {
                    if(ability.limit) {
                        ability.limit.modifyMax(-amount);
                    }
                });
                _.each(card.abilities.reactions, ability => {
                    if(ability.limit) {
                        ability.limit.modifyMax(-amount);
                    }
                });
            }
        };
    },
    canPlayFromOwn: function(location) {
        return {
            apply: function(player, context) {
                let playableLocation = new PlayableLocation('play', player, location);
                context.canPlayFromOwn = playableLocation;
                player.playableLocations.push(playableLocation);
            },
            unapply: function(player, context) {
                player.playableLocations = _.reject(player.playableLocations, l => l === context.canPlayFromOwn);
                delete context.canPlayFromOwn;
            }
        };
    },
    reduceCost: function(properties) {
        return {
            apply: function(player, context) {
                context.reducers = context.reducers || [];
                var reducer = new CostReducer(context.game, context.source, properties);
                context.reducers.push(reducer);
                player.addCostReducer(reducer);
            },
            unapply: function(player, context) {
                if(context.reducers.length > 0) {
                    _.each(context.reducers, reducer => player.removeCostReducer(reducer));
                }
            }
        };
    },
    reduceNextCardCost: function(playingTypes, amount, match) {
        return this.reduceCost({
            playingTypes: playingTypes,
            amount: amount,
            match: match,
            limit: AbilityLimit.fixed(1)
        });
    },
    reduceNextPlayedCardCost: function(amount, match) {
        return this.reduceNextCardCost('play', amount, match);
    },
    reduceFirstCardCostEachRound: function(playingTypes, amount, match) {
        return this.reduceCost({
            playingTypes: playingTypes,
            amount: amount,
            match: match,
            limit: AbilityLimit.perRound(1)
        });
    },
    reduceFirstPlayedCardCostEachRound: function(amount, match) {
        return this.reduceFirstCardCostEachRound('play', amount, match);
    },
    increaseCost: function(properties) {
        properties.amount = -properties.amount;
        return this.reduceCost(properties);
    }
};

module.exports = Effects;
<|endoftext|>