<commit_before>janus.registerElement('locomotion_teleporter', {
  active: false,
  longpresstime: 500,
  deadzone: 5,
  xrplayer: null,
  linesegments: 100,

  create() {
    this.marker = this.createObject('Object', {
    });
    this.ring = this.marker.createObject('object', {
      id: 'pipe',
      col: V(0,0,155),
      emissive: V(0,0,155),
      scale: V(.5,.01,.5),
      collidable: false,
      pickable: false,
      shadow: false,
      shadow_cast: false,
      shadow_receive: false,
      renderorder: 20,
      depth_test: false,
      depth_write: false,
    });
    this.cylinder = this.marker.createObject('object', {
      id: 'cylinder',
      col: V(0,0,155,.4),
      scale: V(.5,1.5,.5),
      collidable: false,
      pickable: false,
      shadow: false,
      shadow_cast: false,
      shadow_receive: false,
      renderorder: 10,
    });
    this.pointer = this.marker.createObject('Object', {
      id: 'pyramid',
      col: 'red',
      rotation: V(90,0,0),
      scale: V(.1,.5,.0125),
      pos: V(0,.01,0),
      collidable: false,
      pickable: false,
      shadow: false,
      shadow_cast: false,
      shadow_receive: false,
    });
/*
    this.light = this.createObject('Light', {
      col: '#009',
      pos: V(0,1,0),
      light_range: 20,
      light_intensity: 8
    });
*/
    this.particles = room.createObject('Particle', {
      col: V(0,.2,1,.4),
      pos: V(-.25,.1,-.25),
      scale: V(.05),
      //vel: V(-.5,0,-.5),
      particle_vel: V(-.4,2,-.4),
      rand_vel: V(.8,2,.8),
      rand_col: V(.5,.5,1),
      rand_pos: V(.5,0,.5),
      accel: V(0,-1,0),
      rand_accel: V(0,2,0),
      rate: 50,
      count: 60,
      duration: .5,
      collision_id: '',
      collidable: false,
      pickable: false,
      loop: true
    });
    this.shroud = this.createObject('object', {
      id: 'sphere',
      scale: V(2),
      lighting: false,
      col: 'black',
      cull_face: 'none',
      depth_test: false,
      depth_write: false,
      shadow_cast: false,
      shadow_receive: false,
      renderorder: 100,
      visible: false,
    });

    let linepositions = [];
    for (let i = 0; i < this.linesegments; i++) {
      linepositions.push(V(0));
      linepositions.push(V(0));
    }

    this.laser = room.createObject('linesegments', {
      positions: linepositions,
      opacity: .8,
      col: 'blue',
      visible: false,
    });
    player.head.add(this.shroud._target);
    this.particles.particle_vel = V(-.4, 0, -.4); // FIXME - particle velocity isn't being set on spawn
    this.sound = room.createObject('Sound', { id: 'teleport2' }, this);

    this.disableCursor();
    window.addEventListener('mousemove', this.handleMouseMove);
    window.addEventListener('touchmove', this.handleTouchMove, true);

    this.activecontrols = this.addControlContext('teleporter', {
      'teleport_x': {
        defaultbindings: 'gamepad_any_axis_0,gamepad_any_axis_2',
        onchange: ev => this.handleTeleportChange(ev),
        onactivate: ev => this.handleTeleportTurn(ev),
      },
      'teleport_y': {
        defaultbindings: 'gamepad_any_axis_1,gamepad_any_axis_3',
        onchange: ev => this.handleTeleportChange(ev),
        onactivate: ev => this.handleTeleportStart(ev),
      },
      'teleport_trigger': {
        defaultbindings: 'gamepad_any_button_0',
        onactivate: ev => this.handleTeleportTrigger(ev),
      },
    });
    this.activateControlContext('teleporter');

    room.addEventListener('mousedown', (ev) => this.handleMouseDown(ev));
    room.addEventListener('mouseup', (ev) => this.handleMouseUp(ev));
    elation.events.add(janus._target, 'room_change', (ev) => this.handleRoomChange(ev));
  },
  update() {
    if (this.active) {
      let hand = this.xrplayer.trackedobjects['hand_' + this.teleporthand];
      let startpoint,
          segments = this.linesegments,
          duration = .25,
          speed = 4,
          g = V(0, -1, 0),
          p1 = V(),
          v1 = V(),
          v0;

      if (hand) {
        startpoint = hand.pointer.localToWorld(V(0, 0, 0));
        v0 = hand.pointer.localToWorld(V(0, 0, -speed)).sub(startpoint);
      } else {
        startpoint = player.head.localToWorld(V(0,0,0));
        v0 = player.head.localToWorld(V(0,0,-speed)).sub(startpoint);
      }
      let i = 0,
          p0 = startpoint.clone(),
          dir = v0.clone().normalize();
      let laserpoints = this.laser.positions;
      // Trace our arc in steps, performing a raytrace at each step
      for (i = 0; i < segments; i++) {
        let t = (i + 1) * duration / segments
        dir.copy(v0);
        speed = dir.length();
        dir.divideScalar(speed);
        let hits = room.raycast(dir, p0, null, speed);
        if (hits.length > 0) {
          let hit = hits[0];
          p1.copy(hit.point);
          if (hit.distance < 200) {
            this.pos = player.worldToLocal(hit.point);
            this.localToWorld(this.particles.emitter_pos.set(0,0,0));
            this.updateTeleportAngle();
          }
          laserpoints[i * 2].copy(p0);
          laserpoints[i * 2 + 1].copy(p1);
          // Zero out any further line segments
          for (let k = i+1; k < segments; k++) {
            laserpoints[k * 2].set(0,0,0);
            laserpoints[k * 2 + 1].set(0,0,0);
          }
          break;
        } else {
          p1.copy(g).multiplyScalar(.5 * t * t).add(v0.clone().multiplyScalar(t)).add(p0);;
          v1.copy(g).multiplyScalar(t).add(v0);
          laserpoints[i * 2].copy(p0);
          laserpoints[i * 2 + 1].copy(p1);
          p0.copy(p1);
          v0.copy(v1);
        }
      }
      this.laser.updateLine();
      if (this.laser.room !== room) room.appendChild(this.laser);
      this.pointer.orientation._target.setFromEuler(new THREE.Euler(Math.PI/2, this.teleportangle, 0, "YXZ"));
    } else {
      if (this.shroud.visible) {
        ////this.worldToLocal(player.head.localToWorld(this.shroud.pos.set(0,0,0)));
        if (this.shroud.opacity > .001) {
          this.shroud.opacity *= .9;
          if (this.shroud.opacity <= .001) {
            this.shroud.visible = false;
            this.shroud.opacity = 0;
          }
        }
      }
    }
  },
  handleRoomChange(ev) {
    this.setRoom(room);

    room.addEventListener('mousedown', (ev) => this.handleMouseDown(ev));
    room.addEventListener('mouseup', (ev) => this.handleMouseUp(ev));
  },
  handleTeleportChange(ev) {
    //if (!room.teleport) return;
    if (this.teleportactive) {
      let controls = this.activecontrols;
      let xy = new THREE.Vector2(controls.teleport_x, controls.teleport_y),
          len = xy.length();

      if (len > .8) {
        this.updateTeleportAngle();
      } else if (len < .01) {
        this.showShroud();
        this.teleport();
        this.teleportactive = false;
        this.teleporthand = false;
        this.disableCursor();
      }
    }
  },
  handleTeleportStart(ev, hand) {
    if (!room.teleport) return;
    if (!this.teleportactive && Math.abs(ev.value) > .8) {
      this.teleportactive = true;
      this.teleporthand = 'right';
      this.enableCursor();
      this.updateTeleportAngle();
    }
  },
  handleTeleportTurn(ev) {
    if (!this.teleportactive) {
      this.showShroud();
      let turn = new THREE.Quaternion();
      turn.setFromEuler(new THREE.Euler(0, Math.PI / 4 * (ev.value > 0 ? -1 : 1), 0));
      player.orientation.multiply(turn);
    }
  },
  handleTeleportTrigger(ev) {
    if (!room.teleport) return;
    if (this.active) {

    }
  },
  teleport() {
    //if (!room.teleport) return;
    let pos = player.localToWorld(this.pos.clone());
    pos.y += player.fatness; // FIXME - This accounts for wonky player sphere collider, when we switch to a capsule we won't need it
    player.pos = pos;
    player.vel = V(0,0,.01); // "wake up" physics engine
    player.angular.set(0,0,0);
    let playerangle = Math.atan2(this.pos.x, this.pos.z);
    console.log('Teleport player', pos, playerangle);
    this.xrplayer.orientation._target.setFromEuler(new THREE.Euler(0, this.teleportangle - playerangle, 0));
  },
  updateTeleportAngle() {
    let controls = this.activecontrols;
    let controllerangle = Math.atan2(controls.teleport_x, controls.teleport_y);
    let playerangle = Math.atan2(this.pos.x, this.pos.z);
    this.teleportangle = (controllerangle + playerangle) + Math.PI;
  },
  handleMouseDown(ev) {
    if (!room.teleport) return;
    if (ev.button == 0 && (player.enabled || janus.hmd)) {
      this.longpresstimer = setTimeout(() => { console.log('timer fired'); this.enableCursor(); }, this.longpresstime);
      this.mousediff = [0,0];
      //this.active = true;
    }
  },
  handleMouseMove(ev) {
    if (!room.teleport) return;
    if (this.longpresstimer) {
      this.mousediff[0] += ev.movementX;
      this.mousediff[1] += ev.movementY
      var distance = Math.sqrt(this.mousediff[0] * this.mousediff[0] + this.mousediff[1] * this.mousediff[1]);
      if (distance > this.deadzone) {
        clearTimeout(this.longpresstimer);
        this.longpresstimer = false;
      }
    }
  },
  handleTouchMove(ev) {
    if (!room.teleport) return;
    if (this.longpresstimer) {
      var touch = ev.changedTouches[0];

      if (this.lasttouch) {
        this.mousediff[0] += touch.clientX - this.lasttouch[0];
        this.mousediff[1] += touch.clientY - this.lasttouch[1];
      } else {
        this.mousediff[0] = 0;
        this.mousediff[1] = 0;
      }
      this.lasttouch = [touch.clientX, touch.clientY];
      var distance = Math.sqrt(this.mousediff[0] * this.mousediff[0] + this.mousediff[1] * this.mousediff[1]);
      if (distance > this.deadzone) {
        clearTimeout(this.longpresstimer);
      }
      if (this.active) {
        ev.stopPropagation();
        ev.preventDefault();
      }
    }
  },
  handleMouseUp(ev) {
    //if (!room.teleport) return;
    if (this.longpresstimer) {
      clearTimeout(this.longpresstimer);
      this.longpresstimer = false;
    }
    if (this.active) {
/*
      player.pos = this.pos;
      this.sound.pos = this.pos;
      this.sound.play();
*/
      this.showShroud();
      this.teleport();
    }
    this.disableCursor();
  },
  enableCursor() {
    if (!room.teleport) return;
    this.visible = true;
    this.particles.visible = true;
    if (this.laser.room !== room) room.appendChild(this.laser);
    if (this.particles.room !== room) room.appendChild(this.particles);
    this.laser.visible = true;
    this.active = true;
    this.particles.start();
  },
  disableCursor() {
    this.visible = false;
    this.particles.visible = false;
    this.laser.visible = false;
    this.active = false;
    this.particles.stop();
  },
  showShroud() {
    this.shroud.visible = true;
    this.shroud.opacity = 1;
  }
});
<commit_msg>Disabled broken mouse-based teleporter event bindings<commit_after>janus.registerElement('locomotion_teleporter', {
  active: false,
  longpresstime: 500,
  deadzone: 5,
  xrplayer: null,
  linesegments: 100,

  create() {
    this.marker = this.createObject('Object', {
    });
    this.ring = this.marker.createObject('object', {
      id: 'pipe',
      col: V(0,0,155),
      emissive: V(0,0,155),
      scale: V(.5,.01,.5),
      collidable: false,
      pickable: false,
      shadow: false,
      shadow_cast: false,
      shadow_receive: false,
      renderorder: 20,
      depth_test: false,
      depth_write: false,
    });
    this.cylinder = this.marker.createObject('object', {
      id: 'cylinder',
      col: V(0,0,155,.4),
      scale: V(.5,1.5,.5),
      collidable: false,
      pickable: false,
      shadow: false,
      shadow_cast: false,
      shadow_receive: false,
      renderorder: 10,
    });
    this.pointer = this.marker.createObject('Object', {
      id: 'pyramid',
      col: 'red',
      rotation: V(90,0,0),
      scale: V(.1,.5,.0125),
      pos: V(0,.01,0),
      collidable: false,
      pickable: false,
      shadow: false,
      shadow_cast: false,
      shadow_receive: false,
    });
/*
    this.light = this.createObject('Light', {
      col: '#009',
      pos: V(0,1,0),
      light_range: 20,
      light_intensity: 8
    });
*/
    this.particles = room.createObject('Particle', {
      col: V(0,.2,1,.4),
      pos: V(-.25,.1,-.25),
      scale: V(.05),
      //vel: V(-.5,0,-.5),
      particle_vel: V(-.4,2,-.4),
      rand_vel: V(.8,2,.8),
      rand_col: V(.5,.5,1),
      rand_pos: V(.5,0,.5),
      accel: V(0,-1,0),
      rand_accel: V(0,2,0),
      rate: 50,
      count: 60,
      duration: .5,
      collision_id: '',
      collidable: false,
      pickable: false,
      loop: true
    });
    this.shroud = this.createObject('object', {
      id: 'sphere',
      scale: V(2),
      lighting: false,
      col: 'black',
      cull_face: 'none',
      depth_test: false,
      depth_write: false,
      shadow_cast: false,
      shadow_receive: false,
      renderorder: 100,
      visible: false,
    });

    let linepositions = [];
    for (let i = 0; i < this.linesegments; i++) {
      linepositions.push(V(0));
      linepositions.push(V(0));
    }

    this.laser = room.createObject('linesegments', {
      positions: linepositions,
      opacity: .8,
      col: 'blue',
      visible: false,
    });
    player.head.add(this.shroud._target);
    this.particles.particle_vel = V(-.4, 0, -.4); // FIXME - particle velocity isn't being set on spawn
    this.sound = room.createObject('Sound', { id: 'teleport2' }, this);

    this.disableCursor();
    window.addEventListener('mousemove', this.handleMouseMove);
    window.addEventListener('touchmove', this.handleTouchMove, true);

    this.activecontrols = this.addControlContext('teleporter', {
      'teleport_x': {
        defaultbindings: 'gamepad_any_axis_0,gamepad_any_axis_2',
        onchange: ev => this.handleTeleportChange(ev),
        onactivate: ev => this.handleTeleportTurn(ev),
      },
      'teleport_y': {
        defaultbindings: 'gamepad_any_axis_1,gamepad_any_axis_3',
        onchange: ev => this.handleTeleportChange(ev),
        onactivate: ev => this.handleTeleportStart(ev),
      },
      'teleport_trigger': {
        defaultbindings: 'gamepad_any_button_0',
        onactivate: ev => this.handleTeleportTrigger(ev),
      },
    });
    this.activateControlContext('teleporter');

    //room.addEventListener('mousedown', (ev) => this.handleMouseDown(ev));
    //room.addEventListener('mouseup', (ev) => this.handleMouseUp(ev));
    elation.events.add(janus._target, 'room_change', (ev) => this.handleRoomChange(ev));
  },
  update() {
    if (this.active) {
      let hand = this.xrplayer.trackedobjects['hand_' + this.teleporthand];
      let startpoint,
          segments = this.linesegments,
          duration = .25,
          speed = 4,
          g = V(0, -1, 0),
          p1 = V(),
          v1 = V(),
          v0;

      if (hand) {
        startpoint = hand.pointer.localToWorld(V(0, 0, 0));
        v0 = hand.pointer.localToWorld(V(0, 0, -speed)).sub(startpoint);
      } else {
        startpoint = player.head.localToWorld(V(0,0,0));
        v0 = player.head.localToWorld(V(0,0,-speed)).sub(startpoint);
      }
      let i = 0,
          p0 = startpoint.clone(),
          dir = v0.clone().normalize();
      let laserpoints = this.laser.positions;
      // Trace our arc in steps, performing a raytrace at each step
      for (i = 0; i < segments; i++) {
        let t = (i + 1) * duration / segments
        dir.copy(v0);
        speed = dir.length();
        dir.divideScalar(speed);
        let hits = room.raycast(dir, p0, null, speed);
        if (hits.length > 0) {
          let hit = hits[0];
          p1.copy(hit.point);
          if (hit.distance < 200) {
            this.pos = player.worldToLocal(hit.point);
            this.localToWorld(this.particles.emitter_pos.set(0,0,0));
            this.updateTeleportAngle();
          }
          laserpoints[i * 2].copy(p0);
          laserpoints[i * 2 + 1].copy(p1);
          // Zero out any further line segments
          for (let k = i+1; k < segments; k++) {
            laserpoints[k * 2].set(0,0,0);
            laserpoints[k * 2 + 1].set(0,0,0);
          }
          break;
        } else {
          p1.copy(g).multiplyScalar(.5 * t * t).add(v0.clone().multiplyScalar(t)).add(p0);;
          v1.copy(g).multiplyScalar(t).add(v0);
          laserpoints[i * 2].copy(p0);
          laserpoints[i * 2 + 1].copy(p1);
          p0.copy(p1);
          v0.copy(v1);
        }
      }
      this.laser.updateLine();
      if (this.laser.room !== room) room.appendChild(this.laser);
      this.pointer.orientation._target.setFromEuler(new THREE.Euler(Math.PI/2, this.teleportangle, 0, "YXZ"));
    } else {
      if (this.shroud.visible) {
        ////this.worldToLocal(player.head.localToWorld(this.shroud.pos.set(0,0,0)));
        if (this.shroud.opacity > .001) {
          this.shroud.opacity *= .9;
          if (this.shroud.opacity <= .001) {
            this.shroud.visible = false;
            this.shroud.opacity = 0;
          }
        }
      }
    }
  },
  handleRoomChange(ev) {
    this.setRoom(room);

    room.addEventListener('mousedown', (ev) => this.handleMouseDown(ev));
    room.addEventListener('mouseup', (ev) => this.handleMouseUp(ev));
  },
  handleTeleportChange(ev) {
    //if (!room.teleport) return;
    if (this.teleportactive) {
      let controls = this.activecontrols;
      let xy = new THREE.Vector2(controls.teleport_x, controls.teleport_y),
          len = xy.length();

      if (len > .8) {
        this.updateTeleportAngle();
      } else if (len < .01) {
        this.showShroud();
        this.teleport();
        this.teleportactive = false;
        this.teleporthand = false;
        this.disableCursor();
      }
    }
  },
  handleTeleportStart(ev, hand) {
    if (!room.teleport) return;
    if (!this.teleportactive && Math.abs(ev.value) > .8) {
      this.teleportactive = true;
      this.teleporthand = 'right';
      this.enableCursor();
      this.updateTeleportAngle();
    }
  },
  handleTeleportTurn(ev) {
    if (!this.teleportactive) {
      this.showShroud();
      let turn = new THREE.Quaternion();
      turn.setFromEuler(new THREE.Euler(0, Math.PI / 4 * (ev.value > 0 ? -1 : 1), 0));
      player.orientation.multiply(turn);
    }
  },
  handleTeleportTrigger(ev) {
    if (!room.teleport) return;
    if (this.active) {

    }
  },
  teleport() {
    //if (!room.teleport) return;
    let pos = player.localToWorld(this.pos.clone());
    pos.y += player.fatness; // FIXME - This accounts for wonky player sphere collider, when we switch to a capsule we won't need it
    player.pos = pos;
    player.vel = V(0,0,.01); // "wake up" physics engine
    player.angular.set(0,0,0);
    let playerangle = Math.atan2(this.pos.x, this.pos.z);
    console.log('Teleport player', pos, playerangle);
    this.xrplayer.orientation._target.setFromEuler(new THREE.Euler(0, this.teleportangle - playerangle, 0));
  },
  updateTeleportAngle() {
    let controls = this.activecontrols;
    let controllerangle = Math.atan2(controls.teleport_x, controls.teleport_y);
    let playerangle = Math.atan2(this.pos.x, this.pos.z);
    this.teleportangle = (controllerangle + playerangle) + Math.PI;
  },
  handleMouseDown(ev) {
    if (!room.teleport) return;
    if (ev.button == 0 && (player.enabled || janus.hmd)) {
      this.longpresstimer = setTimeout(() => { console.log('timer fired'); this.enableCursor(); }, this.longpresstime);
      this.mousediff = [0,0];
      //this.active = true;
    }
  },
  handleMouseMove(ev) {
    if (!room.teleport) return;
    if (this.longpresstimer) {
      this.mousediff[0] += ev.movementX;
      this.mousediff[1] += ev.movementY
      var distance = Math.sqrt(this.mousediff[0] * this.mousediff[0] + this.mousediff[1] * this.mousediff[1]);
      if (distance > this.deadzone) {
        clearTimeout(this.longpresstimer);
        this.longpresstimer = false;
      }
    }
  },
  handleTouchMove(ev) {
    if (!room.teleport) return;
    if (this.longpresstimer) {
      var touch = ev.changedTouches[0];

      if (this.lasttouch) {
        this.mousediff[0] += touch.clientX - this.lasttouch[0];
        this.mousediff[1] += touch.clientY - this.lasttouch[1];
      } else {
        this.mousediff[0] = 0;
        this.mousediff[1] = 0;
      }
      this.lasttouch = [touch.clientX, touch.clientY];
      var distance = Math.sqrt(this.mousediff[0] * this.mousediff[0] + this.mousediff[1] * this.mousediff[1]);
      if (distance > this.deadzone) {
        clearTimeout(this.longpresstimer);
      }
      if (this.active) {
        ev.stopPropagation();
        ev.preventDefault();
      }
    }
  },
  handleMouseUp(ev) {
    //if (!room.teleport) return;
    if (this.longpresstimer) {
      clearTimeout(this.longpresstimer);
      this.longpresstimer = false;
    }
    if (this.active) {
/*
      player.pos = this.pos;
      this.sound.pos = this.pos;
      this.sound.play();
*/
      this.showShroud();
      this.teleport();
    }
    this.disableCursor();
  },
  enableCursor() {
    if (!room.teleport) return;
    this.visible = true;
    this.particles.visible = true;
    if (this.laser.room !== room) room.appendChild(this.laser);
    if (this.particles.room !== room) room.appendChild(this.particles);
    this.laser.visible = true;
    this.active = true;
    this.particles.start();
  },
  disableCursor() {
    this.visible = false;
    this.particles.visible = false;
    this.laser.visible = false;
    this.active = false;
    this.particles.stop();
  },
  showShroud() {
    this.shroud.visible = true;
    this.shroud.opacity = 1;
  }
});
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import autosize from 'autosize';

