<commit_before>// require('../shader/VertLinesFragment');

import dat from 'dat-gui';
import THREE from '../Three';
import Particle from './Particle-alt';

// Render Class Object //
export default class Render {
  constructor() {
    this.frames = 360;
    this.size = 5;
    this.speed = 5.0;
    this.amps = 500;
    this.scale = 1.0;
    this.ratio = 1024;
    this.mirror = 4;

    // Camera Stuff and Viewport //
    this.width = window.innerWidth;
    this.height = window.innerHeight;
    this.aspect = this.width / this.height;
    this.devicePixelRatio = window.devicePixelRatio;
    this.viewAngle = 65;
    this.aspect = this.width / this.height;
    this.near = 1;
    this.far = 20000;
    // Particles Stuff //

    this.particles = [];
    this.particleColor = 360;
    this.background = 0x333333;
    this.camPosition = {
      x: -1500.0,
      y: -90.0,
      z: -200.0
    };
    this.trsPosition = {
      x: -1500.0,
      y: -90.0,
      z: -200.0
    };
    this.emitter = {
      x: 0,
      y: 0,
      z: -1200
    };
    const bsize = 6000;
    this.box = {
      top: bsize,
      left: -bsize,
      bottom: -bsize,
      right: bsize,
    };
    this.settings = {
      gravity: 0.0,
      bounce: 0.35,
    };
    this.camTimeoutx = true;
    this.camTimeouty = true;
    this.camTimeoutz = true;
    setTimeout(
      () => {
        this.camTimeoutx = false;
        this.camTimeouty = false;
        this.camTimeoutz = false;
      },
      3000 + (600 * Math.random() * 10)
    );
    window.addEventListener('resize', this.resize, true);
    window.addEventListener('click', () => {
      console.log(this.camera.position);
    }, true);
    this.setRender();
    this.setEffects();
    // this.createGUI();
    this.renderLoop();
    this.music();
  }

  resize = () => {
    this.width = window.innerWidth;
    this.height = window.innerHeight;
    this.camera.updateProjectionMatrix();
    this.renderer.setSize(this.width, this.height);
  };

  createGUI = () => {
    this.options = {
      gravity: this.settings.gravity * 100,
      bounce: this.settings.bounce * 100,
      amps: this.amps
    };
    this.gui = new dat.GUI();
    const folderRender = this.gui.addFolder('Particle Options');
    // folderRender.add(this.options, 'gravity', 0, 100).step(1)
    //   .onFinishChange((value) => {
    //     this.settings.gravity = value * 0.01;
    //   });
    // folderRender.add(this.options, 'bounce', 0, 100).step(1)
    //   .onFinishChange((value) => {
    //     this.settings.bounce = value * 0.01;
    //   });
    folderRender.add(this.options, 'amps', 0, 800).step(1)
    .onFinishChange((value) => {
      this.amps = value;
    });
  }

  setRender = () => {
    // Set Render and Scene //
    this.renderer = new THREE.WebGLRenderer();
    this.renderer.setSize(this.width, this.height);
    this.renderer.setPixelRatio(this.devicePixelRatio);
    document.body.appendChild(this.renderer.domElement);

    this.scene = new THREE.Scene();
    this.scene.fog = new THREE.FogExp2(this.background, 0.00062);
    this.scene.background = new THREE.Color(this.background);

    this.camera = new THREE.PerspectiveCamera(
        this.viewAngle,
        this.aspect,
        this.near,
        this.far
    );

    this.camera.position.set(0, 0, 1200);
    this.camera.lookAt(new THREE.Vector3(0, 0, 0));

    this.controls = new THREE.OrbitControls(this.camera);
    this.controls.maxDistance = 2500;
    this.controls.minDistance = 0;

    // Set Lights //
    let pointLight = new THREE.PointLight(0xDDDDDD);
    pointLight.position.set(450, 450, -800);
    this.scene.add(pointLight);
    pointLight = new THREE.PointLight(0xEEEEEE);
    pointLight.position.set(-250, -850, 800);
    this.scene.add(pointLight);
    let ambient = new THREE.AmbientLight(0x9f9f9f);
    ambient.position.set(1, 200, -200);
    this.scene.add(ambient);
  };

  music = () => {
    const youtube = document.createElement('iframe');
    youtube.width=1;
    youtube.height=1;
    const videoid = '3vnZnuqgh7U';
    youtube.wmode='transparent';
    const html ='https://www.youtube.com/embed/3vnZnuqgh7U?rel=0&autoplay=1';
    youtube.src = encodeURI(html); // 'data:text/html;charset=utf-8,' + // e4GJsV3PzsI // gkyFQTUR-rA
    youtube.frameborder=0;
    document.body.appendChild(youtube);
    const overlay = document.createElement('div');
    const link = document.createElement('a');
    const image = document.createElement('img');
    image.src = 'https://img.youtube.com/vi/3vnZnuqgh7U/sddefault.jpg';
    image.width = 60;
    image.height = 45;
    image.style.float = 'left';
    image.style.margin = '0 0 0 15px';
    link.href = html;
    link.innerHTML = 'Music by Lorn | Stuck in the System';
    overlay.style.position = 'absolute';
    overlay.style.bottom = '15px';
    overlay.style.left = '0';
    overlay.style.lineHeight = '45px';
    overlay.style.zIndex = '9999';
    link.style.color = '#FFF';
    link.style.padding = '15px';
    overlay.appendChild(image);
    overlay.appendChild(link);
    document.body.appendChild(overlay);
  }

  setEffects = () => {
    this.effect = new THREE.AnaglyphEffect(this.renderer);
    this.effect.setSize(this.width, this.height);
    // this.composer = new THREE.EffectComposer(this.renderer);
    // this.composer.addPass(new THREE.RenderPass(this.scene, this.camera));

    // const renderPass = new THREE.RenderPass(this.scene, this.camera);
    // this.composer.addPass(renderPass);

    // this.effect = new THREE.ShaderPass(THREE.MirrorShader);
    // this.effect.uniforms.side.value = this.mirror;

    // this.composer.addPass(this.effect);

    // this.rfrag = new THREE.ShaderPass(THREE.RenderFragment);
    // this.rfrag.uniforms.scale.value = this.scale;
    // this.rfrag.uniforms.ratio.value = this.ratio;
    // this.rfrag.uniforms.time.value = this.frames;
    // this.rfrag.renderToScreen = true;
    // this.composer.addPass(this.rfrag);
  };

  hitRnd = () => {
    const { x, y, z } = this.emitter;
    this.frames++;
    let iter = 2.25;
    let amps = 40 + Math.abs(this.amps * Math.cos((this.frames * 0.2 ) * Math.PI / 180));
    let sVar = amps * Math.sin(this.frames * iter * Math.PI / 180);
    let cVar = amps * Math.cos(this.frames * iter * Math.PI / 180);
    let dVar = amps * Math.cos((this.frames * 0.4 ) * 8 * Math.PI / 180);
    this.makeParticle(x + sVar, y + cVar, z + dVar);
    this.makeParticle(x - sVar, y - cVar, z + dVar);
  };

  makeParticle = (mx, my, mz) => {
    const geometry = new THREE.BoxBufferGeometry(this.size / 2, this.size  * 3, this.size * 8);
    const sphere = new THREE.Mesh(
      geometry,
      new THREE.MeshPhongMaterial({ color: 0xFFFFFF, specular: 0x999999 })
    );
    sphere.castShadow = true;
    sphere.receiveShadow = true;

    const point = new Particle({
      size: this.size,
      x: mx,
      y: my,
      z: mz,
      vx: -(0.0 - mx) * 0.005,
      vy: -(0.0 - my) * 0.005,
      vz: this.speed,
      box: this.box,
      settings: this.settings,
      ref: sphere,
      decay: 0.000015
    });

    sphere.position.set(mx, my, mz);
    sphere.scale.x = this.size;
    sphere.scale.y = this.size;
    sphere.scale.z = this.size;
    const ex = this.emitter.x;
    const ey = this.emitter.y;
    const ry = Math.atan2(my - ey, mx - ex) * Math.PI / 180;

    sphere.rotateZ((15 + ry) * 180 / Math.PI);

    // const cRed = Math.sin(this.frames * 0.25 * Math.PI / 180);
    // const cGreen = Math.cos(this.frames * 0.25 * Math.PI / 180);
    // const cBlue = 1 - Math.sin(this.frames * 0.25 * Math.PI / 180);

    // sphere.material.color.setRGB(cRed, cGreen ,cBlue);

    const particleColor = Math.abs(Math.sin(this.frames * 0.25 * Math.PI / 180) * 0.75);
    const offsetColor  = 0.85 - Math.abs(Math.cos(this.frames * 0.25 * Math.PI / 180) );
    sphere.material.color.setRGB(offsetColor, offsetColor, offsetColor);
    // sphere.material.color.setHSL(particleColor,1,0.5);

    this.particles.push(point);
    this.scene.add(sphere);
  };

  checkParticles = () => {
    for (let i = 0; i < this.particles.length; i++) {
      const part = this.particles[i];
      part.update();
      part.ref.position.set(
        part.x,
        part.y,
        part.z
      );
      part.ref.scale.x = part.size;
      part.ref.scale.y = part.size;
      part.ref.scale.z = part.size;
      if (part.life > 800 || part.size < 0.0) {
        this.scene.remove(part.ref);
        this.particles.splice(i, 1);
      }
    }
  };

  cameraLoop = () => {
    const damp = 0.01;
    this.camPosition.x = this.camPosition.x - (this.camPosition.x - this.trsPosition.x) * damp;
    this.camPosition.y = this.camPosition.y - (this.camPosition.y - this.trsPosition.y) * damp;
    this.camPosition.z = this.camPosition.z - (this.camPosition.z - this.trsPosition.z) * 0.004;

    this.camera.position.set(
      this.camPosition.x,
      this.camPosition.y,
      this.camPosition.z
    );
    this.camera.lookAt(new THREE.Vector3(0, 0, 0));

    if(!this.camTimeoutx && Math.random() * 260 > 200) {
      const tempRand = 100 + Math.random() * 1000;
      this.trsPosition.x = Math.random() * 255 > 200 ?
        Math.random() * 200 > 100 ? -(tempRand) : tempRand : 0;
      this.camTimeoutx = true;
      setTimeout(
        () => { this.camTimeoutx = false; },
        6000 + (1000 * Math.random() * 20)
      );
    }
    if(!this.camTimeouty && Math.random() * 260 > 200) {
      const tempRand = 100 + Math.random() * 1000;
      this.trsPosition.y = Math.random() * 255 > 200 ?
        Math.random() * 200 > 100 ? tempRand : -(tempRand) : 0;
      this.camTimeouty = true;
      setTimeout(
        () => { this.camTimeouty = false; },
        6000 + (1000 * Math.random() * 20)
      );
    }
    if(!this.camTimeoutz && Math.random() * 255 > 253) {
      this.trsPosition.z = Math.random() * 200 > 150 ? 100 + Math.random() * 100 : -(100 + Math.random() * 100);
      this.camTimeoutz = true;
      setTimeout(
        () => { this.camTimeoutz = false; },
        24000 + (1200 * Math.random() * 7)
      );
    }
    if (this.camPosition.x == 0 && this.camPosition.y == 0 ) {
      this.camera.rotationZ((this.frames * 0.1) * Math.PI / 180);
    }
  };
  dist = (a, b, c, d) =>{
    return Math.sqrt(((a - c) * (a - c) + (b - d) * (b - d)));
  }
  renderScene = () => {
    // this.composer.render();
    // this.renderer.render(this.scene, this.camera);
    this.effect.render(this.scene, this.camera);
  };