const UPDATE = 'autosize:update',
  DESTROY = 'autosize:destroy',
  RESIZED = 'autosize:resized';

export default class TextareaAutosize extends React.Component {

  static propTypes = {
    onResize: React.PropTypes.func
  };

  static defaultProps = {
    rows: 1
  };

  getTextareaDOMNode = () => (
    this.refs.textarea.nodeType === 1 ?
      this.refs.textarea :
      ReactDOM.findDOMNode(this.refs.textarea)
  );

  componentDidMount() {
    autosize(this.getTextareaDOMNode());
    if (this.props.onResize) {
      this.getTextareaDOMNode().addEventListener(RESIZED, this.props.onResize);
    }
  }

  componentWillUnmount() {
    if (this.props.onResize) {
      this.getTextareaDOMNode().removeEventListener(RESIZED, this.props.onResize);
    }
    this.dispatchEvent(DESTROY);
  }

  dispatchEvent = (EVENT_TYPE, defer) => {
    const event = document.createEvent('Event');
    event.initEvent(EVENT_TYPE, true, false);
    const dispatch = () => this.getTextareaDOMNode().dispatchEvent(event);
    if (defer) {
      setTimeout(dispatch);
    } else {
      dispatch();
    }
  };

  getValue = ({ valueLink, value }) => valueLink ? valueLink.value : value;