  renderLoop = () => {
    this.checkParticles();

    if(Math.random() * 255 > 245){
      this.speed = 5.0 + Math.random() * 10;
    }

    if(this.particles.length < 1800 && this.frames % 2 == 0) {
      this.hitRnd();
    }

    this.cameraLoop();
    this.renderScene();
    this.frames++;
    // this.rfrag.uniforms.time.value = this.frames;
    window.requestAnimationFrame(this.renderLoop);
  };
}<commit_msg>working on camear loops<commit_after>// require('../shader/VertLinesFragment');

import dat from 'dat-gui';
import THREE from '../Three';
import Particle from './Particle-alt';

// Render Class Object //
export default class Render {
  constructor() {
    this.frames = 360;
    this.size = 5;
    this.speed = 5.0;
    this.amps = 500;
    this.scale = 1.0;
    this.ratio = 1024;
    this.mirror = 4;

    // Camera Stuff and Viewport //
    this.width = window.innerWidth;
    this.height = window.innerHeight;
    this.aspect = this.width / this.height;
    this.devicePixelRatio = window.devicePixelRatio;
    this.viewAngle = 65;
    this.aspect = this.width / this.height;
    this.near = 1;
    this.far = 20000;
    // Particles Stuff //

    this.particles = [];
    this.particleColor = 360;
    this.background = 0x333333;
    this.camPosition = {
      x: -1500.0,
      y: -90.0,
      z: -200.0
    };
    this.trsPosition = {
      x: -1500.0,
      y: -90.0,
      z: -200.0
    };
    this.emitter = {
      x: 0,
      y: 0,
      z: -1200
    };
    const bsize = 6000;
    this.box = {
      top: bsize,
      left: -bsize,
      bottom: -bsize,
      right: bsize,
    };
    this.settings = {
      gravity: 0.0,
      bounce: 0.35,
    };
    this.camTimeoutx = true;
    this.camTimeouty = true;
    this.camTimeoutz = true;
    setTimeout(
      () => {
        this.camTimeoutx = false;
        this.camTimeouty = false;
        this.camTimeoutz = false;
      },
      3000 + (600 * Math.random() * 10)
    );
    window.addEventListener('resize', this.resize, true);
    window.addEventListener('click', () => {
      console.log(this.camera.position);
    }, true);
    this.setRender();
    this.setEffects();
    // this.createGUI();
    this.renderLoop();
    this.music();
  }

  resize = () => {
    this.width = window.innerWidth;
    this.height = window.innerHeight;
    this.camera.updateProjectionMatrix();
    this.renderer.setSize(this.width, this.height);
  };

  createGUI = () => {
    this.options = {
      gravity: this.settings.gravity * 100,
      bounce: this.settings.bounce * 100,
      amps: this.amps
    };
    this.gui = new dat.GUI();
    const folderRender = this.gui.addFolder('Particle Options');
    // folderRender.add(this.options, 'gravity', 0, 100).step(1)
    //   .onFinishChange((value) => {
    //     this.settings.gravity = value * 0.01;
    //   });
    // folderRender.add(this.options, 'bounce', 0, 100).step(1)
    //   .onFinishChange((value) => {
    //     this.settings.bounce = value * 0.01;
    //   });
    folderRender.add(this.options, 'amps', 0, 800).step(1)
    .onFinishChange((value) => {
      this.amps = value;
    });
  }

  setRender = () => {
    // Set Render and Scene //
    this.renderer = new THREE.WebGLRenderer();
    this.renderer.setSize(this.width, this.height);
    this.renderer.setPixelRatio(this.devicePixelRatio);
    document.body.appendChild(this.renderer.domElement);

    this.scene = new THREE.Scene();
    this.scene.fog = new THREE.FogExp2(this.background, 0.00062);
    this.scene.background = new THREE.Color(this.background);

    this.camera = new THREE.PerspectiveCamera(
        this.viewAngle,
        this.aspect,
        this.near,
        this.far
    );

    this.camera.position.set(0, 0, 1200);
    this.camera.lookAt(new THREE.Vector3(0, 0, 0));

    this.controls = new THREE.OrbitControls(this.camera);
    this.controls.maxDistance = 2500;
    this.controls.minDistance = 0;

    // Set Lights //
    let pointLight = new THREE.PointLight(0xDDDDDD);
    pointLight.position.set(450, 450, -800);
    this.scene.add(pointLight);
    pointLight = new THREE.PointLight(0xEEEEEE);
    pointLight.position.set(-250, -850, 800);
    this.scene.add(pointLight);
    let ambient = new THREE.AmbientLight(0x9f9f9f);
    ambient.position.set(1, 200, -200);
    this.scene.add(ambient);
  };

  music = () => {
    const youtube = document.createElement('iframe');
    youtube.width=1;
    youtube.height=1;
    const videoid = '3vnZnuqgh7U';
    youtube.wmode='transparent';
    const html ='https://www.youtube.com/embed/3vnZnuqgh7U?rel=0&autoplay=1';
    youtube.src = encodeURI(html); // 'data:text/html;charset=utf-8,' + // e4GJsV3PzsI // gkyFQTUR-rA
    youtube.frameborder=0;
    document.body.appendChild(youtube);
    const overlay = document.createElement('div');
    const link = document.createElement('a');
    const image = document.createElement('img');
    image.src = 'https://img.youtube.com/vi/3vnZnuqgh7U/sddefault.jpg';
    image.width = 60;
    image.height = 45;
    image.style.float = 'left';
    image.style.margin = '0 0 0 15px';
    link.href = html;
    link.innerHTML = 'Music by Lorn | Stuck in the System';
    overlay.style.position = 'absolute';
    overlay.style.bottom = '15px';
    overlay.style.left = '0';
    overlay.style.lineHeight = '45px';
    overlay.style.zIndex = '9999';
    link.style.color = '#FFF';
    link.style.padding = '15px';
    overlay.appendChild(image);
    overlay.appendChild(link);
    document.body.appendChild(overlay);
  }

  setEffects = () => {
    this.effect = new THREE.AnaglyphEffect(this.renderer);
    this.effect.setSize(this.width, this.height);
    // this.composer = new THREE.EffectComposer(this.renderer);
    // this.composer.addPass(new THREE.RenderPass(this.scene, this.camera));

    // const renderPass = new THREE.RenderPass(this.scene, this.camera);
    // this.composer.addPass(renderPass);

    // this.effect = new THREE.ShaderPass(THREE.MirrorShader);
    // this.effect.uniforms.side.value = this.mirror;

    // this.composer.addPass(this.effect);

    // this.rfrag = new THREE.ShaderPass(THREE.RenderFragment);
    // this.rfrag.uniforms.scale.value = this.scale;
    // this.rfrag.uniforms.ratio.value = this.ratio;
    // this.rfrag.uniforms.time.value = this.frames;
    // this.rfrag.renderToScreen = true;
    // this.composer.addPass(this.rfrag);
  };

  hitRnd = () => {
    const { x, y, z } = this.emitter;
    this.frames++;
    let iter = 2.25;
    let amps = 40 + Math.abs(this.amps * Math.cos((this.frames * 0.2 ) * Math.PI / 180));
    let sVar = amps * Math.sin(this.frames * iter * Math.PI / 180);
    let cVar = amps * Math.cos(this.frames * iter * Math.PI / 180);
    let dVar = amps * Math.cos((this.frames * 0.4 ) * 8 * Math.PI / 180);
    this.makeParticle(x + sVar, y + cVar, z + dVar);
    this.makeParticle(x - sVar, y - cVar, z + dVar);
  };

  makeParticle = (mx, my, mz) => {
    const geometry = new THREE.BoxBufferGeometry(this.size / 2, this.size  * 3, this.size * 8);
    const sphere = new THREE.Mesh(
      geometry,
      new THREE.MeshPhongMaterial({ color: 0xFFFFFF, specular: 0x999999 })
    );
    sphere.castShadow = true;
    sphere.receiveShadow = true;

    const point = new Particle({
      size: this.size,
      x: mx,
      y: my,
      z: mz,
      vx: -(0.0 - mx) * 0.005,
      vy: -(0.0 - my) * 0.005,
      vz: this.speed,
      box: this.box,
      settings: this.settings,
      ref: sphere,
      decay: 0.000015
    });

    sphere.position.set(mx, my, mz);
    sphere.scale.x = this.size;
    sphere.scale.y = this.size;
    sphere.scale.z = this.size;
    const ex = this.emitter.x;
    const ey = this.emitter.y;
    const ry = Math.atan2(my - ey, mx - ex) * Math.PI / 180;

    sphere.rotateZ((15 + ry) * 180 / Math.PI);

    // const cRed = Math.sin(this.frames * 0.25 * Math.PI / 180);
    // const cGreen = Math.cos(this.frames * 0.25 * Math.PI / 180);
    // const cBlue = 1 - Math.sin(this.frames * 0.25 * Math.PI / 180);

    // sphere.material.color.setRGB(cRed, cGreen ,cBlue);

    const particleColor = Math.abs(Math.sin(this.frames * 0.25 * Math.PI / 180) * 0.75);
    const offsetColor  = 0.85 - Math.abs(Math.cos(this.frames * 0.25 * Math.PI / 180) );
    sphere.material.color.setRGB(offsetColor, offsetColor, offsetColor);
    // sphere.material.color.setHSL(particleColor,1,0.5);

    this.particles.push(point);
    this.scene.add(sphere);
  };

  checkParticles = () => {
    for (let i = 0; i < this.particles.length; i++) {
      const part = this.particles[i];
      part.update();
      part.ref.position.set(
        part.x,
        part.y,
        part.z
      );
      part.ref.scale.x = part.size;
      part.ref.scale.y = part.size;
      part.ref.scale.z = part.size;
      if (part.life > 800 || part.size < 0.0) {
        this.scene.remove(part.ref);
        this.particles.splice(i, 1);
      }
    }
  };

  cameraLoop = () => {
    const damp = 0.01;
    this.camPosition.x = this.camPosition.x - (this.camPosition.x - this.trsPosition.x) * damp;
    this.camPosition.y = this.camPosition.y - (this.camPosition.y - this.trsPosition.y) * damp;
    this.camPosition.z = this.camPosition.z - (this.camPosition.z - this.trsPosition.z) * 0.004;

    this.camera.position.set(
      this.camPosition.x,
      this.camPosition.y,
      this.camPosition.z
    );
    this.camera.lookAt(new THREE.Vector3(0, 0, 0));

    if(!this.camTimeoutx && Math.random() * 260 > 200) {
      const tempRand = 100 + Math.random() * 1000;
      this.trsPosition.x = Math.random() * 255 > 200 ?
        Math.random() * 250 > 100 ? -(tempRand) : tempRand : 0;
      this.camTimeoutx = true;
      setTimeout(
        () => { this.camTimeoutx = false; },
        6000 + (1000 * Math.random() * 20)
      );
    }
    if(!this.camTimeouty && Math.random() * 260 > 200) {
      const tempRand = 100 + Math.random() * 1000;
      this.trsPosition.y = Math.random() * 255 > 200 ?
        Math.random() * 250 > 100 ? tempRand : -(tempRand) : 0;
      this.camTimeouty = true;
      setTimeout(
        () => { this.camTimeouty = false; },
        6000 + (1000 * Math.random() * 20)
      );
    }
    if(!this.camTimeoutz && Math.random() * 255 > 253) {
      this.trsPosition.z = Math.random() * 200 > 150 ? 100 + Math.random() * 100 : -(100 + Math.random() * 100);
      this.camTimeoutz = true;
      setTimeout(
        () => { this.camTimeoutz = false; },
        18000 + (1100 * Math.random() * 7)
      );
    }
    if (this.camPosition.x == 0 && this.camPosition.y == 0 ) {
      this.camera.rotationZ((this.frames * 0.1) * Math.PI / 180);
    }
  };
  dist = (a, b, c, d) =>{
    return Math.sqrt(((a - c) * (a - c) + (b - d) * (b - d)));
  }
  renderScene = () => {
    // this.composer.render();
    // this.renderer.render(this.scene, this.camera);
    this.effect.render(this.scene, this.camera);
  };