  render() {
    const { children, ...props } = this.props;
    return (
      <textarea {...props} ref='textarea'>
        {children}
      </textarea>
    );
  }

  componentWillReceiveProps(nextProps) {
    if (this.getValue(nextProps) !== this.getValue(this.props)) {
      this.dispatchEvent(UPDATE, true);
    }
  }

}
<commit_msg>prevent onResize passing to textarea, fixes react warning<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import autosize from 'autosize';

const UPDATE = 'autosize:update',
  DESTROY = 'autosize:destroy',
  RESIZED = 'autosize:resized';

export default class TextareaAutosize extends React.Component {

  static propTypes = {
    onResize: React.PropTypes.func
  };

  static defaultProps = {
    rows: 1
  };

  getTextareaDOMNode = () => (
    this.refs.textarea.nodeType === 1 ?
      this.refs.textarea :
      ReactDOM.findDOMNode(this.refs.textarea)
  );

  componentDidMount() {
    autosize(this.getTextareaDOMNode());
    if (this.props.onResize) {
      this.getTextareaDOMNode().addEventListener(RESIZED, this.props.onResize);
    }
  }

  componentWillUnmount() {
    if (this.props.onResize) {
      this.getTextareaDOMNode().removeEventListener(RESIZED, this.props.onResize);
    }
    this.dispatchEvent(DESTROY);
  }

  dispatchEvent = (EVENT_TYPE, defer) => {
    const event = document.createEvent('Event');
    event.initEvent(EVENT_TYPE, true, false);
    const dispatch = () => this.getTextareaDOMNode().dispatchEvent(event);
    if (defer) {
      setTimeout(dispatch);
    } else {
      dispatch();
    }
  };

  getValue = ({ valueLink, value }) => valueLink ? valueLink.value : value;

  render() {
    const { children, onResize, ...props } = this.props;  // eslint-disable-line no-unused-vars
    return (
      <textarea {...props} ref='textarea'>
        {children}
      </textarea>
    );
  }

  componentWillReceiveProps(nextProps) {
    if (this.getValue(nextProps) !== this.getValue(this.props)) {
      this.dispatchEvent(UPDATE, true);
    }
  }

}
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react'
import {
  View,
  UIManager,
  findNodeHandle,
  requireNativeComponent,
} from 'react-native'

class BottomSheetBehavior extends Component {
  static propTypes = {
    ...View.propTypes,
    onSlide: PropTypes.func,
    onStateChanged: PropTypes.func,
  };

  static STATE_DRAGGING  = 1;
  static STATE_SETTLING  = 2;
  static STATE_EXPANDED  = 3;
  static STATE_COLLAPSED = 4;
  static STATE_HIDDEN    = 5;

  componentDidMount() {
    this.setRequestLayout()
  }

  componentDidUpdate() {
    this.setRequestLayout()
  }

  setRequestLayout() {
    UIManager.dispatchViewManagerCommand(
      findNodeHandle(this),
      UIManager.RCTBottomSheetBehaviorAndroid.Commands.setRequestLayout,
      [],
    )
  }

  onStateChange(e) {
    const { onStateChange } = this.props
    onStateChange && onStateChange(e)
  }

  onSlide(e) {
    const { onSlide } = this.props
    onSlide && onSlide(e)
  }

  render() {
    return (
      <RCTBottomSheetBehavior
        {...this.props}
        style={this.props.style}
        onSlide={this.onSlide.bind(this)}
        onStateChange={this.onStateChange.bind(this)}
        >
        {this.props.children}
      </RCTBottomSheetBehavior>
    )
  }
}

const RCTBottomSheetBehavior = requireNativeComponent('RCTBottomSheetBehaviorAndroid', BottomSheetBehavior, {
  nativeOnly: {
    hideable: true,
    peekHeight: true,
    onSlide: true,
    onStateChange: true,
  }
})

export default BottomSheetBehavior
<commit_msg>Added missing propTypes<commit_after>import React, { Component, PropTypes } from 'react'
import {
  View,
  UIManager,
  findNodeHandle,
  requireNativeComponent,
} from 'react-native'

class BottomSheetBehavior extends Component {
  static propTypes = {
    ...View.propTypes,
    state: PropTypes.oneOf([1, 2, 3, 4, 5]),
    hideable: PropTypes.bool,
    peekHeight: PropTypes.number,
    onSlide: PropTypes.func,
    onStateChanged: PropTypes.func,
  };

  static STATE_DRAGGING  = 1;
  static STATE_SETTLING  = 2;
  static STATE_EXPANDED  = 3;
  static STATE_COLLAPSED = 4;
  static STATE_HIDDEN    = 5;

  componentDidMount() {
    this.setRequestLayout()
  }

  componentDidUpdate() {
    this.setRequestLayout()
  }

  setRequestLayout() {
    UIManager.dispatchViewManagerCommand(
      findNodeHandle(this),
      UIManager.RCTBottomSheetBehaviorAndroid.Commands.setRequestLayout,
      [],
    )
  }

  onStateChange(e) {
    const { onStateChange } = this.props
    onStateChange && onStateChange(e)
  }

  onSlide(e) {
    const { onSlide } = this.props
    onSlide && onSlide(e)
  }

  render() {
    return (
      <RCTBottomSheetBehavior
        {...this.props}
        style={this.props.style}
        onSlide={this.onSlide.bind(this)}
        onStateChange={this.onStateChange.bind(this)}
        >
        {this.props.children}
      </RCTBottomSheetBehavior>
    )
  }
}

const RCTBottomSheetBehavior = requireNativeComponent('RCTBottomSheetBehaviorAndroid', BottomSheetBehavior)

export default BottomSheetBehavior
<|endoftext|>


<commit_before>import React from 'react'
import { ScrollView, Text, Image, View } from 'react-native'
import { Navigation } from 'react-native-navigation'

import { Images } from '../../shared/themes'
import styles from './launch-screen.styles'

export default class LaunchScreen extends React.Component {
  constructor (props) {
    super(props)
    Navigation.events().bindComponent(this)
  }
  componentDidAppear () {
    Navigation.mergeOptions(this.props.componentId, {
      sideMenu: {
        left: {
          enabled: true
        }
      }
    })
  }
  showSideMenu () {
    Navigation.mergeOptions(this.props.componentId, {
      sideMenu: {
        left: {
          visible: true
        }
      }
    })
  }

  navigationButtonPressed ({ buttonId }) {
    this.showSideMenu()
  }