  renderLoop = () => {
    this.checkParticles();

    if(Math.random() * 255 > 245){
      this.speed = 5.0 + Math.random() * 10;
    }

    if(this.particles.length < 1800 && this.frames % 2 == 0) {
      this.hitRnd();
    }

    this.cameraLoop();
    this.renderScene();
    this.frames++;
    // this.rfrag.uniforms.time.value = this.frames;
    window.requestAnimationFrame(this.renderLoop);
  };
}<|endoftext|>


<commit_before>import React, {Component, PropTypes} from 'react';
import ReactDOM from 'react-dom';
import Manager from '../Manager';
import {closest, events, vendorPrefix} from '../utils';
import invariant from 'invariant';

// Export Higher Order Sortable Container Component
export default function SortableContainer(WrappedComponent, config = {withRef: false}) {
	return class extends Component {
		constructor() {
			super();
			this.manager = new Manager();
			this.events = {
				start: this.handleStart,
				move: this.cancel,
				end: this.cancel
			};
		}
		static displayName = (WrappedComponent.displayName) ? `SortableList(${WrappedComponent.displayName})` : 'SortableList';
        static WrappedComponent = WrappedComponent;
		static defaultProps = {
			axis: 'y',
			transitionDuration: 300,
			pressDelay: 0,
			useWindowAsScrollContainer: false,
			hideSortableGhost: true,
			contentWindow: window,
			lockToContainerEdges: false
		};
		static propTypes = {
			axis: PropTypes.string,
			lockAxis: PropTypes.string,
			helperClass: PropTypes.string,
			transitionDuration: PropTypes.number,
			contentWindow: PropTypes.any,
			onSortStart: PropTypes.func,
			onSortMove: PropTypes.func,
			onSortEnd: PropTypes.func,
			pressDelay: PropTypes.number,
			useDragHandle: PropTypes.bool,
			useWindowAsScrollContainer: PropTypes.bool,
			hideSortableGhost: PropTypes.bool,
			lockToContainerEdges: PropTypes.bool
		};
		static childContextTypes = {
			manager: PropTypes.object.isRequired
		};
		state = {};
		getChildContext() {
			return {
				manager: this.manager
			};
		}
		componentDidMount() {
			let {contentWindow} = this.props;

			this.container = ReactDOM.findDOMNode(this);
			this.document = this.container.ownerDocument || document;
			this.scrollContainer = (this.props.useWindowAsScrollContainer) ? this.document.body : this.container;
			this.contentWindow = (typeof contentWindow == 'function') ? contentWindow() : contentWindow;

			for (let key in this.events) {
				events[key].forEach(eventName => this.container.addEventListener(eventName, this.events[key], false));
			}
		}
		componentWillUnmount() {
			for (let key in this.events) {
				events[key].forEach(eventName => this.container.removeEventListener(eventName, this.events[key]));
			}
		}
		handleStart = (e) => {
			let node = closest(e.target, (el) => el.sortableInfo != null);

			if (node && !this.state.sorting && node.sortableInfo) {
				let {useDragHandle} = this.props;
				let {index, collection} = node.sortableInfo;

				if (useDragHandle && !e.target.sortableHandle) return;

				this.manager.active = {index, collection};
				this.pressTimer = setTimeout(() => this.handlePress(e), this.props.pressDelay);
			}
		};
		cancel = () => {
			if (!this.state.sorting) {
				clearTimeout(this.pressTimer);
				this.manager.active = null;
			}
		};
		handlePress = (e) => {
			let active = this.manager.getActive();

			if (active) {
				let {axis, onSortStart, helperClass, useWindowAsScrollContainer} = this.props;
				let {node, index, collection} = active;

				let containerBoundingRect = this.container.getBoundingClientRect();

				this.node = node;
				this.width = node.offsetWidth;
				this.height = node.offsetHeight;
				this.dimension = (axis == 'x') ? this.width : this.height;
				this.boundingClientRect = node.getBoundingClientRect();
				this.index = index;
				this.newIndex = index;

				let edge = this.edge = (axis == 'x') ? 'Left' : 'Top';
				this.offsetEdge = this.getEdgeOffset(edge, node);
				this.initialOffset = this.getOffset(e);
				this.initialScroll = this.scrollContainer[`scroll${edge}`];

				this.helper = this.document.body.appendChild(node.cloneNode(true));
				this.helper.style.position = 'fixed';
				this.helper.style.top = `${this.boundingClientRect.top}px`;
				this.helper.style.left = `${this.boundingClientRect.left}px`;
				this.helper.style.width = `${this.width}px`;

				if (axis == 'x') {
					this.minTranslate = ((useWindowAsScrollContainer) ? 0 : containerBoundingRect.left) - this.boundingClientRect.left - this.width/2;
					this.maxTranslate = ((useWindowAsScrollContainer) ? this.contentWindow.innerWidth : containerBoundingRect.left + containerBoundingRect.width) - this.boundingClientRect.left - this.width/2;
				} else {
					this.minTranslate = ((useWindowAsScrollContainer) ? 0 : containerBoundingRect.top) - this.boundingClientRect.top - this.height/2;
					this.maxTranslate = ((useWindowAsScrollContainer) ? this.contentWindow.innerHeight : containerBoundingRect.top + containerBoundingRect.height) - this.boundingClientRect.top - this.height/2;
				}

				if (helperClass) {
					this.helper.classList.add(helperClass.split(' '));
				}

				this.listenerNode = (e.touches) ? node : this.contentWindow;
				events.move.forEach(eventName => this.listenerNode.addEventListener(eventName, this.handleSortMove, false));
				events.end.forEach(eventName => this.listenerNode.addEventListener(eventName, this.handleSortEnd, false));

				this.setState({
					sorting: true,
					sortingIndex: index
				});

				if (onSortStart) onSortStart({node, index, collection}, e);
			}
		}
		handleSortMove = (e) => {
			let {onSortMove} = this.props;
			e.preventDefault(); // Prevent scrolling on mobile

			this.updatePosition(e);
			this.animateNodes();
			this.autoscroll();

			if (onSortMove) onSortMove(e);
		}
		handleSortEnd = (e) => {
			let {hideSortableGhost, onSortEnd} = this.props;
			let {collection} = this.manager.active;

			// Remove the event listeners if the node is still in the DOM
			if (this.listenerNode) {
				events.move.forEach(eventName => this.listenerNode.removeEventListener(eventName, this.handleSortMove));
				events.end.forEach(eventName => this.listenerNode.removeEventListener(eventName, this.handleSortEnd));
			}

			// Remove the helper from the DOM
			this.helper.parentNode.removeChild(this.helper);

			if (hideSortableGhost && this.node) {
				this.node.style.visibility = '';
			}

			let nodes = this.manager.refs[collection];
			for (let i = 0, len = nodes.length; i < len; i++) {
				let node = nodes[i];
				let {node: el} = node;
				node.edgeOffset = null; // Clear the cached offsetTop / offsetLeft value

				// Remove the transforms / transitions
				el.style[`${vendorPrefix}Transform`] = '';
				el.style[`${vendorPrefix}TransitionDuration`] = '';
			}

			if (typeof onSortEnd == 'function') {
				onSortEnd({
					oldIndex: this.index,
					newIndex: this.newIndex,
					collection: collection
				}, e);
			}

			// Stop autoscroll
			clearInterval(this.autoscrollInterval);
			this.autoscrollInterval = null;

			// Update state
			this.manager.active = null;
			this.setState({
				sorting: false,
				sortingIndex: null
			});
		}
		getEdgeOffset(edge, node, offset = 0) {
			// Get the actual offsetTop / offsetLeft value, no matter how deep the node is nested
			if (node) {
				if (node.parentNode !== this.container) {
					return this.getEdgeOffset(edge, node.parentNode, offset + node[`offset${edge}`]);
				} else {
					return node[`offset${edge}`] + offset;
				}
			}
		}
		getOffset(e) {
			return {
				x: (e.touches) ? e.touches[0].clientX : e.clientX,
				y: (e.touches) ? e.touches[0].clientY : e.clientY
			}
		}
		updatePosition(e) {
			let {axis, lockAxis, lockToContainerEdges} = this.props;
			let offset = this.getOffset(e);
			let translate = {
				x: offset.x - this.initialOffset.x,
				y: offset.y - this.initialOffset.y
			};

			this.translate = translate[axis];

			if (lockToContainerEdges) {
				if (translate[axis] < this.minTranslate) {
					translate[axis] = this.minTranslate;
				} else if (translate[axis] > this.maxTranslate) {
					translate[axis] = this.maxTranslate;
				}
			}

			switch (lockAxis) {
				case 'x':
					translate.y = 0;
					break;
				case 'y':
					translate.x = 0;
					break;
			}

			this.helper.style[`${vendorPrefix}Transform`] = `translate3d(${translate.x}px,${translate.y}px, 0)`;
		}
		animateNodes() {
			let {axis, transitionDuration, hideSortableGhost} = this.props;
			let nodes = this.manager.getOrderedRefs();
			let deltaScroll = this.scrollContainer[`scroll${this.edge}`] - this.initialScroll;
			let sortingOffset = this.offsetEdge + this.translate + deltaScroll;
			this.newIndex = null;

			for (let i = 0, len = nodes.length; i < len; i++) {
				let {node, index, edgeOffset} = nodes[i];
				let dimension = (axis == 'x') ? node.offsetWidth : node.offsetHeight;
				let offset = (this.dimension > dimension) ? dimension / 2 : this.dimension / 2;
				let translate = 0;
				let translateX = 0;
				let translateY = 0;

				// If we haven't cached the node's offsetTop / offsetLeft value
				if (edgeOffset == null) {
					nodes[i].edgeOffset = edgeOffset = this.getEdgeOffset(this.edge, node);
				}

				// If the node is the one we're currently animating, skip it
				if (index === this.index) {
					if (hideSortableGhost) {
						node.style.visibility = 'hidden';
					}
					continue;
				}

				if (transitionDuration) {
					node.style[`${vendorPrefix}TransitionDuration`] = `${transitionDuration}ms`;
				}
				if (index > this.index && (sortingOffset + offset >= edgeOffset)) {
					translate = -this.dimension;
					this.newIndex = index;
				}
				else if (index < this.index && (sortingOffset <= edgeOffset + offset)) {
					translate = this.dimension;

					if (this.newIndex == null) {
						this.newIndex = index;
					}
				}

				if (axis == 'x') {
					translateX = translate;
				} else {
					translateY = translate;
				}

				node.style[`${vendorPrefix}Transform`] = `translate3d(${translateX}px,${translateY}px,0)`;
			}
			if (this.newIndex == null) {
				this.newIndex = this.index;
			}
		}
		autoscroll = () => {
			let translate = this.translate;
			let direction;
			let speed = 1;
			let acceleration = 10;

			if (translate >= this.maxTranslate - this.dimension/2) {
				direction = 1; // Scroll Down
				speed = acceleration * Math.abs((this.maxTranslate - this.dimension/2 - translate) / this.dimension);
			} else if (translate <= this.minTranslate + this.dimension/2) {
				direction = -1; // Scroll Up
				speed = acceleration * Math.abs((translate - this.dimension/2 - this.minTranslate) / this.dimension);
			}

			if (this.autoscrollInterval) {
				clearTimeout(this.autoscrollInterval);
				this.autoscrollInterval = null;
				this.isAutoScrolling = false;
			}

			if (direction) {
				this.autoscrollInterval = setInterval(() => {
					this.isAutoScrolling = true;
					let offset = 1 * speed * direction;
					this.scrollContainer[`scroll${this.edge}`] += offset;
					this.translate += offset;
					this.animateNodes();
				}, 5);
			}
		};
		getWrappedInstance() {
            invariant(config.withRef, 'To access the wrapped instance, you need to pass in {withRef: true} as the second argument of the SortableContainer() call');
            return this.refs.wrappedInstance;
        }
        render() {
            const ref = (config.withRef) ? 'wrappedInstance' : null;

			return <WrappedComponent ref={ref} {...this.props} {...this.state} />;
		}
	}
}
<commit_msg>Immediately hide the sortableGhost on sortStart (#19)<commit_after>import React, {Component, PropTypes} from 'react';
import ReactDOM from 'react-dom';
import Manager from '../Manager';
import {closest, events, vendorPrefix} from '../utils';
import invariant from 'invariant';

// Export Higher Order Sortable Container Component
export default function SortableContainer(WrappedComponent, config = {withRef: false}) {
	return class extends Component {
		constructor() {
			super();
			this.manager = new Manager();
			this.events = {
				start: this.handleStart,
				move: this.cancel,
				end: this.cancel
			};
		}
		static displayName = (WrappedComponent.displayName) ? `SortableList(${WrappedComponent.displayName})` : 'SortableList';
        static WrappedComponent = WrappedComponent;
		static defaultProps = {
			axis: 'y',
			transitionDuration: 300,
			pressDelay: 0,
			useWindowAsScrollContainer: false,
			hideSortableGhost: true,
			contentWindow: window,
			lockToContainerEdges: false
		};
		static propTypes = {
			axis: PropTypes.string,
			lockAxis: PropTypes.string,
			helperClass: PropTypes.string,
			transitionDuration: PropTypes.number,
			contentWindow: PropTypes.any,
			onSortStart: PropTypes.func,
			onSortMove: PropTypes.func,
			onSortEnd: PropTypes.func,
			pressDelay: PropTypes.number,
			useDragHandle: PropTypes.bool,
			useWindowAsScrollContainer: PropTypes.bool,
			hideSortableGhost: PropTypes.bool,
			lockToContainerEdges: PropTypes.bool
		};
		static childContextTypes = {
			manager: PropTypes.object.isRequired
		};
		state = {};
		getChildContext() {
			return {
				manager: this.manager
			};
		}
		componentDidMount() {
			let {contentWindow} = this.props;

			this.container = ReactDOM.findDOMNode(this);
			this.document = this.container.ownerDocument || document;
			this.scrollContainer = (this.props.useWindowAsScrollContainer) ? this.document.body : this.container;
			this.contentWindow = (typeof contentWindow == 'function') ? contentWindow() : contentWindow;

			for (let key in this.events) {
				events[key].forEach(eventName => this.container.addEventListener(eventName, this.events[key], false));
			}
		}
		componentWillUnmount() {
			for (let key in this.events) {
				events[key].forEach(eventName => this.container.removeEventListener(eventName, this.events[key]));
			}
		}
		handleStart = (e) => {
			let node = closest(e.target, (el) => el.sortableInfo != null);

			if (node && !this.state.sorting && node.sortableInfo) {
				let {useDragHandle} = this.props;
				let {index, collection} = node.sortableInfo;

				if (useDragHandle && !e.target.sortableHandle) return;

				this.manager.active = {index, collection};
				this.pressTimer = setTimeout(() => this.handlePress(e), this.props.pressDelay);
			}
		};
		cancel = () => {
			if (!this.state.sorting) {
				clearTimeout(this.pressTimer);
				this.manager.active = null;
			}
		};
		handlePress = (e) => {
			let active = this.manager.getActive();

			if (active) {
				let {axis, onSortStart, helperClass, hideSortableGhost, useWindowAsScrollContainer} = this.props;
				let {node, index, collection} = active;

				let containerBoundingRect = this.container.getBoundingClientRect();

				this.node = node;
				this.width = node.offsetWidth;
				this.height = node.offsetHeight;
				this.dimension = (axis == 'x') ? this.width : this.height;
				this.boundingClientRect = node.getBoundingClientRect();
				this.index = index;
				this.newIndex = index;

				if (hideSortableGhost) {
					node.style.visibility = 'hidden';
				}

				let edge = this.edge = (axis == 'x') ? 'Left' : 'Top';
				this.offsetEdge = this.getEdgeOffset(edge, node);
				this.initialOffset = this.getOffset(e);
				this.initialScroll = this.scrollContainer[`scroll${edge}`];

				this.helper = this.document.body.appendChild(node.cloneNode(true));
				this.helper.style.position = 'fixed';
				this.helper.style.top = `${this.boundingClientRect.top}px`;
				this.helper.style.left = `${this.boundingClientRect.left}px`;
				this.helper.style.width = `${this.width}px`;

				if (axis == 'x') {
					this.minTranslate = ((useWindowAsScrollContainer) ? 0 : containerBoundingRect.left) - this.boundingClientRect.left - this.width/2;
					this.maxTranslate = ((useWindowAsScrollContainer) ? this.contentWindow.innerWidth : containerBoundingRect.left + containerBoundingRect.width) - this.boundingClientRect.left - this.width/2;
				} else {
					this.minTranslate = ((useWindowAsScrollContainer) ? 0 : containerBoundingRect.top) - this.boundingClientRect.top - this.height/2;
					this.maxTranslate = ((useWindowAsScrollContainer) ? this.contentWindow.innerHeight : containerBoundingRect.top + containerBoundingRect.height) - this.boundingClientRect.top - this.height/2;
				}

				if (helperClass) {
					this.helper.classList.add(helperClass.split(' '));
				}

				this.listenerNode = (e.touches) ? node : this.contentWindow;
				events.move.forEach(eventName => this.listenerNode.addEventListener(eventName, this.handleSortMove, false));
				events.end.forEach(eventName => this.listenerNode.addEventListener(eventName, this.handleSortEnd, false));

				this.setState({
					sorting: true,
					sortingIndex: index
				});

				if (onSortStart) onSortStart({node, index, collection}, e);
			}
		}
		handleSortMove = (e) => {
			let {onSortMove} = this.props;
			e.preventDefault(); // Prevent scrolling on mobile

			this.updatePosition(e);
			this.animateNodes();
			this.autoscroll();

			if (onSortMove) onSortMove(e);
		}
		handleSortEnd = (e) => {
			let {hideSortableGhost, onSortEnd} = this.props;
			let {collection} = this.manager.active;

			// Remove the event listeners if the node is still in the DOM
			if (this.listenerNode) {
				events.move.forEach(eventName => this.listenerNode.removeEventListener(eventName, this.handleSortMove));
				events.end.forEach(eventName => this.listenerNode.removeEventListener(eventName, this.handleSortEnd));
			}

			// Remove the helper from the DOM
			this.helper.parentNode.removeChild(this.helper);

			if (hideSortableGhost && this.node) {
				this.node.style.visibility = '';
			}

			let nodes = this.manager.refs[collection];
			for (let i = 0, len = nodes.length; i < len; i++) {
				let node = nodes[i];
				let {node: el} = node;
				node.edgeOffset = null; // Clear the cached offsetTop / offsetLeft value

				// Remove the transforms / transitions
				el.style[`${vendorPrefix}Transform`] = '';
				el.style[`${vendorPrefix}TransitionDuration`] = '';
			}

			if (typeof onSortEnd == 'function') {
				onSortEnd({
					oldIndex: this.index,
					newIndex: this.newIndex,
					collection: collection
				}, e);
			}

			// Stop autoscroll
			clearInterval(this.autoscrollInterval);
			this.autoscrollInterval = null;

			// Update state
			this.manager.active = null;
			this.setState({
				sorting: false,
				sortingIndex: null
			});
		}
		getEdgeOffset(edge, node, offset = 0) {
			// Get the actual offsetTop / offsetLeft value, no matter how deep the node is nested
			if (node) {
				if (node.parentNode !== this.container) {
					return this.getEdgeOffset(edge, node.parentNode, offset + node[`offset${edge}`]);
				} else {
					return node[`offset${edge}`] + offset;
				}
			}
		}
		getOffset(e) {
			return {
				x: (e.touches) ? e.touches[0].clientX : e.clientX,
				y: (e.touches) ? e.touches[0].clientY : e.clientY
			}
		}
		updatePosition(e) {
			let {axis, lockAxis, lockToContainerEdges} = this.props;
			let offset = this.getOffset(e);
			let translate = {
				x: offset.x - this.initialOffset.x,
				y: offset.y - this.initialOffset.y
			};

			this.translate = translate[axis];

			if (lockToContainerEdges) {
				if (translate[axis] < this.minTranslate) {
					translate[axis] = this.minTranslate;
				} else if (translate[axis] > this.maxTranslate) {
					translate[axis] = this.maxTranslate;
				}
			}

			switch (lockAxis) {
				case 'x':
					translate.y = 0;
					break;
				case 'y':
					translate.x = 0;
					break;
			}

			this.helper.style[`${vendorPrefix}Transform`] = `translate3d(${translate.x}px,${translate.y}px, 0)`;
		}
		animateNodes() {
			let {axis, transitionDuration, hideSortableGhost} = this.props;
			let nodes = this.manager.getOrderedRefs();
			let deltaScroll = this.scrollContainer[`scroll${this.edge}`] - this.initialScroll;
			let sortingOffset = this.offsetEdge + this.translate + deltaScroll;
			this.newIndex = null;

			for (let i = 0, len = nodes.length; i < len; i++) {
				let {node, index, edgeOffset} = nodes[i];
				let dimension = (axis == 'x') ? node.offsetWidth : node.offsetHeight;
				let offset = (this.dimension > dimension) ? dimension / 2 : this.dimension / 2;
				let translate = 0;
				let translateX = 0;
				let translateY = 0;

				// If we haven't cached the node's offsetTop / offsetLeft value
				if (edgeOffset == null) {
					nodes[i].edgeOffset = edgeOffset = this.getEdgeOffset(this.edge, node);
				}

				// If the node is the one we're currently animating, skip it
				if (index === this.index) {
					if (hideSortableGhost) {
						node.style.visibility = 'hidden';
					}
					continue;
				}

				if (transitionDuration) {
					node.style[`${vendorPrefix}TransitionDuration`] = `${transitionDuration}ms`;
				}
				if (index > this.index && (sortingOffset + offset >= edgeOffset)) {
					translate = -this.dimension;
					this.newIndex = index;
				}
				else if (index < this.index && (sortingOffset <= edgeOffset + offset)) {
					translate = this.dimension;

					if (this.newIndex == null) {
						this.newIndex = index;
					}
				}

				if (axis == 'x') {
					translateX = translate;
				} else {
					translateY = translate;
				}

				node.style[`${vendorPrefix}Transform`] = `translate3d(${translateX}px,${translateY}px,0)`;
			}
			if (this.newIndex == null) {
				this.newIndex = this.index;
			}
		}
		autoscroll = () => {
			let translate = this.translate;
			let direction;
			let speed = 1;
			let acceleration = 10;

			if (translate >= this.maxTranslate - this.dimension/2) {
				direction = 1; // Scroll Down
				speed = acceleration * Math.abs((this.maxTranslate - this.dimension/2 - translate) / this.dimension);
			} else if (translate <= this.minTranslate + this.dimension/2) {
				direction = -1; // Scroll Up
				speed = acceleration * Math.abs((translate - this.dimension/2 - this.minTranslate) / this.dimension);
			}

			if (this.autoscrollInterval) {
				clearTimeout(this.autoscrollInterval);
				this.autoscrollInterval = null;
				this.isAutoScrolling = false;
			}

			if (direction) {
				this.autoscrollInterval = setInterval(() => {
					this.isAutoScrolling = true;
					let offset = 1 * speed * direction;
					this.scrollContainer[`scroll${this.edge}`] += offset;
					this.translate += offset;
					this.animateNodes();
				}, 5);
			}
		};
		getWrappedInstance() {
            invariant(config.withRef, 'To access the wrapped instance, you need to pass in {withRef: true} as the second argument of the SortableContainer() call');
            return this.refs.wrappedInstance;
        }
        render() {
            const ref = (config.withRef) ? 'wrappedInstance' : null;

			return <WrappedComponent ref={ref} {...this.props} {...this.state} />;
		}
	}
}
<|endoftext|>


<commit_before>import React, {Component} from 'react';
import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
import ReactCSSTransitionGroup from 'react-addons-transition-group';

import Ripple from '../_Ripple';

import Util from '../_vendors/Util';
import Dom from '../_vendors/Dom';

import './TouchRipple.css';

export default class TouchRipple extends Component {

    constructor(props) {

        super(props);

        this.ignoreNextMouseDown = false;
        this.nextKey = 0;
        this.timeoutIds = [];

        this.state = {
            ripples: []
        };

        this.getRippleStyle = this::this.getRippleStyle;
        this.addRipple = this::this.addRipple;
        this.removeRipple = this::this.removeRipple;
        this.clearRippleTimeout = this::this.clearRippleTimeout;
        this.mouseDownHandle = this::this.mouseDownHandle;

    }

    getRippleStyle(e) {

        const {displayCenter} = this.props;

        // 获取div
        const el = ReactDOM.findDOMNode(this);

        // 获取div 宽度、高度 和 偏移
        const elWidth = el.offsetWidth;
        const elHeight = el.offsetHeight;

        // 获取相对于div的点击位置偏移
        let pointerX, pointerY;
        if (displayCenter) {
            pointerX = elWidth / 2;
            pointerY = elHeight / 2;
        } else {
            const {top, left} = Dom.getOffset(el);
            pointerX = e.pageX - left;
            pointerY = e.pageY - top;
        }

        // 涟漪半径为4个距离的最大值
        const rippleRadius = Math.max(
            Util.getDiag(pointerX, pointerY),
            Util.getDiag(elWidth - pointerX, pointerY),
            Util.getDiag(elWidth - pointerX, elHeight - pointerY),
            Util.getDiag(pointerX, elHeight - pointerY)
        );
        const rippleSize = rippleRadius * 2;

        // 最终偏移量
        const left = pointerX - rippleRadius;
        const top = pointerY - rippleRadius;

        return {
            height: rippleSize,
            width: rippleSize,
            top: top,
            left: left
        };

    }

    addRipple(e) {

        if (this.ignoreNextMouseDown) {
            return;
        }

        this.ignoreNextMouseDown = true;
        let {ripples} = this.state;

        ripples.push(
            <Ripple key={this.nextKey++}
                    style={this.getRippleStyle(e)}/>
        );

        this.setState({
            ripples: ripples
        }, () => {
            this.ignoreNextMouseDown = false;
        });

    }

    removeRipple() {
        this.clearRippleTimeout();
        this.setState({
            ripples: []
        });
    }

    clearRippleTimeout() {

        if (!this.timeoutIds || this.timeoutIds.length < 1) {
            return;
        }

        this.timeoutIds.forEach(item => clearTimeout(item));
        this.timeoutIds = [];

    }

    mouseDownHandle(e) {

        this.timeoutIds[this.nextKey] = setTimeout(() => {
            this.removeRipple();
        }, 1000 / 60);

        this.addRipple(e);

    }

    componentWillUnmount() {
        this.clearRippleTimeout();
    }

    render() {

        const {className, style} = this.props;
        const {ripples} = this.state;

        return (
            <ReactCSSTransitionGroup component="div"
                                     className={`touch-ripple ${className}`}
                                     style={style}
                                     onMouseDown={this.mouseDownHandle}
                                     onMouseUp={this.removeRipple}
                                     onMouseLeave={this.removeRipple}>
                {
                    ripples && ripples.length > 0 ?
                        ripples
                        :
                        null
                }
            </ReactCSSTransitionGroup>
        );

    }
};

TouchRipple.propTypes = {

    className: PropTypes.string,
    style: PropTypes.object,

    displayCenter: PropTypes.bool

};

TouchRipple.defaultProps = {

    className: '',
    style: null,

    displayCenter: false

};<commit_msg>optimize TouchRipple<commit_after>import React, {Component} from 'react';
import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
import ReactCSSTransitionGroup from 'react-addons-transition-group';

import Ripple from '../_Ripple';

import Util from '../_vendors/Util';
import Dom from '../_vendors/Dom';

import './TouchRipple.css';

export default class TouchRipple extends Component {

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.ignoreNextMouseDown = false;
        this.nextKey = 0;
        this.timeoutIds = [];

        this.state = {
            ripples: []
        };

        this.getRippleStyle = ::this.getRippleStyle;
        this.addRipple = ::this.addRipple;
        this.removeRipple = ::this.removeRipple;
        this.clearRippleTimeout = ::this.clearRippleTimeout;
        this.mouseDownHandle = ::this.mouseDownHandle;

    }

    getRippleStyle(e) {

        const {displayCenter} = this.props,

            el = ReactDOM.findDOMNode(this),

            elWidth = el.offsetWidth,
            elHeight = el.offsetHeight;

        // get pointer offset of el
        let pointerX, pointerY;
        if (displayCenter) {
            pointerX = elWidth / 2;
            pointerY = elHeight / 2;
        } else {
            const {top, left} = Dom.getOffset(el);
            pointerX = e.pageX - left;
            pointerY = e.pageY - top;
        }

        // radius is the max distence
        const rippleRadius = Math.max(
            Util.getDiag(pointerX, pointerY),
            Util.getDiag(elWidth - pointerX, pointerY),
            Util.getDiag(elWidth - pointerX, elHeight - pointerY),
            Util.getDiag(pointerX, elHeight - pointerY)
        );
        const rippleSize = rippleRadius * 2;

        // calculate offset
        const left = pointerX - rippleRadius;
        const top = pointerY - rippleRadius;

        return {
            height: rippleSize,
            width: rippleSize,
            top: top,
            left: left
        };

    }

    addRipple(e) {

        if (this.ignoreNextMouseDown) {
            return;
        }

        this.ignoreNextMouseDown = true;
        let {ripples} = this.state;

        ripples.push(
            <Ripple key={this.nextKey++}
                    style={this.getRippleStyle(e)}/>
        );

        this.setState({
            ripples: ripples
        }, () => {
            this.ignoreNextMouseDown = false;
        });

    }

    removeRipple() {
        this.clearRippleTimeout();
        this.setState({
            ripples: []
        });
    }

    clearRippleTimeout() {

        if (!this.timeoutIds || this.timeoutIds.length < 1) {
            return;
        }

        this.timeoutIds.forEach(item => clearTimeout(item));
        this.timeoutIds = [];

    }

    mouseDownHandle(e) {

        this.timeoutIds[this.nextKey] = setTimeout(() => {
            this.removeRipple();
        }, 1000 / 60);

        this.addRipple(e);

    }

    componentWillUnmount() {
        this.clearRippleTimeout();
    }

    render() {

        const {className, style} = this.props;
        const {ripples} = this.state;

        return (
            <ReactCSSTransitionGroup component="div"
                                     className={`touch-ripple ${className}`}
                                     style={style}
                                     onMouseDown={this.mouseDownHandle}
                                     onMouseUp={this.removeRipple}
                                     onMouseLeave={this.removeRipple}>
                {
                    ripples && ripples.length > 0 ?
                        ripples
                        :
                        null
                }
            </ReactCSSTransitionGroup>
        );

    }
};