  render () {
    return (
      <View style={styles.mainContainer} testID='launchScreen'>
        <Image source={Images.background} style={styles.backgroundImage} resizeMode='stretch' />
        <ScrollView style={styles.container}>
          <View style={styles.centered}>
            <Image source={Images.logoJhipster} style={styles.logo} />
          </View>

          <View style={styles.section} >
            <Image source={Images.ready} />
            <Text style={styles.sectionText}>
              {'Welcome to your Ignite JHipster app.'}
            </Text>
          </View>

        </ScrollView>
      </View>
    )
  }
}
<commit_msg>default sideMenu to closed state on launch-screen<commit_after>import React from 'react'
import { ScrollView, Text, Image, View } from 'react-native'
import { Navigation } from 'react-native-navigation'

import { Images } from '../../shared/themes'
import styles from './launch-screen.styles'

export default class LaunchScreen extends React.Component {
  constructor (props) {
    super(props)
    Navigation.events().bindComponent(this)
  }
  componentDidAppear () {
    Navigation.mergeOptions(this.props.componentId, {
      sideMenu: {
        left: {
          enabled: true,
          visible: false
        }
      }
    })
  }
  showSideMenu () {
    Navigation.mergeOptions(this.props.componentId, {
      sideMenu: {
        left: {
          visible: true
        }
      }
    })
  }

  navigationButtonPressed ({ buttonId }) {
    this.showSideMenu()
  }

  render () {
    return (
      <View style={styles.mainContainer} testID='launchScreen'>
        <Image source={Images.background} style={styles.backgroundImage} resizeMode='stretch' />
        <ScrollView style={styles.container}>
          <View style={styles.centered}>
            <Image source={Images.logoJhipster} style={styles.logo} />
          </View>

          <View style={styles.section} >
            <Image source={Images.ready} />
            <Text style={styles.sectionText}>
              {'Welcome to your Ignite JHipster app.'}
            </Text>
          </View>

        </ScrollView>
      </View>
    )
  }
}
<|endoftext|>


<commit_before>var labels = document.getElementsByClassName('filter-item');
var total = 0.0;
for (var i = 0; i < labels.length; i++) {
    element = labels[i];
    var scale = element.querySelector('.name');
    if (scale) {
      scale = scale.innerHTML;

      var count = element.querySelector('.count');

      if (count) {
        count = count.innerHTML;

        scale = parseFloat(scale);
        count = parseInt(count);
        if (!isNaN(scale) && !isNaN(count)) {
          total += scale * count;
        }
      }
    }
}

var display = document.createElement('span')
display.innerHTML = "| Total estimate: " + total.toString();
display.className = 'open';
console.log("1");
document.querySelector('.info-secondary').appendChild(display);
console.log("2");<commit_msg>Fix #2 in an ugly fashion, in that we don't have the same styling as when looking at a milestone.<commit_after>var labels = document.getElementsByClassName('filter-item');
var total = 0.0;
for (var i = 0; i < labels.length; i++) {
    element = labels[i];
    var scale = element.querySelector('.name');
    if (scale) {
      scale = scale.innerHTML;

      var count = element.querySelector('.count');

      if (count) {
        count = count.innerHTML;

        scale = parseFloat(scale);
        count = parseInt(count);
        if (!isNaN(scale) && !isNaN(count)) {
          total += scale * count;
        }
      }
    }
}

var hangPoint = document.querySelector('.info-secondary');
var totalDescription = "Total estimate: " + total.toString();

if (!hangPoint) {
  var progBar = document.querySelector('.sidebar-milestone-widget');
  var fakeInfo = document.createElement('div');
  progBar.appendChild(fakeInfo);
  hangPoint = fakeInfo;
} else {
  totalDescription = "| " + totalDescription;
}

var display = document.createElement('span');
display.innerHTML = totalDescription;
display.className = 'open';
hangPoint.appendChild(display);<|endoftext|>


<commit_before>export default {
    "$schema": "http://json-schema.org/draft-04/schema#",
    "definitions": {
        "children": {
            "type": "array",
            "uniqueItems": true,
            "items": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "children": {
                        "$ref": "#/definitions/children"
                    }
                },
                "required": ["id"]
            }
        }
    },
    "type": "object",
    "properties": {
        "id": {
            "type": "string"
        },
        "name": {
            "type": "string"
        },
        "sensors": {
            "$ref": "#/definitions/children"
        }
    },
    "additionalProperties": false,
    "required": [
        "id",
        "name"
    ]
};
<commit_msg>Added `description` and `shortDescription` fields on site api<commit_after>export default {
    "$schema": "http://json-schema.org/draft-04/schema#",
    "definitions": {
        "children": {
            "type": "array",
            "uniqueItems": true,
            "items": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "children": {
                        "$ref": "#/definitions/children"
                    }
                },
                "required": ["id"]
            }
        }
    },
    "type": "object",
    "properties": {
        "id": {
            "type": "string"
        },
        "name": {
            "type": "string"
        },
        "description": {
            "type": "string"
        },
        "shortDescription": {
            "type": "string"
        },
        "sensors": {
            "$ref": "#/definitions/children"
        }
    },
    "additionalProperties": false,
    "required": [
        "id",
        "name"
    ]
};
<|endoftext|>


<commit_before>/*jslint browser: true*/
/*global L */
/*global GEOHEX */
var geohexCode = null;
var startZoomLevel = 12;
var localStoragePrefix = "EW_"; // earthWatchers
var user = localStorage.getItem(localStoragePrefix + "user") || "anonymous";
var satelliteImages = null;
var map = null;
var defaultGeohexLevel = null;
var defaultSatelliteType = "Sentinel";
var selectedObservationType = null;
var project = null;
var projectObservationTypes = null;
var observationTypesObject = null;
var dragMarkerPosition = null;
var projectName = null;

function cbVisibilityClicked(isVisible){
    if(!isVisible){
        map.removeLayer(findLayerByType("earthWatchersNow"));
        map.removeLayer(findLayerByType("earthWatchersPrevious"));
        map.removeLayer(findLayerByType("earthWatchersOld"));
    }
    else{
        drawSatelliteImages(map, defaultSatelliteType);
    }
}

function gotoNextHexagon() {
    var url = location.href.replace(location.hash, "#/" + projectName);
    location.href = url;
    window.location.reload();
}

function goToHexagon(event) {
    event.originalEvent.preventDefault();
    var newGeohexCode = event.originalEvent.srcElement.id;
    goToGeohexCode(newGeohexCode);
}

function goToGeohexCode(code){
    var url = location.href.replace(location.hash, "#/" + projectName + "/" + code);
    location.href = url;

    var previousSelectedHexagon = geohexCode;
    geohexCode = code;

    removeMakersByType("navigation");
    removeMakersByType("observation");
    removeStyles(previousSelectedHexagon);

    addCurrentHexagonStyle(code);
    loadJSON("/api/observations/" + projectName + "/" + geohexCode + "/" + user, function (observations) {
        showObservations(observations);
    });

    getHexagonNavigation(geohexCode, map, user, projectName);

    var polygon = findLayerByName("hexagon" + code);
    centerOnPolygon(polygon);

    drawSatelliteImages(map, document.getElementById("satTypeLabel").innerText);

}

function showObservations(observations) {
    var status = getStatusHexagon(observations);
    if (status === "hasObservations") {
        drawObservations(observations, observationTypesObject);
        //setHexagonColor("hasObservations");
    }
}

function clearhexagon() {
    var observations = getObservationsCount();
    if (observations === 0) {
        //post/save there are no observations for this hexagon
        var geohexpoly = getGeohexPolygon(geohexCode,null);
        var cp = geohexpoly.getBounds().getCenter();

        postclearHexagon(user, geohexCode, cp.lng, cp.lat, project.properties.Name, function (resp1) {
            postObservation("clear", user, geohexCode, cp.lng, cp.lat, project.properties.Name, function (resp) {
                setHexagonColor("clear");
                var total = document.getElementById("hexagonstotal").innerHTML;
                loadUserStatistics(project.properties.Name,user,total);
            });
        });
    }
    else {
        var messageDiv = document.getElementById("messageDiv");
        messageDiv.style.display = 'block';
        messageDiv.innerHTML = "Remove observations first!";
        messageDiv.className = "message messagesShown";
        window.setTimeout(function(){messageDiv.style.display = 'none';},1500);
    }
}

function setObservationType(observationType) {
    selectedObservationType = observationType;
    styleObservationTypeButtons(projectObservationTypes, observationType.type);
}

function onMapClick(e) {
    var isInside = isPointInHexagon(geohexCode, e.latlng);
    if (isInside) {
        var observations = getObservationsCount();

        postObservation(selectedObservationType.type, user, geohexCode, e.latlng.lng, e.latlng.lat, project.properties.Name, function (resp) {
            var newMarker = getObservationMarker(map, e.latlng.lng, e.latlng.lat, geohexCode, selectedObservationType.name, resp.id, selectedObservationType,user,project.properties.Name);
            newMarker.options.type = "observation";
            newMarker.addTo(map);

            // update statistics
            var total = document.getElementById("hexagonstotal").innerHTML;
            loadUserStatistics(project.properties.Name,user,total);

        });

        if (observations === 0) {
            setHexagonColor("hasObservations");
        }
    }
}

function setHexagonColor(status) {
    var layer = findLayerByName("hexagon" + geohexCode);
    if (status === "hasObservations") {
        layer.setStyle({color: "#FF0000"});
    }
    else if (status === "clear") {
        layer.setStyle({color: "#00FF00"});
    }
}

function initializeRouting() {
    Path.map("#/:project").to(function () {
        // sample: #/borneo
        geohexCode = null;
        projectName = this.params["project"];
    });
    Path.map("#/:project/:hex").to(function () {
        // sample: #/borneo/PO2670248
        projectName = this.params["project"];
        geohexCode = this.params["hex"];
    });
    Path.listen();
}

(function (window, document, L) {
    "use strict";
    L.Icon.Default.imagePath = "images/";
    initializeRouting();

    initUserPanel();

    loadJSON("data/observationTypes.json", function (observationTypes) {
        loadJSON("data/projects.geojson", function (projects) {
            if (projectName === null) {
                // first project is the default project...
                projectName = projects.features[0].properties.Name;
            }
            project = getProjectByName(projects, projectName);
            projectObservationTypes = project.properties.ObservationCategories.split(",");

            observationTypesObject = observationTypes;
            addObservationTypeButtons(projectObservationTypes, observationTypes);

            defaultGeohexLevel = project.properties.GeohexLevel;

            if (geohexCode === null) {
                geohexCode = getRandomHexagon(project, defaultGeohexLevel);
                location.hash = "#/" + projectName + "/" + geohexCode;
            }

            var hexagons = getTotalHexagons();
            console.log("Total Hexagons: " + hexagons.length);

            loadJSON("/api/observations/" + projectName + "/" + geohexCode + "/" + user, function (observations) {

                loadUserStatistics(projectName, user, hexagons.length);

                map = L.map("map", {
                    zoomControl: false,
                    attributionControl: false
                });
                L.control.zoom({
                    position:'topleft'
                }).addTo(map);

                map.on("click", onMapClick);

                drawSatelliteImages(map, defaultSatelliteType);

                drawHexagons(map, hexagons);

                getHexagonNavigation(geohexCode, map,user,projectName);

                var polygon = getGeohexPolygon(geohexCode, null);
                addCurrentHexagonStyle(geohexCode);

                var centerHex = centerOnPolygon(polygon);

                showObservations(observations);

                L.control.scale({imperial: false, position: "topleft"}).addTo(map);

                var ggl2 = new L.Google("HYBRID");
                map.addLayer(ggl2);

                L.geoJson(projects, {fill: false}).addTo(map);

            });
        });
    });

}(window, document, L));
<commit_msg>back to start zoom level 13<commit_after>/*jslint browser: true*/
/*global L */
/*global GEOHEX */
var geohexCode = null;
var startZoomLevel = 13;
var localStoragePrefix = "EW_"; // earthWatchers
var user = localStorage.getItem(localStoragePrefix + "user") || "anonymous";
var satelliteImages = null;
var map = null;
var defaultGeohexLevel = null;
var defaultSatelliteType = "Sentinel";
var selectedObservationType = null;
var project = null;
var projectObservationTypes = null;
var observationTypesObject = null;
var dragMarkerPosition = null;
var projectName = null;

function cbVisibilityClicked(isVisible){
    if(!isVisible){
        map.removeLayer(findLayerByType("earthWatchersNow"));
        map.removeLayer(findLayerByType("earthWatchersPrevious"));
        map.removeLayer(findLayerByType("earthWatchersOld"));
    }
    else{
        drawSatelliteImages(map, defaultSatelliteType);
    }
}

function gotoNextHexagon() {
    var url = location.href.replace(location.hash, "#/" + projectName);
    location.href = url;
    window.location.reload();
}

function goToHexagon(event) {
    event.originalEvent.preventDefault();
    var newGeohexCode = event.originalEvent.srcElement.id;
    goToGeohexCode(newGeohexCode);
}

function goToGeohexCode(code){
    var url = location.href.replace(location.hash, "#/" + projectName + "/" + code);
    location.href = url;

    var previousSelectedHexagon = geohexCode;
    geohexCode = code;

    removeMakersByType("navigation");
    removeMakersByType("observation");
    removeStyles(previousSelectedHexagon);

    addCurrentHexagonStyle(code);
    loadJSON("/api/observations/" + projectName + "/" + geohexCode + "/" + user, function (observations) {
        showObservations(observations);
    });

    getHexagonNavigation(geohexCode, map, user, projectName);

    var polygon = findLayerByName("hexagon" + code);
    centerOnPolygon(polygon);

    drawSatelliteImages(map, document.getElementById("satTypeLabel").innerText);

}

function showObservations(observations) {
    var status = getStatusHexagon(observations);
    if (status === "hasObservations") {
        drawObservations(observations, observationTypesObject);
        //setHexagonColor("hasObservations");
    }
}

function clearhexagon() {
    var observations = getObservationsCount();
    if (observations === 0) {
        //post/save there are no observations for this hexagon
        var geohexpoly = getGeohexPolygon(geohexCode,null);
        var cp = geohexpoly.getBounds().getCenter();

        postclearHexagon(user, geohexCode, cp.lng, cp.lat, project.properties.Name, function (resp1) {
            postObservation("clear", user, geohexCode, cp.lng, cp.lat, project.properties.Name, function (resp) {
                setHexagonColor("clear");
                var total = document.getElementById("hexagonstotal").innerHTML;
                loadUserStatistics(project.properties.Name,user,total);
            });
        });
    }
    else {
        var messageDiv = document.getElementById("messageDiv");
        messageDiv.style.display = 'block';
        messageDiv.innerHTML = "Remove observations first!";
        messageDiv.className = "message messagesShown";
        window.setTimeout(function(){messageDiv.style.display = 'none';},1500);
    }
}

function setObservationType(observationType) {
    selectedObservationType = observationType;
    styleObservationTypeButtons(projectObservationTypes, observationType.type);
}

function onMapClick(e) {
    var isInside = isPointInHexagon(geohexCode, e.latlng);
    if (isInside) {
        var observations = getObservationsCount();

        postObservation(selectedObservationType.type, user, geohexCode, e.latlng.lng, e.latlng.lat, project.properties.Name, function (resp) {
            var newMarker = getObservationMarker(map, e.latlng.lng, e.latlng.lat, geohexCode, selectedObservationType.name, resp.id, selectedObservationType,user,project.properties.Name);
            newMarker.options.type = "observation";
            newMarker.addTo(map);

            // update statistics
            var total = document.getElementById("hexagonstotal").innerHTML;
            loadUserStatistics(project.properties.Name,user,total);

        });

        if (observations === 0) {
            setHexagonColor("hasObservations");
        }
    }
}

function setHexagonColor(status) {
    var layer = findLayerByName("hexagon" + geohexCode);
    if (status === "hasObservations") {
        layer.setStyle({color: "#FF0000"});
    }
    else if (status === "clear") {
        layer.setStyle({color: "#00FF00"});
    }
}

function initializeRouting() {
    Path.map("#/:project").to(function () {
        // sample: #/borneo
        geohexCode = null;
        projectName = this.params["project"];
    });
    Path.map("#/:project/:hex").to(function () {
        // sample: #/borneo/PO2670248
        projectName = this.params["project"];
        geohexCode = this.params["hex"];
    });
    Path.listen();
}