TouchRipple.propTypes = {

    className: PropTypes.string,
    style: PropTypes.object,

    displayCenter: PropTypes.bool

};

TouchRipple.defaultProps = {

    className: '',
    style: null,

    displayCenter: false

};<|endoftext|>


<commit_before>
/*global jest*/
jest.dontMock('../Animator.jsx');

<commit_msg>First basic test<commit_after>
/*global describe*/
/*global it*/
/*global after*/
// global afterEach
/*global expect*/

import React from 'react/addons';
import Animator from '../Animator.jsx';

const TestUtils = React.addons.TestUtils;

const animate = new Animator();

const SimpleComponent = React.createClass({
  render: function(){
    return (

    );
  }
});

describe('Animator', function() {

  describe('animate()', function() {

    it('should successfully create a renderable component', function() {
      let component = null;
      after(function() {
        React.unmountComponentAtNode(React.findDOMNode(component).parentNode);
      });

      expect(() => {
        const AnimatedSimpleComponent = animate(SimpleComponent, () => {});
        component = TestUtils.renderIntoDocument(<AnimatedSimpleComponent />);
      }).to.not.throw();
    });
  });
});
<|endoftext|>


<commit_before>
<commit_msg>deleted<commit_after><|endoftext|>


<commit_before>var DATASETS = [
  {
    name: "Barley",
    url: "data/barley.json"
  },{
    name: "Cars",
    url: "data/cars.json"
  },{
    name: "Crimea",
    url: "data/crimea.json"
  },{
    name: "Driving",
    url: "data/driving.json"
  },{
    name: "Iris",
    url: "data/iris.json"
  },{
    name: "Jobs",
    url: "data/jobs.json"
  },{
    name: "Population",
    url: "data/population.json"
  },{
    name: "Movies",
    url: "data/movies.json"
  },{
    name: "Birdstrikes",
    url: "data/birdstrikes.json"
  }
];