(function (window, document, L) {
    "use strict";
    L.Icon.Default.imagePath = "images/";
    initializeRouting();

    initUserPanel();

    loadJSON("data/observationTypes.json", function (observationTypes) {
        loadJSON("data/projects.geojson", function (projects) {
            if (projectName === null) {
                // first project is the default project...
                projectName = projects.features[0].properties.Name;
            }
            project = getProjectByName(projects, projectName);
            projectObservationTypes = project.properties.ObservationCategories.split(",");

            observationTypesObject = observationTypes;
            addObservationTypeButtons(projectObservationTypes, observationTypes);

            defaultGeohexLevel = project.properties.GeohexLevel;

            if (geohexCode === null) {
                geohexCode = getRandomHexagon(project, defaultGeohexLevel);
                location.hash = "#/" + projectName + "/" + geohexCode;
            }

            var hexagons = getTotalHexagons();
            console.log("Total Hexagons: " + hexagons.length);

            loadJSON("/api/observations/" + projectName + "/" + geohexCode + "/" + user, function (observations) {

                loadUserStatistics(projectName, user, hexagons.length);

                map = L.map("map", {
                    zoomControl: false,
                    attributionControl: false
                });
                L.control.zoom({
                    position:'topleft'
                }).addTo(map);

                map.on("click", onMapClick);

                drawSatelliteImages(map, defaultSatelliteType);

                drawHexagons(map, hexagons);

                getHexagonNavigation(geohexCode, map,user,projectName);

                var polygon = getGeohexPolygon(geohexCode, null);
                addCurrentHexagonStyle(geohexCode);

                var centerHex = centerOnPolygon(polygon);

                showObservations(observations);

                L.control.scale({imperial: false, position: "topleft"}).addTo(map);

                var ggl2 = new L.Google("HYBRID");
                map.addLayer(ggl2);

                L.geoJson(projects, {fill: false}).addTo(map);

            });
        });
    });

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


<commit_before>var PromiseSolver = require('./PromiseSolver.js');
var P = require('bluebird');

/**
 * Object promise resolver
 *
 * @extends PromiseSolver
 * @constructor
 */
function ObjectPromiseSolver() {}
ObjectPromiseSolver.prototype = Object.create(PromiseSolver.prototype);
ObjectPromiseSolver.prototype.constructor = ObjectPromiseSolver;

/**
 * Takes an array of objects and resolve or reject them all.
 *
 * @param {array} promises
 * @returns {Array}
 */
ObjectPromiseSolver.prototype.all = function(promises){
  return P.all(
    promises.map(
      function(promise) {
        var error, success;
        error = function (res) {
          promise.err = true;
          promise.res = res;
          return  promise;
        };
        success = function (res) {
          promise.err = false;
          promise.res = res;
          return  promise;
        };

        if (!promise.p || !promise.p.then) return error(new Error('The object missing p property that holds the promise.'));
        return promise.p.then(success,error)
      }
    )
  );
};

/**
 * Overrides parent and simply return the Array
 *
 * @param {Array} res
 * @returns {Array}
 */
ObjectPromiseSolver.prototype.clearResponse = function(res) { return res;};

module.exports = (function(){ return ObjectPromiseSolver; })();
<commit_msg>Update ObjectPromiseSolver.js<commit_after>var PromiseSolver = require('./PromiseSolver.js');
var P = require('bluebird');

/**
 * Object promise resolver
 *
 * @extends PromiseSolver
 * @constructor
 */
function ObjectPromiseSolver() {}
ObjectPromiseSolver.prototype = Object.create(PromiseSolver.prototype);
ObjectPromiseSolver.prototype.constructor = ObjectPromiseSolver;

/**
 * Takes an array of objects and resolve or reject them all.
 *
 * @param {array} promises
 * @returns {Array}
 */
ObjectPromiseSolver.prototype.all = function(promises) {
  return P.all(
    promises.map(
      function(promise) {
        var error, success;
        error = function (res) {
          promise.err = true;
          promise.res = res;
          return  promise;
        };
        success = function (res) {
          promise.err = false;
          promise.res = res;
          return  promise;
        };

        if (!promise.p || !promise.p.then) return error(new Error('The object missing p property that holds the promise.'));
        return promise.p.then(success,error)
      }
    )
  );
};

/**
 * Overrides parent and simply return the Array
 *
 * @param {Array} res
 * @returns {Array}
 */
ObjectPromiseSolver.prototype.clearResponse = function(res) { return res;};

module.exports = (function(){ return ObjectPromiseSolver; })();
<|endoftext|>


<commit_before>/**
 * 1.init element
 * 2.generate para
 *
 * prevent default
 * document.execCommand
 * delete key
 * tab key
 * clipboard
 *
 * modules:
 * selectionchange,
 * changeNode:{insertNewNode,changeTag,changeFont,changeJustify...}
 * drag & drop,
 */
import Status from './Status/status';
import Drag from './Drag/drag';
import handleSl from './HandleSelection/HandleSelection';
import util from './util';
import Template from './Template/template';
import Format from './Format/format';

const inlinelist = [
  'bold',
  'italic',
  'strikeThrough',
  'underline',
  'subscript',
  'superscript',
  'fontSize',
  'fontColor'
]

const paralist = ['fontSize', 'lineHeight', 'color', 'textAlign']

const DEFULT_CALLBACK = (...all)=>{
  console.log(all);
}

class Edt {

  constructor(element, {format,callback} = {format :false,callback :DEFULT_CALLBACK}) {
    this.el = element;
    this.selection = undefined;
    this.rangeCopy = undefined;
    this.status = undefined;
    Drag.init(this.el, Template.map,this.dragBack());
    this.format = format;
    this.callbacks = [];
    this.addCallback(callback);
  }

  getDragin(){
    return Drag.generateDragin(this);
  }

  styleGen() {
    let style = document.createElement('style');
    style.type = 'text/css';
    style.innerHTML = `.edt-page{
      font-size: 12px;
      line-height: 1.2;
      color: #212121;
    }
    .edt-page .para{
      padding: 8px 0;
      font-size: 12px;
      line-height: 1.2;
      color: #212121;
    }`
    return style;
  }

  init() {
    this.el.classList.add('edt-page');
    document.head.appendChild(this.styleGen());
    document.execCommand('styleWithCss', false, false);
    document.addEventListener('selectionchange', e => {
      // console.log(e);
      if (document.activeElement === this.el) {
        let sl = window.getSelection();
        if (sl.rangeCount) {
          //judge the cursor in the el
          let tmp = handleSl.handleSelection(sl);
          // let num = 0;
          // if (this.selection) {
          //   num = handleSl.compareSelection(this.selection, tmp);
          // }
          this.selection = tmp;
          this.alertUI({type:0,value:Status.computeStyle(tmp, this.el)});
        }
      }
    });
    this.formatDoc();
    this.editDoc();
    // this.editLayout();
  }

  formatDoc() {
    console.log(this.format);
    if (this.format) {
      return;
    }
    let [result,
      changed] = Format(this.el.innerHTML);
    if (changed) {
      this.el.innerHTML = '';
      this.el.appendChild(result);
    }
  }

  editDoc() {
    this.status = 1;
    this.el.setAttribute('contenteditable', 'true');
    Drag.unbind();
  }

  editLayout() {
    this.status = 2;
    this.el.setAttribute('contenteditable', 'false');
    Drag.bind();
  }

  alertUI({type,value}) {
    this.callbacks.forEach(e => {
      e({type,value});
    })
  }

  dragBack(){
    return (ele)=>{
      this.alertUI({type:2,value:ele});
    }
  }

  addTemplate({value,innerHTML,outer,callback}){
    Template.addTemplate({value,innerHTML,outer,callback});
  }

  addCallback(fn){
    if(!this.callbacks.includes(fn)){
      this.callbacks.push(fn);
    }
  }

  /**
   * [command description]
   * @param  {number} level 0:inline,1:para,2:full
   * @param  {number} type  the index of stylelist
   * @return {[type]}       [description]
   */
  command({level, type, value}) {
    if (this.status !== 1) {
      return
    }
    console.log(level);
    if (level === 0) {
      if (type < 6) {
        document.execCommand(inlinelist[type]);
      } else {
        console.log(this.selection.type);
        [...this.selection.origin.querySelectorAll('*')].forEach(e => {
          e.style[inlinelist[type]] = '';
          if (e.nodeName === 'SPAN' && !e.style[0]) {
            util.replaceWidthChild(e);
          }
        })
        if (this.selection.type === 0) {
          let span = document.createElement('span');
          span.style[inlinelist[type]] = value;
          span.appendChild(this.selection.origin);
          this.selection.range.deleteContents();
          this.selection.range.insertNode(span);
        } else {
          [...this.selection.origin.children].forEach(para => {
            para.innerHTML = `<span style="${util.camlToHypen(inlinelist[type])}:${value}"'>${para.innerHTML}</span>`
          })
          this.selection.range.deleteContents();
          let firstChild = this.selection.origin.firstChild.children[0];
          let lastChild = this.selection.origin.lastChild.children[0];
          this.selection.origin.firstChild.remove();
          this.selection.origin.lastChild.remove();
          this.selection.range.insertNode(this.selection.origin);
          this.selection.select.startContainer.appendChild(firstChild);
          this.selection.select.endContainer.insertBefore(lastChild, this.selection.select.endContainer.firstChild);
          this.selection.range.setStart(firstChild, 0);
          this.selection.range.setEnd(lastChild, lastChild.childNodes.length);
        }
        window.getSelection().addRange(this.selection.range);
      }
    } else if (level === 1) {
      if (this.selection.type === 0) {
        this.selection.parent.style[paralist[type]] = value;
      } else {
        this.selection.select.startContainer.style[paralist[type]] = value;
        this.selection.select.endContainer.style[paralist[type]] = value;
        let next = this.selection.select.startContainer.nextElementSibling;
        while (next && next !== this.selection.select.endContainer) {
          next.style[paralist[type]] = value;
          next = next.nextElementSibling;
        }
      }
    } else {
      this.el.style[paralist[type]] = value;
    }
  }

  // createNewPara(type){
  //   let newPara = document.createElement('div');
  //   newPara.classList.add('para');
  //   return newPara;
  // }

}

export default Edt;
<commit_msg>0.1.0-bug-fix destructuring assignment to default value<commit_after>/**
 * 1.init element
 * 2.generate para
 *
 * prevent default
 * document.execCommand
 * delete key
 * tab key
 * clipboard
 *
 * modules:
 * selectionchange,
 * changeNode:{insertNewNode,changeTag,changeFont,changeJustify...}
 * drag & drop,
 */
import Status from './Status/status';
import Drag from './Drag/drag';
import handleSl from './HandleSelection/HandleSelection';
import util from './util';
import Template from './Template/template';
import Format from './Format/format';

const inlinelist = [
  'bold',
  'italic',
  'strikeThrough',
  'underline',
  'subscript',
  'superscript',
  'fontSize',
  'fontColor'
]

const paralist = ['fontSize', 'lineHeight', 'color', 'textAlign']

const DEFULT_CALLBACK = (...all)=>{
  console.log(all);
}

class Edt {

  constructor(element, {format = false,callback = DEFULT_CALLBACK} = {}) {
    this.el = element;
    this.selection = undefined;
    this.rangeCopy = undefined;
    this.status = undefined;
    Drag.init(this.el, Template.map,this.dragBack());
    this.format = format;
    this.callbacks = [];
    this.addCallback(callback);
  }

  getDragin(){
    return Drag.generateDragin(this);
  }

  styleGen() {
    let style = document.createElement('style');
    style.type = 'text/css';
    style.innerHTML = `.edt-page{
      font-size: 12px;
      line-height: 1.2;
      color: #212121;
    }
    .edt-page .para{
      padding: 8px 0;
      font-size: 12px;
      line-height: 1.2;
      color: #212121;
    }`
    return style;
  }

  init() {
    this.el.classList.add('edt-page');
    document.head.appendChild(this.styleGen());
    document.execCommand('styleWithCss', false, false);
    document.addEventListener('selectionchange', e => {
      // console.log(e);
      if (document.activeElement === this.el) {
        let sl = window.getSelection();
        if (sl.rangeCount) {
          //judge the cursor in the el
          let tmp = handleSl.handleSelection(sl);
          // let num = 0;
          // if (this.selection) {
          //   num = handleSl.compareSelection(this.selection, tmp);
          // }
          this.selection = tmp;
          this.alertUI({type:0,value:Status.computeStyle(tmp, this.el)});
        }
      }
    });
    this.formatDoc();
    this.editDoc();
    // this.editLayout();
  }

  formatDoc() {
    console.log(this.format);
    if (!this.format) {
      return;
    }
    let [result,
      changed] = Format(this.el.innerHTML);
    if (changed) {
      this.el.innerHTML = '';
      this.el.appendChild(result);
    }
  }

  editDoc() {
    this.status = 1;
    this.el.setAttribute('contenteditable', 'true');
    Drag.unbind();
  }

  editLayout() {
    this.status = 2;
    this.el.setAttribute('contenteditable', 'false');
    Drag.bind();
    this.selection = undefined;
  }

  alertUI({type,value}) {
    this.callbacks.forEach(e => {
      e({type,value});
    })
  }

  dragBack(){
    return (ele)=>{
      this.alertUI({type:2,value:ele});
    }
  }

  addTemplate({value,innerHTML,outer,callback}){
    Template.addTemplate({value,innerHTML,outer,callback});
  }

  addCallback(fn){
    if(!this.callbacks.includes(fn)){
      this.callbacks.push(fn);
    }
  }

  /**
   * [command description]
   * @param  {number} level 0:inline,1:para,2:full
   * @param  {number} type  the index of stylelist
   * @return {[type]}       [description]
   */
  command({level, type, value}) {
    if (this.status !== 1) {
      return
    }
    if(!this.selection){
      return
    }
    console.log(level);
    let _selection = this.selection;
    if (level === 0) {
      if (type < 6) {
        document.execCommand(inlinelist[type]);
      } else {
        console.log(_selection.type);
        [..._selection.origin.querySelectorAll('*')].forEach(e => {
          e.style[inlinelist[type]] = '';
          if (e.nodeName === 'SPAN' && !e.style[0]) {
            util.replaceWidthChild(e);
          }
        })
        if (_selection.type === 0) {
          let span = document.createElement('span');
          span.style[inlinelist[type]] = value;
          span.appendChild(_selection.origin);
          _selection.range.deleteContents();
          _selection.range.insertNode(span);
        } else {
          [..._selection.origin.children].forEach(para => {
            para.innerHTML = `<span style="${util.camlToHypen(inlinelist[type])}:${value}"'>${para.innerHTML}</span>`
          })
          _selection.range.deleteContents();
          let firstChild = _selection.origin.firstChild.children[0];
          let lastChild = _selection.origin.lastChild.children[0];
          _selection.origin.firstChild.remove();
          _selection.origin.lastChild.remove();
          _selection.range.insertNode(_selection.origin);
          _selection.select.startContainer.appendChild(firstChild);
          _selection.select.endContainer.insertBefore(lastChild, _selection.select.endContainer.firstChild);
          _selection.range.setStart(firstChild, 0);
          _selection.range.setEnd(lastChild, lastChild.childNodes.length);
        }
        window.getSelection().addRange(_selection.range);
      }
    } else if (level === 1) {
      if (_selection.type === 0) {
        _selection.parent.style[paralist[type]] = value;
      } else {
        _selection.select.startContainer.style[paralist[type]] = value;
        _selection.select.endContainer.style[paralist[type]] = value;
        let next = _selection.select.startContainer.nextElementSibling;
        while (next && next !== _selection.select.endContainer) {
          next.style[paralist[type]] = value;
          next = next.nextElementSibling;
        }
      }
    } else {
      this.el.style[paralist[type]] = value;
    }
  }

  // createNewPara(type){
  //   let newPara = document.createElement('div');
  //   newPara.classList.add('para');
  //   return newPara;
  // }

}

export default Edt;
<|endoftext|>


<commit_before>/**
 * Template Helpers
 */
Template.TestCaseList.helpers({
  getGroups: function () {
    return TestGroups.find({ parentGroupId: null, projectVersionId: this.version._id }, { sort: { title: 1 } });
  },
  getTestCases: function () {
    return TestCases.find({ testGroupId: null, projectVersionId: this.version._id }, { sort: { title: 1 } });
  }
});

/**
 * Template Event Handlers
 */
Template.TestCaseList.events({
  "keyup .add-item-form input": function (e, instance) {
    var value = $(e.target).val();

    if(e.which == 13 && value.length >= 2){
      //instance.$(".add-item-form .dropdown-toggle").trigger("click");
      // Search for the entered text
      instance.$(".add-item-form .btn-search").trigger("click");
    } else if(value.length >= 2){
      if(instance.$(".add-item-form .btn-add-item").attr("disabled")){
        instance.$(".add-item-form .btn-add-item").removeAttr("disabled");
      }
      if(instance.$(".add-item-form .btn-search").attr("disabled")){
        instance.$(".add-item-form .btn-search").removeAttr("disabled");
      }
    } else {
      instance.$(".add-item-form .btn-add-item").attr("disabled", "disabled");
      instance.$(".add-item-form .btn-search").attr("disabled", "disabled");
    }
  },
  "click .btn-search": function (e, instance) {
    var search = instance.$(".add-item-form input").val();

    if(search.length < 2){
      return;
    }

    // show the clear button
    instance.$(".field-clear-btn").show();

    // hide everything from the list
    instance.$(".test-case-list-selectable").hide();

    // show everything that matches the search
    var highlight = function (item) {
      var item = instance.$(".test-case-list-selectable[data-pk='" + item._id + "']")
      item.show().addClass("highlight");
      item.parents(".test-case-list-group-items").each(function (i, el) {
        var parentInstance = Blaze.getView(el).templateInstance();
        if(parentInstance.expanded){
          parentInstance.$(".test-case-list-selectable").first().show();
          parentInstance.expanded.set(true);
        }
      });
    };
    TestCases.find({ title: {$regex: search, $options: "i"}, projectVersionId: this.version._id }).forEach(highlight);
    TestGroups.find({ title: {$regex: search, $options: "i"}, projectVersionId: this.version._id }).forEach(highlight);

    // show no results if nothing matched
    if(!instance.$(".test-case-list-selectable.highlight").length){
      instance.$(".search-no-results").show();
    }
  },
  "click .field-clear-btn": function (e, instance) {
    instance.$(".add-item-form input").val("");
    instance.$(".field-clear-btn").hide();
    instance.$(".search-no-results").hide();
    instance.$(".test-case-list-selectable.highlight").removeClass("highlight");
    instance.$(".test-case-list-selectable").show();
  },
  "click .add-item-form a": function (e, instance) {
    var itemType = $(e.target).closest("a").attr("data-name"),
      itemName = $(".add-item-form input").val().trim(),
      version = instance.data.version,
      groupId = instance.$(".test-case-list-group.selected").attr("data-group-id");

    if(itemType && itemName && itemName.length){
      if(itemType == "testcase"){
        TestCases.insert({
          projectId: version.projectId,
          projectVersionId: version._id,
          testGroupId: groupId,
          title: itemName
        }, function (error, result) {
          if(error){
            Meteor.log.error("Failed to insert test case: " + error.message);
            Dialog.error("Failed to insert test case: " + error.message);
          } else {
            $(".add-item-form input").val("")
          }
        });
      } else if(itemType == "testgroup") {
        TestGroups.insert({
          projectId: version.projectId,
          projectVersionId: version._id,
          parentGroupId: groupId,
          title: itemName
        }, function (error, result) {
          if(error){
            Meteor.log.error("Failed to insert test group: " + error.message);
            Dialog.error("Failed to insert test group: " + error.message);
          } else {
            $(".add-item-form input").val("")
          }
        });
      }
    }
  },
  "click .test-case-list-item": function (e, instance) {
    if(instance.data.editable){
      var selectable = $(e.target).closest(".test-case-list-item");
      instance.$(".test-case-list-item.selected").removeClass("selected");
      selectable.addClass("selected");

      if(instance.data.testCaseId){
        $(".test-case-content").addClass("intro-slide-left");
        setTimeout(function () {
          instance.data.testCaseId.set(selectable.attr("data-pk"));
          $(".test-case-content").removeClass("intro-slide-left");
        }, 500);
      }
    }
  },
  "click .test-case-list-group": function (e, instance) {
    var selectable = $(e.target).closest(".test-case-list-group"),
      wasSelected = selectable.hasClass("selected");

    instance.$(".test-case-list-group.selected").removeClass("selected");
    if(!wasSelected){
      selectable.addClass("selected");
    }
  },
  // make sure the draggable and droppable items stay up to date
  "mouseover .test-case-list-selectable:not(.ui-draggable)": function (e, instance) {
    $(e.target).closest(instance.draggableSelector).draggable(instance.draggableOptions);
  },
  "mouseover .test-case-list-group:not(.ui-droppable)": function (e, instance) {
    if(instance.data.editable){
      $(e.target).closest(".test-case-list-group").droppable(instance.droppableOptions);
    }
  }
});

/**
 * Template Created
 */
Template.TestCaseList.created = function () {

};

/**
 * Template Rendered
 */
Template.TestCaseList.rendered = function () {
  var instance = Template.instance();

  // setup the draggable config
  instance.draggableSelector = ".test-case-list-selectable";
  instance.draggableOptions = {
    revert: "invalid",
    distance: 5,
    start: function (event, ui) {
      ui.helper.addClass("in-drag");
    },
    stop: function (event, ui) {
      ui.helper.removeClass("in-drag");
    }
  };
  if(instance.data.editable){
    instance.draggableOptions.axis = "y";
  }
  if(instance.data.connectToSortable){
    instance.draggableOptions.connectToSortable = instance.data.connectToSortable;
    instance.draggableOptions.helper = "clone";
    //instance.draggableSelector = ".test-case-list-item";
  }

  // make the list items draggable
  instance.$(instance.draggableSelector).draggable(instance.draggableOptions);

  if(instance.data.editable) {
    // setup the droppable config
    instance.droppableOptions = {
      greedy: true,
      hoverClass: "test-case-list-drop-hover",
      drop: function (event, ui) {
        var groupId = $(this).attr("data-group-id"),
          itemId = ui.draggable.attr("data-pk"),
          itemIsGroup = ui.draggable.hasClass("test-case-list-group");
        console.log("Drop: ", itemId, "on", groupId);
        if (groupId && itemId) {
          if (itemIsGroup) {
            TestGroups.update(itemId, {$set: {parentGroupId: groupId}}, function (error) {
              if (error) {
                Meteor.log.error("Failed to update parent group: " + error.message);
                Dialog.error("Failed to update parent group: " + error.message);
              }
            });
          } else {
            TestCases.update(itemId, {$set: {testGroupId: groupId}}, function (error) {
              if (error) {
                Meteor.log.error("Failed to update test group: " + error.message);
                Dialog.error("Failed to update test group: " + error.message);
              }
            });
          }
        }
      },
      accept: function (el) {
        var dragParentId = $(el).attr("data-parent-id"),
          dragId = $(el).attr("data-group-id"),
          targetId = $(this).attr("data-group-id"),
          isChild = false;
        if (dragId) {
          isChild = $(this).closest("[data-group-id='" + dragId + "']").length > 0;
        }
        return dragParentId !== targetId && !isChild;
      }
    };

    // make the groups droppable
    instance.$(".test-case-list-group").droppable(instance.droppableOptions);
  }
};

/**
 * Template Destroyed
 */
Template.TestCaseList.destroyed = function () {

};
<commit_msg>Removed transition animations<commit_after>/**
 * Template Helpers
 */
Template.TestCaseList.helpers({
  getGroups: function () {
    return TestGroups.find({ parentGroupId: null, projectVersionId: this.version._id }, { sort: { title: 1 } });
  },
  getTestCases: function () {
    return TestCases.find({ testGroupId: null, projectVersionId: this.version._id }, { sort: { title: 1 } });
  }
});

/**
 * Template Event Handlers
 */
Template.TestCaseList.events({
  "keyup .add-item-form input": function (e, instance) {
    var value = $(e.target).val();

    if(e.which == 13 && value.length >= 2){
      //instance.$(".add-item-form .dropdown-toggle").trigger("click");
      // Search for the entered text
      instance.$(".add-item-form .btn-search").trigger("click");
    } else if(value.length >= 2){
      if(instance.$(".add-item-form .btn-add-item").attr("disabled")){
        instance.$(".add-item-form .btn-add-item").removeAttr("disabled");
      }
      if(instance.$(".add-item-form .btn-search").attr("disabled")){
        instance.$(".add-item-form .btn-search").removeAttr("disabled");
      }
    } else {
      instance.$(".add-item-form .btn-add-item").attr("disabled", "disabled");
      instance.$(".add-item-form .btn-search").attr("disabled", "disabled");
    }
  },
  "click .btn-search": function (e, instance) {
    var search = instance.$(".add-item-form input").val();

    if(search.length < 2){
      return;
    }

    // show the clear button
    instance.$(".field-clear-btn").show();

    // hide everything from the list
    instance.$(".test-case-list-selectable").hide();

    // show everything that matches the search
    var highlight = function (item) {
      var item = instance.$(".test-case-list-selectable[data-pk='" + item._id + "']")
      item.show().addClass("highlight");
      item.parents(".test-case-list-group-items").each(function (i, el) {
        var parentInstance = Blaze.getView(el).templateInstance();
        if(parentInstance.expanded){
          parentInstance.$(".test-case-list-selectable").first().show();
          parentInstance.expanded.set(true);
        }
      });
    };
    TestCases.find({ title: {$regex: search, $options: "i"}, projectVersionId: this.version._id }).forEach(highlight);
    TestGroups.find({ title: {$regex: search, $options: "i"}, projectVersionId: this.version._id }).forEach(highlight);

    // show no results if nothing matched
    if(!instance.$(".test-case-list-selectable.highlight").length){
      instance.$(".search-no-results").show();
    }
  },
  "click .field-clear-btn": function (e, instance) {
    instance.$(".add-item-form input").val("");
    instance.$(".field-clear-btn").hide();
    instance.$(".search-no-results").hide();
    instance.$(".test-case-list-selectable.highlight").removeClass("highlight");
    instance.$(".test-case-list-selectable").show();
  },
  "click .add-item-form a": function (e, instance) {
    var itemType = $(e.target).closest("a").attr("data-name"),
      itemName = $(".add-item-form input").val().trim(),
      version = instance.data.version,
      groupId = instance.$(".test-case-list-group.selected").attr("data-group-id");

    if(itemType && itemName && itemName.length){
      if(itemType == "testcase"){
        TestCases.insert({
          projectId: version.projectId,
          projectVersionId: version._id,
          testGroupId: groupId,
          title: itemName
        }, function (error, result) {
          if(error){
            Meteor.log.error("Failed to insert test case: " + error.message);
            Dialog.error("Failed to insert test case: " + error.message);
          } else {
            $(".add-item-form input").val("")
          }
        });
      } else if(itemType == "testgroup") {
        TestGroups.insert({
          projectId: version.projectId,
          projectVersionId: version._id,
          parentGroupId: groupId,
          title: itemName
        }, function (error, result) {
          if(error){
            Meteor.log.error("Failed to insert test group: " + error.message);
            Dialog.error("Failed to insert test group: " + error.message);
          } else {
            $(".add-item-form input").val("")
          }
        });
      }
    }
  },
  "click .test-case-list-item": function (e, instance) {
    if(instance.data.editable){
      var selectable = $(e.target).closest(".test-case-list-item");
      instance.$(".test-case-list-item.selected").removeClass("selected");
      selectable.addClass("selected");

      if(instance.data.testCaseId){
        instance.data.testCaseId.set(selectable.attr("data-pk"));
      }
    }
  },
  "click .test-case-list-group": function (e, instance) {
    var selectable = $(e.target).closest(".test-case-list-group"),
      wasSelected = selectable.hasClass("selected");

    instance.$(".test-case-list-group.selected").removeClass("selected");
    if(!wasSelected){
      selectable.addClass("selected");
    }
  },
  // make sure the draggable and droppable items stay up to date
  "mouseover .test-case-list-selectable:not(.ui-draggable)": function (e, instance) {
    $(e.target).closest(instance.draggableSelector).draggable(instance.draggableOptions);
  },
  "mouseover .test-case-list-group:not(.ui-droppable)": function (e, instance) {
    if(instance.data.editable){
      $(e.target).closest(".test-case-list-group").droppable(instance.droppableOptions);
    }
  }
});

/**
 * Template Created
 */
Template.TestCaseList.created = function () {

};

/**
 * Template Rendered
 */
Template.TestCaseList.rendered = function () {
  var instance = Template.instance();

  // setup the draggable config
  instance.draggableSelector = ".test-case-list-selectable";
  instance.draggableOptions = {
    revert: "invalid",
    distance: 5,
    start: function (event, ui) {
      ui.helper.addClass("in-drag");
    },
    stop: function (event, ui) {
      ui.helper.removeClass("in-drag");
    }
  };
  if(instance.data.editable){
    instance.draggableOptions.axis = "y";
  }
  if(instance.data.connectToSortable){
    instance.draggableOptions.connectToSortable = instance.data.connectToSortable;
    instance.draggableOptions.helper = "clone";
    //instance.draggableSelector = ".test-case-list-item";
  }

  // make the list items draggable
  instance.$(instance.draggableSelector).draggable(instance.draggableOptions);

  if(instance.data.editable) {
    // setup the droppable config
    instance.droppableOptions = {
      greedy: true,
      hoverClass: "test-case-list-drop-hover",
      drop: function (event, ui) {
        var groupId = $(this).attr("data-group-id"),
          itemId = ui.draggable.attr("data-pk"),
          itemIsGroup = ui.draggable.hasClass("test-case-list-group");
        console.log("Drop: ", itemId, "on", groupId);
        if (groupId && itemId) {
          if (itemIsGroup) {
            TestGroups.update(itemId, {$set: {parentGroupId: groupId}}, function (error) {
              if (error) {
                Meteor.log.error("Failed to update parent group: " + error.message);
                Dialog.error("Failed to update parent group: " + error.message);
              }
            });
          } else {
            TestCases.update(itemId, {$set: {testGroupId: groupId}}, function (error) {
              if (error) {
                Meteor.log.error("Failed to update test group: " + error.message);
                Dialog.error("Failed to update test group: " + error.message);
              }
            });
          }
        }
      },
      accept: function (el) {
        var dragParentId = $(el).attr("data-parent-id"),
          dragId = $(el).attr("data-group-id"),
          targetId = $(this).attr("data-group-id"),
          isChild = false;
        if (dragId) {
          isChild = $(this).closest("[data-group-id='" + dragId + "']").length > 0;
        }
        return dragParentId !== targetId && !isChild;
      }
    };

    // make the groups droppable
    instance.$(".test-case-list-group").droppable(instance.droppableOptions);
  }
};

/**
 * Template Destroyed
 */
Template.TestCaseList.destroyed = function () {

};
<|endoftext|>


<commit_before>'use strict';

var Promise = require('bluebird');

const updateUsers = (sequelize, action) => {

  const updateUser = (user) => {
    switch (action) {
      case 'splitName': return splitName(user);
      case 'mergeFirstNameLastName': return mergeFirstNameLastName(user);
    }
  };

  const splitName = (user) => {
    if (!user.name) return;
    const tokens = user.name.split(' ');
    const firstName = tokens[0];
    const lastName = tokens.length > 0 ? tokens[1] || '' : '';
    return sequelize.query(`UPDATE "Users" SET "firstName"=:firstName, "lastName"=:lastName WHERE id=:id`, { replacements: { id: user.id, firstName, lastName } });
  };

  const mergeFirstNameLastName = (user) => {
    if (!user.firstName) return;
    const name = `${user.firstName} ${user.lastName}`;
    return sequelize.query(`UPDATE "Users" SET name=:name WHERE id=:id`, { replacements: { id: user.id, name } });
  };

  return sequelize.query(`SELECT * FROM "Users"`, { type: sequelize.QueryTypes.SELECT }).then(users => Promise.map(users, updateUser));
}

module.exports = {
  up: function (queryInterface, Sequelize) {
    return queryInterface.addColumn('Users', 'firstName', { type: Sequelize.STRING(128) })
      .then(() => queryInterface.addColumn('Users', 'lastName', { type: Sequelize.STRING(128) }))
      .then(() => updateUsers(queryInterface.sequelize, 'splitName'))
      .then(() => queryInterface.removeColumn('Users','name'));
  },

  down: function (queryInterface, Sequelize) {
    return queryInterface.addColumn('Users', 'name', { type: Sequelize.STRING(128) })
      .then(() => updateUsers(queryInterface.sequelize, 'mergeFirstNameLastName'))
      .then(() => queryInterface.removeColumn('Users','firstName'))
      .then(() => queryInterface.removeColumn('Users','lastName'));
  }
};<commit_msg>support names with more than one space<commit_after>'use strict';

var Promise = require('bluebird');

const updateUsers = (sequelize, action) => {

  const updateUser = (user) => {
    switch (action) {
      case 'splitName': return splitName(user);
      case 'mergeFirstNameLastName': return mergeFirstNameLastName(user);
    }
  };

  const splitName = (user) => {
    if (!user.name) return;
    const tokens = user.name.split(' ');
    const firstName = tokens.shift();
    const lastName = tokens.join(' ');
    return sequelize.query(`UPDATE "Users" SET "firstName"=:firstName, "lastName"=:lastName WHERE id=:id`, { replacements: { id: user.id, firstName, lastName } });
  };

  const mergeFirstNameLastName = (user) => {
    if (!user.firstName) return;
    const name = `${user.firstName} ${user.lastName}`;
    return sequelize.query(`UPDATE "Users" SET name=:name WHERE id=:id`, { replacements: { id: user.id, name } });
  };

  return sequelize.query(`SELECT * FROM "Users"`, { type: sequelize.QueryTypes.SELECT }).then(users => Promise.map(users, updateUser));
}

module.exports = {
  up: function (queryInterface, Sequelize) {
    return queryInterface.addColumn('Users', 'firstName', { type: Sequelize.STRING(128) })
      .then(() => queryInterface.addColumn('Users', 'lastName', { type: Sequelize.STRING(128) }))
      .then(() => updateUsers(queryInterface.sequelize, 'splitName'))
      .then(() => queryInterface.removeColumn('Users','name'));
  },

  down: function (queryInterface, Sequelize) {
    return queryInterface.addColumn('Users', 'name', { type: Sequelize.STRING(128) })
      .then(() => updateUsers(queryInterface.sequelize, 'mergeFirstNameLastName'))
      .then(() => queryInterface.removeColumn('Users','firstName'))
      .then(() => queryInterface.removeColumn('Users','lastName'));
  }
};<|endoftext|>