var vled = {
  version: 0.1,
  spec: {}
}

vled.format = function() {
  var el = d3.select("#vlspec"),
      spec = JSON.parse(el.property("value")),
      text = JSON.stringify(spec, null, "  ", 80);
  el.property("value", text);
};

vled.parse = function() {
  var spec, encoding, source, cfg;
  try {
    spec = JSON.parse(d3.select("#vlspec").property("value"));
  } catch (e) {
    console.log(e);
    return;
  }

  cfg = {
    dataUrl: vled.dataset.url
  }

  encoding = vl.Encoding.parseJSON(spec, cfg);
  vled.loadEncoding(encoding);
}

vled.parseShorthand = function() {
  var shorthand = d3.select("#shorthand").property("value");

  var encoding = vl.Encoding.parseShorthand(shorthand);
  d3.select("#vlspec").node().value = JSON.stringify(encoding.toJSON(), null, "  ", 80);
  vled.parse();
}

vled.loadEncoding = function(encoding) {
  var spec = vl.toVegaSpec(encoding, vled.dataset.stats);

  d3.select("#shorthand").node().value = encoding.toShorthand();
  d3.select("#vlspec").node().value = JSON.stringify(encoding.toJSON(), null, "  ", 80);
  d3.select("#vgspec").node().value = JSON.stringify(spec, null, "  ", 80);

  $('textarea').trigger('autosize.resize');

  vled.vis = null; // DEBUG
  vg.parse.spec(spec, function(chart) {
    vled.vis = chart({el:"#vis", renderer: "svg"});

    vled.vis.update();
    vled.vis.on('mouseover', function(event, item) { console.log(item); });
  });
}

vled.datasetChanged = function(dataset, callback) {
  vled.dataset = dataset;

  if (dataset.stats) return;

  d3.json(dataset.url, function(err, data) {
    if (err) return alert("Error loading data " + err.statusText);

    dataset.stats = vl.getStats(data);
    callback();
  });
}

vled.init = function() {

  // Specification drop-down menu
  var sel = d3.select("#sel_spec");
  sel.selectAll("option.spec")
    .data(DATASETS)
   .enter().append("option")
    .text(function(d) { return d.name; });

  sel.on("change", function() {
    var item = this.options[this.selectedIndex].__data__;
      vled.datasetChanged(item, function() {
      d3.select("#vgspec").node().value = "";
      d3.select("#vis").node().innerHTML = "";
    });
  });

  // Initialize application
  d3.select("#btn_spec_format").on("click", vled.format);
  d3.select("#btn_spec_parse").on("click", vled.parse);
  d3.select("#btn_shorthand_parse").on("click", vled.parseShorthand);

  document.getElementById("shorthand").value = "point.x-bin_yield-Q.y-variety-O.size-count_-Q.color-year-O";
  vled.datasetChanged(DATASETS[0], function() {
    vled.parseShorthand();
  });
};

window.onload = vled.init;<commit_msg>Get short hand from url to increase productivity<commit_after>var DATASETS = [
  {
    name: "Barley",
    url: "data/barley.json"
  },{
    name: "Cars",
    url: "data/cars.json"
  },{
    name: "Crimea",
    url: "data/crimea.json"
  },{
    name: "Driving",
    url: "data/driving.json"
  },{
    name: "Iris",
    url: "data/iris.json"
  },{
    name: "Jobs",
    url: "data/jobs.json"
  },{
    name: "Population",
    url: "data/population.json"
  },{
    name: "Movies",
    url: "data/movies.json"
  },{
    name: "Birdstrikes",
    url: "data/birdstrikes.json"
  }
];

var vled = {
  version: 0.1,
  spec: {}
}

function getParams() {
  var params = location.search.slice(1);

  // remove trailing slash that chrome adds automatically
  if (params[params.length-1] == "/") params = params.substring(0, params.length-1);

  return params.split("&")
    .map(function(x) { return x.split("="); })
    .reduce(function(a, b) {
      a[b[0]] = b[1]; return a;
    }, {});
};

vled.format = function() {
  var el = d3.select("#vlspec"),
      spec = JSON.parse(el.property("value")),
      text = JSON.stringify(spec, null, "  ", 80);
  el.property("value", text);
};

vled.parse = function() {
  var spec, encoding, source, cfg;
  try {
    spec = JSON.parse(d3.select("#vlspec").property("value"));
  } catch (e) {
    console.log(e);
    return;
  }

  cfg = {
    dataUrl: vled.dataset.url
  }

  encoding = vl.Encoding.parseJSON(spec, cfg);
  vled.loadEncoding(encoding);
}

vled.parseShorthand = function() {
  var shorthand = d3.select("#shorthand").property("value");

  var encoding = vl.Encoding.parseShorthand(shorthand);
  d3.select("#vlspec").node().value = JSON.stringify(encoding.toJSON(), null, "  ", 80);
  vled.parse();
}

vled.loadEncoding = function(encoding) {
  var spec = vl.toVegaSpec(encoding, vled.dataset.stats);

  d3.select("#shorthand").node().value = encoding.toShorthand();
  d3.select("#vlspec").node().value = JSON.stringify(encoding.toJSON(), null, "  ", 80);
  d3.select("#vgspec").node().value = JSON.stringify(spec, null, "  ", 80);

  $('textarea').trigger('autosize.resize');

  vled.vis = null; // DEBUG
  vg.parse.spec(spec, function(chart) {
    vled.vis = chart({el:"#vis", renderer: "svg"});

    vled.vis.update();
    vled.vis.on('mouseover', function(event, item) { console.log(item); });
  });
}

vled.datasetChanged = function(dataset, callback) {
  vled.dataset = dataset;

  if (dataset.stats) return;

  d3.json(dataset.url, function(err, data) {
    if (err) return alert("Error loading data " + err.statusText);

    dataset.stats = vl.getStats(data);
    callback();
  });
}

vled.init = function() {
  var params = getParams();

  // Specification drop-down menu
  var sel = d3.select("#sel_spec");
  sel.selectAll("option.spec")
    .data(DATASETS)
   .enter().append("option")
    .text(function(d) { return d.name; });

  sel.on("change", function() {
    var item = this.options[this.selectedIndex].__data__;
      vled.datasetChanged(item, function() {
      d3.select("#vgspec").node().value = "";
      d3.select("#vis").node().innerHTML = "";
    });
  });

  // Initialize application
  d3.select("#btn_spec_format").on("click", vled.format);
  d3.select("#btn_spec_parse").on("click", vled.parse);
  d3.select("#btn_shorthand_parse").on("click", vled.parseShorthand);

  var initialShortHand = params.shortHand ? params.shortHand : "point.x-bin_yield-Q.y-variety-O.size-count_-Q.color-year-O";

  document.getElementById("shorthand").value = initialShortHand;
  vled.datasetChanged(DATASETS[0], function() {
    vled.parseShorthand();
  });
};

window.onload = vled.init;<|endoftext|>


<commit_before>'use strict';

/*global location, d3, vl, vg, docCookies, document, $, alert, dl */

var DATASETS = [
  {
    name: "Barley",
    url: "data/barley.json"
  },{
    name: "Cars",
    url: "data/cars.json"
  },{
    name: "Crimea",
    url: "data/crimea.json"
  },{
    name: "Driving",
    url: "data/driving.json"
  },{
    name: "Iris",
    url: "data/iris.json"
  },{
    name: "Jobs",
    url: "data/jobs.json"
  },{
    name: "Population",
    url: "data/population.json"
  },{
    name: "Movies",
    url: "data/movies.json"
  },{
    name: "Birdstrikes",
    url: "data/birdstrikes.json"
  },{
    name: "Burtin",
    url: "data/burtin.json"
  },{
    name: "Budget 2016",
    url: "data/budget.json"
  },{
    name: "Climate Normals",
    url: "data/climate.json"
  },{
    name: "Campaigns",
    url: "data/weball26.json"
  }
];

var vled = {
  version: 0.1,
  spec: {}
};

function getParams() {
  var params = location.search.slice(1);

  // remove trailing slash that chrome adds automatically
  if (params[params.length-1] == "/") params = params.substring(0, params.length-1);

  return params.split("&")
    .map(function(x) {
      // don't gobble up any equals within the query value
      var idx = x.indexOf("=");
      return [x.slice(0,idx), x.slice(idx+1)];
    })
    .reduce(function(a, b) {
      a[b[0]] = b[1]; return a;
    }, {});
}

vled.format = function() {
  var el = d3.select("#vlspec"),
      spec = JSON.parse(el.property("value")),
      text = JSON.stringify(spec, null, "  ", 60);
  el.property("value", text);
};

vled.parse = function() {
  var spec, encoding;
  try {
    spec = JSON.parse(d3.select("#vlspec").property("value"));
  } catch (e) {
    console.warn(e);
    return;
  }

  var datasetIndex;
  for (var i = 0; spec.data && i < DATASETS.length; i++) {
    if (DATASETS[i].url === spec.data.url) {
      datasetIndex = i;
      break;
    }
  }

  var done = function() {
    // only add url if data is not provided explicitly
    var theme = (spec.data && spec.data.values) ? {} : {
      data: {
        url:  vled.dataset.url
      }
    };
    encoding = vl.Encoding.fromSpec(spec, theme);
    vled.loadEncoding(encoding);
  };

  if (!vled.dataset && !datasetIndex) {
    datasetIndex = 0;
  }

  if (datasetIndex !== undefined) {
    document.getElementById("sel_spec").selectedIndex = datasetIndex;
    vled.datasetChanged(DATASETS[datasetIndex], function() {
      done();
    });
  } else {
    done();
  }
};

vled.parseShorthand = function() {
  var shorthand = d3.select("#shorthand").property("value");

  var encoding = vl.Encoding.parseShorthand(shorthand);
  d3.select("#vlspec").node().value = JSON.stringify(encoding.toSpec(), null, "  ", 60);
  vled.parse();
};

vled.loadEncoding = function(encoding) {
  var stats = encoding.hasValues() ? null : vled.dataset.stats;
  var spec = vl.compile.encoding(encoding, stats);

  d3.select("#shorthand").node().value = encoding.toShorthand();
  d3.select("#vgspec").node().value = JSON.stringify(spec, null, "  ", 60);

  // store spec in cookie for a day
  docCookies.setItem("vlspec", JSON.stringify(encoding.toSpec()), 86400);

  $('textarea').trigger('autosize.resize');

  vled.vis = null; // DEBUG
  vg.parse.spec(spec, function(chart) {
    vled.vis = chart({el:"#vis", renderer: "svg"});

    vled.vis.update();
    vled.vis.on('mouseover', function(ev, item) {
      console.log(item);
    });
  });
};

vled.datasetChanged = function(dataset, callback) {
  vled.dataset = dataset;

  if (dataset.stats) {
    callback();
    return;
  }

  d3.json(dataset.url, function(err, data) {
    if (err) return alert("Error loading data " + err.statusText);
    dataset.stats = dl.summary(data).reduce(function(s, p) {
      s[p.field] = p;
      return s;
    },{});
    callback();
  });
};

vled.init = function() {
  var params = getParams();

  // Specification drop-down menu
  var sel = d3.select("#sel_spec");
  sel.selectAll("option.spec")
    .data(DATASETS)
   .enter().append("option")
    .text(function(d) { return d.name; });

  sel.on("change", function() {
    var item = this.options[this.selectedIndex].__data__;
      vled.datasetChanged(item, function() {
      d3.select("#vgspec").node().value = "";
      d3.select("#vis").node().innerHTML = "";
    });
  });

  // Initialize application
  d3.select("#btn_spec_format").on("click", vled.format);
  d3.select("#btn_spec_parse").on("click", vled.parse);
  d3.select("#btn_shorthand_parse").on("click", vled.parseShorthand);

  var shorthand = params.shortHand;
  if (shorthand) {
    document.getElementById("shorthand").value = shorthand;
    vled.datasetChanged(DATASETS[0], function() {
      vled.parseShorthand();
    });
  } else if (docCookies.hasItem("vlspec")) {
    document.getElementById("vlspec").value = docCookies.getItem("vlspec");
    vled.parse();
    vled.format();
  } else {
    document.getElementById("vlspec").value = JSON.stringify({
      marktype: "point",
      encoding: {
        x: {type: "Q",name: "yield",aggr: "avg"},
        y: {
          sort: [{name: "yield", aggr: "avg", reverse: false}],
          type: "N",
          name: "variety"
        },
        row: {type: "N", name: "site"},
        color: {type: "N", name: "year"}
      }
    });

    vled.parse();
    vled.format();
  }
};

window.onload = vled.init;<commit_msg>Update editor<commit_after>'use strict';

/*global location, d3, vl, vg, docCookies, document, $, alert, dl */

var DATASETS = [
  {
    name: 'Barley',
    url: 'data/barley.json'
  },{
    name: 'Cars',
    url: 'data/cars.json'
  },{
    name: 'Crimea',
    url: 'data/crimea.json'
  },{
    name: 'Driving',
    url: 'data/driving.json'
  },{
    name: 'Iris',
    url: 'data/iris.json'
  },{
    name: 'Jobs',
    url: 'data/jobs.json'
  },{
    name: 'Population',
    url: 'data/population.json'
  },{
    name: 'Movies',
    url: 'data/movies.json'
  },{
    name: 'Birdstrikes',
    url: 'data/birdstrikes.json'
  },{
    name: 'Burtin',
    url: 'data/burtin.json'
  },{
    name: 'Budget 2016',
    url: 'data/budget.json'
  },{
    name: 'Climate Normals',
    url: 'data/climate.json'
  },{
    name: 'Campaigns',
    url: 'data/weball26.json'
  }
];

var vled = {
  version: 0.1,
  spec: {}
};

function getParams() {
  var params = location.search.slice(1);

  // remove trailing slash that chrome adds automatically
  if (params[params.length-1] == '/') params = params.substring(0, params.length-1);

  return params.split('&')
    .map(function(x) {
      // don't gobble up any equals within the query value
      var idx = x.indexOf('=');
      return [x.slice(0,idx), x.slice(idx+1)];
    })
    .reduce(function(a, b) {
      a[b[0]] = b[1]; return a;
    }, {});
}

vled.format = function() {
  var el = d3.select('#vlspec'),
      spec = JSON.parse(el.property('value')),
      text = JSON.stringify(spec, null, '  ', 60);
  el.property('value', text);
};

vled.parse = function() {
  var spec, encoding;
  try {
    spec = JSON.parse(d3.select('#vlspec').property('value'));
  } catch (e) {
    console.warn(e);
    return;
  }

  var datasetIndex;
  for (var i = 0; spec.data && i < DATASETS.length; i++) {
    if (DATASETS[i].url === spec.data.url) {
      datasetIndex = i;
      break;
    }
  }

  var done = function() {
    // only add url if data is not provided explicitly
    var theme = (spec.data && spec.data.values) ? {} : {
      data: {
        url:  vled.dataset.url
      }
    };
    encoding = vl.Encoding.fromSpec(spec, theme);
    vled.loadEncoding(encoding);
  };

  if (!vled.dataset && !datasetIndex) {
    datasetIndex = 0;
  }

  if (datasetIndex !== undefined) {
    document.getElementById('sel_spec').selectedIndex = datasetIndex;
    vled.datasetChanged(DATASETS[datasetIndex], function() {
      done();
    });
  } else {
    done();
  }
};

vled.parseShorthand = function() {
  var shorthand = d3.select('#shorthand').property('value');

  var encoding = vl.Encoding.parseShorthand(shorthand);
  d3.select('#vlspec').node().value = JSON.stringify(encoding.toSpec(), null, '  ', 60);
  vled.parse();
};

vled.loadEncoding = function(encoding) {
  var stats = encoding.hasValues() ? null : vled.dataset.stats;
  var spec = vl.compile.encoding(encoding, stats);

  d3.select('#shorthand').node().value = encoding.toShorthand();
  d3.select('#vgspec').node().value = JSON.stringify(spec, null, '  ', 60);

  // store spec in cookie for a day
  docCookies.setItem('vlspec', JSON.stringify(encoding.toSpec()), 86400);

  $('textarea').trigger('autosize.resize');

  vled.vis = null; // DEBUG
  vg.parse.spec(spec, function(chart) {
    vled.vis = chart({el:'#vis', renderer: 'svg'});

    vled.vis.update();
    vled.vis.on('mouseover', function(ev, item) {
      console.log(item);
    });
  });
};

vled.datasetChanged = function(dataset, callback) {
  vled.dataset = dataset;

  if (dataset.stats) {
    callback();
    return;
  }

  d3.json(dataset.url, function(err, data) {
    if (err) return alert('Error loading data ' + err.statusText);
    dataset.stats = vl.summary(data).reduce(function(s, p) {
      s[p.field] = p;
      return s;
    },{});
    callback();
  });
};

vled.init = function() {
  var params = getParams();

  // Specification drop-down menu
  var sel = d3.select('#sel_spec');
  sel.selectAll('option.spec')
    .data(DATASETS)
   .enter().append('option')
    .text(function(d) { return d.name; });

  sel.on('change', function() {
    var item = this.options[this.selectedIndex].__data__;
      vled.datasetChanged(item, function() {
      d3.select('#vgspec').node().value = '';
      d3.select('#vis').node().innerHTML = '';
    });
  });

  // Initialize application
  d3.select('#btn_spec_format').on('click', vled.format);
  d3.select('#btn_spec_parse').on('click', vled.parse);
  d3.select('#btn_shorthand_parse').on('click', vled.parseShorthand);

  var shorthand = params.shortHand;
  if (shorthand) {
    document.getElementById('shorthand').value = shorthand;
    vled.datasetChanged(DATASETS[0], function() {
      vled.parseShorthand();
    });
  } else if (docCookies.hasItem('vlspec')) {
    document.getElementById('vlspec').value = docCookies.getItem('vlspec');
    vled.parse();
    vled.format();
  } else {
    document.getElementById('vlspec').value = JSON.stringify({
      marktype: 'point',
      encoding: {
        x: {type: 'Q',name: 'yield',aggr: 'avg'},
        y: {
          sort: [{name: 'yield', aggr: 'avg', reverse: false}],
          type: 'N',
          name: 'variety'
        },
        row: {type: 'N', name: 'site'},
        color: {type: 'N', name: 'year'}
      }
    });

    vled.parse();
    vled.format();
  }
};

window.onload = vled.init;<|endoftext|>


<commit_before>'use strict';

/*global location, d3, vl, vg, docCookies, document, $, alert */

var DATASETS = [
  {
    name: 'Barley',
    url: 'data/barley.json'
  },{
    name: 'Cars',
    url: 'data/cars.json'
  },{
    name: 'Crimea',
    url: 'data/crimea.json'
  },{
    name: 'Driving',
    url: 'data/driving.json'
  },{
    name: 'Iris',
    url: 'data/iris.json'
  },{
    name: 'Jobs',
    url: 'data/jobs.json'
  },{
    name: 'Population',
    url: 'data/population.json'
  },{
    name: 'Movies',
    url: 'data/movies.json'
  },{
    name: 'Birdstrikes',
    url: 'data/birdstrikes.json'
  },{
    name: 'Burtin',
    url: 'data/burtin.json'
  },{
    name: 'Budget 2016',
    url: 'data/budget.json'
  },{
    name: 'Climate Normals',
    url: 'data/climate.json'
  },{
    name: 'Campaigns',
    url: 'data/weball26.json'
  }
];

var vled = {
  version: 0.1,
  spec: {}
};

function getParams() {
  var params = location.search.slice(1);

  // remove trailing slash that chrome adds automatically
  if (params[params.length-1] == '/') params = params.substring(0, params.length-1);

  return params.split('&')
    .map(function(x) {
      // don't gobble up any equals within the query value
      var idx = x.indexOf('=');
      return [x.slice(0,idx), x.slice(idx+1)];
    })
    .reduce(function(a, b) {
      a[b[0]] = b[1]; return a;
    }, {});
}

vled.format = function() {
  var el = d3.select('#vlspec'),
      spec = JSON.parse(el.property('value')),
      text = JSON.stringify(spec, null, '  ', 60);
  el.property('value', text);
};

vled.parse = function() {
  var spec;
  try {
    spec = JSON.parse(d3.select('#vlspec').property('value'));
  } catch (e) {
    console.warn(e);
    return;
  }

  var datasetIndex;
  for (var i = 0; spec.data && i < DATASETS.length; i++) {
    if (DATASETS[i].url === spec.data.url) {
      datasetIndex = i;
      break;
    }
  }

  var done = function() {
    // only add url if data is not provided explicitly
    var theme = (spec.data && spec.data.values) ? {} : {
      data: {
        url:  vled.dataset.url
      }
    };
    vled.loadSpec(spec, theme);
  };

  if (!vled.dataset && !datasetIndex) {
    datasetIndex = 0;
  }

  if (datasetIndex !== undefined) {
    document.getElementById('sel_spec').selectedIndex = datasetIndex;
    vled.datasetChanged(DATASETS[datasetIndex], function() {
      done();
    });
  } else {
    done();
  }
};

vled.parseShorthand = function() {
  var shorthand = d3.select('#shorthand').property('value');

  var spec = vl.compile(shorthand, vled.dataset.stats);
  d3.select('#vlspec').node().value = JSON.stringify(spec, null, '  ', 60);
  vled.parse();
};

vled.loadSpec = function(vlspec, theme) {
  var spec = vl.compile(vlspec, vled.dataset.stats, theme);

  d3.select('#shorthand').node().value = vl.toShorthand(vlspec);
  d3.select('#vgspec').node().value = JSON.stringify(spec, null, '  ', 60);

  // store spec in cookie for a day
  docCookies.setItem('vlspec', JSON.stringify(vlspec), 86400);

  $('textarea').trigger('autosize.resize');

  vled.vis = null; // DEBUG
  vg.parse.spec(spec, function(chart) {
    vled.vis = chart({el:'#vis', renderer: 'svg'});

    vled.vis.update();
    vled.vis.on('mouseover', function(ev, item) {
      console.log(item);
    });
  });
};

vled.datasetChanged = function(dataset, callback) {
  vled.dataset = dataset;

  if (dataset.stats) {
    callback();
    return;
  }

  d3.json(dataset.url, function(err, data) {
    if (err) return alert('Error loading data ' + err.statusText);
    dataset.stats = vl.data.stats(data);
    callback();
  });
};

vled.init = function() {
  var params = getParams();

  // Specification drop-down menu
  var sel = d3.select('#sel_spec');
  sel.selectAll('option.spec')
    .data(DATASETS)
   .enter().append('option')
    .text(function(d) { return d.name; });

  sel.on('change', function() {
    var item = this.options[this.selectedIndex].__data__;
      vled.datasetChanged(item, function() {
      d3.select('#vgspec').node().value = '';
      d3.select('#vis').node().innerHTML = '';
    });
  });

  // Initialize application
  d3.select('#btn_spec_format').on('click', vled.format);
  d3.select('#btn_spec_parse').on('click', vled.parse);
  d3.select('#btn_shorthand_parse').on('click', vled.parseShorthand);

  var shorthand = params.shortHand;
  if (shorthand) {
    document.getElementById('shorthand').value = shorthand;
    vled.datasetChanged(DATASETS[0], function() {
      vled.parseShorthand();
    });
  } else if (docCookies.hasItem('vlspec')) {
    document.getElementById('vlspec').value = docCookies.getItem('vlspec');
    vled.parse();
    vled.format();
  } else {
    document.getElementById('vlspec').value = JSON.stringify({
      marktype: 'point',
      encoding: {
        x: {type: 'Q',name: 'yield',aggr: 'avg'},
        y: {
          sort: [{name: 'yield', aggr: 'avg', reverse: false}],
          type: 'N',
          name: 'variety'
        },
        row: {type: 'N', name: 'site'},
        color: {type: 'N', name: 'year'}
      }
    });

    vled.parse();
    vled.format();
  }
};

window.onload = vled.init;
<commit_msg>Fix loading spec with embedded data in editor. Fixes #567<commit_after>'use strict';

/*global location, d3, vl, vg, docCookies, document, $, alert */

var DATASETS = [
  {
    name: 'Barley',
    url: 'data/barley.json'
  },{
    name: 'Cars',
    url: 'data/cars.json'
  },{
    name: 'Crimea',
    url: 'data/crimea.json'
  },{
    name: 'Driving',
    url: 'data/driving.json'
  },{
    name: 'Iris',
    url: 'data/iris.json'
  },{
    name: 'Jobs',
    url: 'data/jobs.json'
  },{
    name: 'Population',
    url: 'data/population.json'
  },{
    name: 'Movies',
    url: 'data/movies.json'
  },{
    name: 'Birdstrikes',
    url: 'data/birdstrikes.json'
  },{
    name: 'Burtin',
    url: 'data/burtin.json'
  },{
    name: 'Budget 2016',
    url: 'data/budget.json'
  },{
    name: 'Climate Normals',
    url: 'data/climate.json'
  },{
    name: 'Campaigns',
    url: 'data/weball26.json'
  }
];

var vled = {
  version: 0.1,
  spec: {}
};

function getParams() {
  var params = location.search.slice(1);

  // remove trailing slash that chrome adds automatically
  if (params[params.length-1] == '/') params = params.substring(0, params.length-1);

  return params.split('&')
    .map(function(x) {
      // don't gobble up any equals within the query value
      var idx = x.indexOf('=');
      return [x.slice(0,idx), x.slice(idx+1)];
    })
    .reduce(function(a, b) {
      a[b[0]] = b[1]; return a;
    }, {});
}

vled.format = function() {
  var el = d3.select('#vlspec'),
      spec = JSON.parse(el.property('value')),
      text = JSON.stringify(spec, null, '  ', 60);
  el.property('value', text);
};

vled.parse = function() {
  var spec;
  try {
    spec = JSON.parse(d3.select('#vlspec').property('value'));
  } catch (e) {
    console.warn(e);
    return;
  }

  var datasetIndex;
  for (var i = 0; spec.data && i < DATASETS.length; i++) {
    if (DATASETS[i].url === spec.data.url) {
      datasetIndex = i;
      break;
    }
  }

  var done = function() {
    // only add url if data is not provided explicitly
    var theme = (spec.data && spec.data.values) ? {} : {
      data: {
        url:  vled.dataset.url
      }
    };
    vled.loadSpec(spec, theme);
  };

  if (!vled.dataset && !datasetIndex) {
    datasetIndex = 0;
  }

  if (datasetIndex !== undefined) {
    document.getElementById('sel_spec').selectedIndex = datasetIndex;
    vled.datasetChanged(DATASETS[datasetIndex], function() {
      done();
    });
  } else {
    done();
  }
};

vled.parseShorthand = function() {
  var shorthand = d3.select('#shorthand').property('value');

  var spec = vl.compile(shorthand, vled.dataset.stats);
  d3.select('#vlspec').node().value = JSON.stringify(spec, null, '  ', 60);
  vled.parse();
};

vled.loadSpec = function(vlspec, theme) {
  var stats = null;

  // use dataset stats only if the spec does not have embedded stats
  if (!vlspec.data  || vlspec.data.values === undefined) {
    stats = vled.dataset.stats;
  }

  var spec = vl.compile(vlspec, stats, theme);

  d3.select('#shorthand').node().value = vl.toShorthand(vlspec);
  d3.select('#vgspec').node().value = JSON.stringify(spec, null, '  ', 60);

  // store spec in cookie for a day
  docCookies.setItem('vlspec', JSON.stringify(vlspec), 86400);

  $('textarea').trigger('autosize.resize');

  vled.vis = null; // DEBUG
  vg.parse.spec(spec, function(chart) {
    vled.vis = chart({el:'#vis', renderer: 'svg'});

    vled.vis.update();
    vled.vis.on('mouseover', function(ev, item) {
      console.log(item);
    });
  });
};

vled.datasetChanged = function(dataset, callback) {
  vled.dataset = dataset;

  if (dataset.stats) {
    callback();
    return;
  }

  d3.json(dataset.url, function(err, data) {
    if (err) return alert('Error loading data ' + err.statusText);
    dataset.stats = vl.data.stats(data);
    callback();
  });
};

vled.init = function() {
  var params = getParams();

  // Specification drop-down menu
  var sel = d3.select('#sel_spec');
  sel.selectAll('option.spec')
    .data(DATASETS)
   .enter().append('option')
    .text(function(d) { return d.name; });

  sel.on('change', function() {
    var item = this.options[this.selectedIndex].__data__;
      vled.datasetChanged(item, function() {
      d3.select('#vgspec').node().value = '';
      d3.select('#vis').node().innerHTML = '';
    });
  });

  // Initialize application
  d3.select('#btn_spec_format').on('click', vled.format);
  d3.select('#btn_spec_parse').on('click', vled.parse);
  d3.select('#btn_shorthand_parse').on('click', vled.parseShorthand);

  var shorthand = params.shortHand;
  if (shorthand) {
    document.getElementById('shorthand').value = shorthand;
    vled.datasetChanged(DATASETS[0], function() {
      vled.parseShorthand();
    });
  } else if (docCookies.hasItem('vlspec')) {
    document.getElementById('vlspec').value = docCookies.getItem('vlspec');
    vled.parse();
    vled.format();
  } else {
    document.getElementById('vlspec').value = JSON.stringify({
      marktype: 'point',
      encoding: {
        x: {type: 'Q',name: 'yield',aggr: 'avg'},
        y: {
          sort: [{name: 'yield', aggr: 'avg', reverse: false}],
          type: 'N',
          name: 'variety'
        },
        row: {type: 'N', name: 'site'},
        color: {type: 'N', name: 'year'}
      }
    });

    vled.parse();
    vled.format();
  }
};

window.onload = vled.init;
<|endoftext|>


<commit_before>const electron = require('electron');
var client;
// Connect to live update if LIVE_UPDATE env variable is true
if (process.env.LIVE_UPDATE === "true") {
  client = require('electron-connect').client;
}
// Module to control application life.
const app = electron.app;
const protocol = electron.protocol;
// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow;

const path = require('path');
const url = require('url');

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;

function createWindow () {
  //Intercept any urls on the page and find the file on disk instead
  protocol.interceptFileProtocol('file', function(req, callback) {
    var url = req.url.substr(7);
    callback({path: path.normalize(__dirname + url)});
  },function (error) {
    if (error) {
      console.error('Failed to register protocol');
    }
  });

  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: 1200,
    height: 700,
    titleBarStyle: 'hidden-inset',
    "web-preferences": {
      "web-security": false
    }
  });

  // and load the index.html of the app.
  mainWindow.loadURL(url.format({
    pathname: 'index.html',
    protocol: 'file:',
    slashes: true
  }));

  // Open the DevTools.
  if (process.env.OPEN_DEV_TOOLS === "true") {
    mainWindow.webContents.openDevTools();
  }

  // Emitted when the window is closed.
  mainWindow.on('closed', function () {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null;
  });

  // Connect to live update if LIVE_UPDATE env variable is true
  if (client) {
    client.create(mainWindow, {"sendBounds":false});
  }
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);

// Quit when all windows are closed.
app.on('window-all-closed', function () {
  // On OS X it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

app.on('activate', function () {
  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (mainWindow === null) {
    createWindow();
  }
});

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.<commit_msg>adding debug port for use in attaching code editor to electron for debugging<commit_after>const electron = require('electron');
var client;
// Module to control application life.
const app = electron.app;
// Connect to live update if LIVE_UPDATE env variable is true
if (process.env.LIVE_UPDATE === "true") {
  app.commandLine.appendSwitch('remote-debugging-port', '8315');
  client = require('electron-connect').client;
}
const protocol = electron.protocol;
// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow;

const path = require('path');
const url = require('url');

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;

function createWindow () {
  //Intercept any urls on the page and find the file on disk instead
  protocol.interceptFileProtocol('file', function(req, callback) {
    var url = req.url.substr(7);
    callback({path: path.normalize(__dirname + url)});
  },function (error) {
    if (error) {
      console.error('Failed to register protocol');
    }
  });

  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: 1200,
    height: 700,
    titleBarStyle: 'hidden-inset',
    "web-preferences": {
      "web-security": false
    }
  });

  // and load the index.html of the app.
  mainWindow.loadURL(url.format({
    pathname: 'index.html',
    protocol: 'file:',
    slashes: true
  }));

  // Open the DevTools.
  if (process.env.OPEN_DEV_TOOLS === "true") {
    mainWindow.webContents.openDevTools();
  }

  // Emitted when the window is closed.
  mainWindow.on('closed', function () {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null;
  });

  // Connect to live update if LIVE_UPDATE env variable is true
  if (client) {
    client.create(mainWindow, {"sendBounds":false});
  }
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);

// Quit when all windows are closed.
app.on('window-all-closed', function () {
  // On OS X it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

app.on('activate', function () {
  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (mainWindow === null) {
    createWindow();
  }
});

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.<|endoftext|>


<commit_before>function ddg_spice_brainy_quote (api_result) {
    // Check if the result is a category search or not.
    // We'll know that if the author is specified in the JSON response.
    if(api_result.error || api_result.author) {
	return;
    }

    Spice.render({
         data              : api_result,
         force_big_header  : true,
         header1           : api_result.header1,
         source_name       : api_result.source_name, // More at ...
         source_url        : api_result.source_url,
         template_normal   : 'brainy_quote',
	 force_no_fold     : true
    });
}
<commit_msg>use strict in Brainy Quote Spice.<commit_after>function ddg_spice_brainy_quote (api_result) {
    "use strict";

    // Check if the result is a category search or not.
    // We'll know that if the author is specified in the JSON response.
    if(api_result.error || api_result.author) {
	return;
    }

    Spice.render({
         data              : api_result,
         force_big_header  : true,
         header1           : api_result.header1,
         source_name       : api_result.source_name, // More at ...
         source_url        : api_result.source_url,
         template_normal   : 'brainy_quote',
	 force_no_fold     : true
    });
}
<|endoftext|>