React-dnd: "рдХреИрдирдбреНрд░реЙрдк", рдХреИрд╕реЗ рдкрддрд╛ рдЪрд▓реЗрдЧрд╛ рдХрд┐ рд╣рдо рдХрд┐рд╕ рддрддреНрд╡ рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рд╣реИрдВ?

рдХреЛ рдирд┐рд░реНрдорд┐рдд 14 рдЕрдкреНрд░реИрд▓ 2016  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: react-dnd/react-dnd

drop(props, monitor, component) рдкрджреНрдзрддрд┐ рдореЗрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рддреАрди рддрд░реНрдХ рд╣реИрдВред рд▓реЗрдХрд┐рди canDrop(props, monitor) рдореЗрдВ component рддрд░реНрдХ рдирд╣реАрдВ рд╣реИред

рдореИрдВ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдЬрдм рдХреЛрдИ рдЖрдЗрдЯрдо рдХрд┐рд╕реА рдЕрдиреНрдп рдШрдЯрдХ рдкрд░ рдЦреАрдВрдЪрд╛ рдЬрд╛рддрд╛ рд╣реИ рддреЛ рдореИрдВ рдЙрд╕ рдШрдЯрдХ рдХреЛ 50% (рдКрдВрдЪрд╛рдИ) рдХреЗ рджреЛ рднрд╛рдЧреЛрдВ рдореЗрдВ "рд╡рд┐рднрд╛рдЬрд┐рдд" рдХрд░рддрд╛ рд╣реВрдВред рдпрджрд┐ рд╡рд╕реНрддреБ рдХреЛ рдКрдкрд░ рд╡рд╛рд▓реЗ рднрд╛рдЧ рдореЗрдВ рдЧрд┐рд░рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рддреЛ рдЙрд╕реЗ рдЙрд╕рдХреЗ рдКрдкрд░ рд░рдЦ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдпрджрд┐ рд╡рд╣ рдиреАрдЪреЗ рдХреЗ рднрд╛рдЧ рдореЗрдВ рдЧрд┐рд░рд╛ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рддреЛ рдЙрд╕реЗ рдмрд╛рдж рдореЗрдВ рд░рдЦ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдореЗрд░реЗ рдкрд╛рд╕ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХреЛрдб рд╣реИ рдЬреЛ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рддрд╛ рд╣реИ рдХрд┐ рдШрдЯрдХ рдКрдкрд░/рдиреАрдЪреЗ рднрд╛рдЧ рдореЗрдВ рдЧрд┐рд░рд╛ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВред рдореИрдВ рдЕрдм рдЬреЛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рд╡рд╣ рдЗрд╕ рдЖрдзрд╛рд░ рдкрд░ рдПрдХ рд╡рд░реНрдЧ рдЬреЛрдбрд╝рдирд╛ рд╣реИ рдХрд┐ рдорд╛рдЙрд╕ рдКрдкрд░/рдиреАрдЪреЗ рднрд╛рдЧ рдореЗрдВ рд╣реИ (рд▓реЗрдХрд┐рди рд╣реЛрд╡рд░ рдПрдХреНрд╢рди рдХреЗ рджреМрд░рд╛рди, рдбреНрд░реЙрдк рдПрдХреНрд╢рди рдирд╣реАрдВ)ред

рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рдХрд┐ рдореИрдВ hover(props, monitor, component) рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ, рдХреНрдпреЛрдВрдХрд┐ рдореБрдЭреЗ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХрд┐ рдореБрдЭреЗ рдЕрдкрдиреЗ рдШрдЯрдХ рдореЗрдВ рдПрдХ рд╕рдВрдкрддреНрддрд┐ рдХреИрд╕реЗ рдЬреЛрдбрд╝рдиреА рд╣реИ (рдЬреЛ рдбреАрдУрдПрдо рдпрд╛ рд╕рдорд╛рди рд░реВрдк рд╕реЗ рдПрдХ рд╕реАрдПрд╕рдПрд╕ рд╡рд░реНрдЧ рдЬреЛрдбрд╝ рджреЗрдЧрд╛) рдпрд╣, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╕реНрд╡рдпрдВ рдШрдЯрдХ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдирд╣реАрдВ рд╣реИ рдФрд░ рдЗрд╕рдХреЗ рд╕рдВрджрд░реНрдн рдЖрджрд┐ рддрдХ рдЗрд╕рдХреА рдкрд╣реБрдВрдЪ рдирд╣реАрдВ рд╣реИред

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореБрдЭреЗ рдХреБрдЫ рдпрд╛рдж рдЖ рд░рд╣рд╛ рд╣реИред :)

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдареАрдХ рд╣реИ, рддреЛ рд╡рд┐рдЪрд╛рд░ рдпрд╣ рд╣реИ рдХрд┐ рдЖрдк рдЕрдкрдиреЗ рдШрдЯрдХ рдореЗрдВ рд░рд╛рдЬреНрдп рд╕реЗрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рдЬрдм рд░рд╛рдЬреНрдп рд╕реЗрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЖрдк рдХрдХреНрд╖рд╛ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред

рдорд╛рди рд▓реЗрдВ рдХрд┐ рдЖрдк рдлреВ рдХреЛ рдмрд╛рд░ рдореЗрдВ рдЦреАрдВрдЪ рд░рд╣реЗ рд╣реИрдВ:

import React, { Component } from "react";
import classNames from "classnames";

class Bar extends Component {
  constructor(props) {
    super(props);

    this.state = {
      // Where a foo is hovering over the component.  One of null, "above", or "below"
      fooHover: null,
    };
  }

  render() {
    const { fooHover } = this.state;

    const classes = classNames("bar", {
      "bar-above": fooHover === "above",
      "bar-below": fooHover === "below",
    });
  }
}

рдПрдХрдорд╛рддреНрд░ рд╕рд╡рд╛рд▓ рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо рдЙрд╕ рд░рд╛рдЬреНрдп рдХреЛ рдХреИрд╕реЗ рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ!

import { findDOMNode } from "react-dom";

const barTarget = {
  ...
  hover(props, monitor, component) {
    if (!monitor.canDrop()) {
      return;
    }

    const rawComponent = undecorate(component); // undecorate described below

    const { y } = monitor.getClientOffset();
    const { top, height } = findDOMNode(component).getBoundingClientRect();

    if (y < top + height/2) {
      rawComponent.setFooHover("above"); // setFooHover described below
    } else {
      rawComponent.setFooHover("below");
    }
  },
  ...
}

рддреЛ рдореВрд▓ рд░реВрдк рд╕реЗ, рдЖрдк рдЕрдкрдиреЗ рдШрдЯрдХ, setFooHover рдПрдХ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдЬреЛ setState рдХреЙрд▓ рдХрд░реЗрдЧрд╛ред рдпрд╣ рдкреНрд░рджрд░реНрд╢рди рдХрд╛рд░рдгреЛрдВ рд╕реЗ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП:

  // In Bar
  setFooHover(fooHover) {
    if (fooHover !== this.state.fooHover) {
      this.setState({ fooHover });
    }
  }

рдореИрдВ рдКрдкрд░ undecorate рдХреНрдпреЛрдВ рдХреЙрд▓ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдЗрд╕рдХрд╛ рдХрд╛рд░рдг рдпрд╣ рд╣реИ рдХрд┐ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛-рдбреАрдПрдирдбреА рдЙрдЪреНрдЪ рдХреНрд░рдо рдШрдЯрдХреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рд╣рдо рдЕрд▓рд┐рдЦрд┐рдд рдШрдЯрдХреЛрдВ рдХреЛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдпрд╣ рдореЗрд░реА рд░рд╛рдп рдореЗрдВ рдЙрдЪреНрдЪ рдХреНрд░рдо рдХреЗ рдШрдЯрдХреЛрдВ рдХреА рдПрдХ рдмрджрд╕реВрд░рдд рдЬрдЯрд┐рд▓рддрд╛ рд╣реИред рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдЕрдкрдиреЗ рдлреНрд▓рдХреНрд╕ рд╕реНрдЯреЛрд░ рдпрд╛ рдХрд┐рд╕реА рдЪреАрдЬрд╝ рдкрд░ рдХрд╛рд░реНрд░рд╡рд╛рдИ рднреЗрдЬрдХрд░ рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХреЗрдВ, рд▓реЗрдХрд┐рди рдпрджрд┐ рдЖрдк рдЗрд╕реЗ рдореЗрд░реА рддрд░рд╣ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓реЗрддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдореЗрд░рд╛ undecorate :

function undecorate(component) {
  let curr = component;
  while (typeof curr.getDecoratedComponentInstance === "function") {
    curr = curr.getDecoratedComponentInstance();
  }

  return curr;
}

рдЕрдм рдпрджрд┐ рдЖрдк рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдПрдХ рдЫреЛрдЯреА рд╕реА рд╕рдорд╕реНрдпрд╛ рдХреЛ рдЫреЛрдбрд╝рдХрд░ рд╕рдм рдХреБрдЫ рдЕрдЪреНрдЫрд╛ рджрд┐рдЦрдиреЗ рд▓рдЧреЗрдЧрд╛ред рдХрдХреНрд╖рд╛ рдХрднреА рдирд╣реАрдВ рдЬрд╛рддреА! рдХреЛрдИ рднреА рдХрднреА рднреА setHoverState(null) рдХреЙрд▓ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ (рдЖрдкрдХреЗ рдмрд╛рд░ рд▓рдХреНрд╖реНрдп рдореЗрдВ рдПрдВрдбрд╣реЛрд╡рд░ рдлрд╝рдВрдХреНрд╢рди рдЬреИрд╕реА рдХреЛрдИ рдЪреАрдЬрд╝ рдирд╣реАрдВ рд╣реИ)ред рдЗрд╕реЗ рд╕рдВрднрд╛рд▓рдиреЗ рдХрд╛ рдЙрдЪрд┐рдд рддрд░реАрдХрд╛ рдЗрд╕ рддрд░рд╣ componentWillReceiveProps рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ:

  componentWillReceiveProps(nextProps) {
    if (this.props.isFooOver && !nextProps.isFooOver) {
      this.setState({ fooHover: null });
    }
  }

(рдЕрдкрдиреЗ рд╕рдВрдЧреНрд░рд╣ рд╕рдорд╛рд░реЛрд╣ рдореЗрдВ { isFooOver: monitor.isOver() } рдЬреЛрдбрд╝рдирд╛ рди рднреВрд▓реЗрдВ)

рдореБрдЭреЗ рдмрддрд╛рдПрдВ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдЬрд╛рддрд╛ рд╣реИ!

рд╕рднреА 4 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдЕрд░реЗ, рддреБрдо рднрд╛рдЧреНрдп рдореЗрдВ рд╣реЛ! рдореИрдВрдиреЗ рд▓рдЧрднрдЧ рдЗрд╕реЗ рдкрд╣рд▓реЗ рд╣реА рд▓рд╛рдЧреВ рдХрд░ рджрд┐рдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ рдХреБрдЫ рдХреЛрдб рдПрдХ рд╕рд╛рде рдлреЗрдВрдХрдиреЗ рджреЗрдВред

рдареАрдХ рд╣реИ, рддреЛ рд╡рд┐рдЪрд╛рд░ рдпрд╣ рд╣реИ рдХрд┐ рдЖрдк рдЕрдкрдиреЗ рдШрдЯрдХ рдореЗрдВ рд░рд╛рдЬреНрдп рд╕реЗрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рдЬрдм рд░рд╛рдЬреНрдп рд╕реЗрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЖрдк рдХрдХреНрд╖рд╛ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред

рдорд╛рди рд▓реЗрдВ рдХрд┐ рдЖрдк рдлреВ рдХреЛ рдмрд╛рд░ рдореЗрдВ рдЦреАрдВрдЪ рд░рд╣реЗ рд╣реИрдВ:

import React, { Component } from "react";
import classNames from "classnames";

class Bar extends Component {
  constructor(props) {
    super(props);

    this.state = {
      // Where a foo is hovering over the component.  One of null, "above", or "below"
      fooHover: null,
    };
  }

  render() {
    const { fooHover } = this.state;

    const classes = classNames("bar", {
      "bar-above": fooHover === "above",
      "bar-below": fooHover === "below",
    });
  }
}

рдПрдХрдорд╛рддреНрд░ рд╕рд╡рд╛рд▓ рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо рдЙрд╕ рд░рд╛рдЬреНрдп рдХреЛ рдХреИрд╕реЗ рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ!

import { findDOMNode } from "react-dom";

const barTarget = {
  ...
  hover(props, monitor, component) {
    if (!monitor.canDrop()) {
      return;
    }

    const rawComponent = undecorate(component); // undecorate described below

    const { y } = monitor.getClientOffset();
    const { top, height } = findDOMNode(component).getBoundingClientRect();

    if (y < top + height/2) {
      rawComponent.setFooHover("above"); // setFooHover described below
    } else {
      rawComponent.setFooHover("below");
    }
  },
  ...
}

рддреЛ рдореВрд▓ рд░реВрдк рд╕реЗ, рдЖрдк рдЕрдкрдиреЗ рдШрдЯрдХ, setFooHover рдПрдХ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдЬреЛ setState рдХреЙрд▓ рдХрд░реЗрдЧрд╛ред рдпрд╣ рдкреНрд░рджрд░реНрд╢рди рдХрд╛рд░рдгреЛрдВ рд╕реЗ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП:

  // In Bar
  setFooHover(fooHover) {
    if (fooHover !== this.state.fooHover) {
      this.setState({ fooHover });
    }
  }

рдореИрдВ рдКрдкрд░ undecorate рдХреНрдпреЛрдВ рдХреЙрд▓ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдЗрд╕рдХрд╛ рдХрд╛рд░рдг рдпрд╣ рд╣реИ рдХрд┐ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛-рдбреАрдПрдирдбреА рдЙрдЪреНрдЪ рдХреНрд░рдо рдШрдЯрдХреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рд╣рдо рдЕрд▓рд┐рдЦрд┐рдд рдШрдЯрдХреЛрдВ рдХреЛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдпрд╣ рдореЗрд░реА рд░рд╛рдп рдореЗрдВ рдЙрдЪреНрдЪ рдХреНрд░рдо рдХреЗ рдШрдЯрдХреЛрдВ рдХреА рдПрдХ рдмрджрд╕реВрд░рдд рдЬрдЯрд┐рд▓рддрд╛ рд╣реИред рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдЕрдкрдиреЗ рдлреНрд▓рдХреНрд╕ рд╕реНрдЯреЛрд░ рдпрд╛ рдХрд┐рд╕реА рдЪреАрдЬрд╝ рдкрд░ рдХрд╛рд░реНрд░рд╡рд╛рдИ рднреЗрдЬрдХрд░ рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХреЗрдВ, рд▓реЗрдХрд┐рди рдпрджрд┐ рдЖрдк рдЗрд╕реЗ рдореЗрд░реА рддрд░рд╣ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓реЗрддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдореЗрд░рд╛ undecorate :

function undecorate(component) {
  let curr = component;
  while (typeof curr.getDecoratedComponentInstance === "function") {
    curr = curr.getDecoratedComponentInstance();
  }

  return curr;
}

рдЕрдм рдпрджрд┐ рдЖрдк рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдПрдХ рдЫреЛрдЯреА рд╕реА рд╕рдорд╕реНрдпрд╛ рдХреЛ рдЫреЛрдбрд╝рдХрд░ рд╕рдм рдХреБрдЫ рдЕрдЪреНрдЫрд╛ рджрд┐рдЦрдиреЗ рд▓рдЧреЗрдЧрд╛ред рдХрдХреНрд╖рд╛ рдХрднреА рдирд╣реАрдВ рдЬрд╛рддреА! рдХреЛрдИ рднреА рдХрднреА рднреА setHoverState(null) рдХреЙрд▓ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ (рдЖрдкрдХреЗ рдмрд╛рд░ рд▓рдХреНрд╖реНрдп рдореЗрдВ рдПрдВрдбрд╣реЛрд╡рд░ рдлрд╝рдВрдХреНрд╢рди рдЬреИрд╕реА рдХреЛрдИ рдЪреАрдЬрд╝ рдирд╣реАрдВ рд╣реИ)ред рдЗрд╕реЗ рд╕рдВрднрд╛рд▓рдиреЗ рдХрд╛ рдЙрдЪрд┐рдд рддрд░реАрдХрд╛ рдЗрд╕ рддрд░рд╣ componentWillReceiveProps рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ:

  componentWillReceiveProps(nextProps) {
    if (this.props.isFooOver && !nextProps.isFooOver) {
      this.setState({ fooHover: null });
    }
  }

(рдЕрдкрдиреЗ рд╕рдВрдЧреНрд░рд╣ рд╕рдорд╛рд░реЛрд╣ рдореЗрдВ { isFooOver: monitor.isOver() } рдЬреЛрдбрд╝рдирд╛ рди рднреВрд▓реЗрдВ)

рдореБрдЭреЗ рдмрддрд╛рдПрдВ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдЬрд╛рддрд╛ рд╣реИ!

рд╡рд┐рд╕реНрддреГрдд рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдмрд╣реБрдд рдзрдиреНрдпрд╡рд╛рдж! рдореИрдВ рдЖрдкрдХреЛ рдмрддрд╛ рджреВрдБрдЧрд╛ :)

рдЕрдВрдд рдореЗрдВ, рдореИрдВрдиреЗ Redux рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛, рдЗрд╕рд▓рд┐рдП рдЬрдм рдбреНрд░реЙрдк рдЗрд╡реЗрдВрдЯ рдХреЛ рдирд┐рдХрд╛рд▓ рджрд┐рдпрд╛ рдЧрдпрд╛ рддреЛ рдореИрдВрдиреЗ рдореВрд▓ рд░реВрдк рд╕реЗ рдПрдХ рд░реЗрдбреНрдпреВрд╕рд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдПрдХ рдИрд╡реЗрдВрдЯ рднреЗрдЬрд╛ред

    drop: (propsTargetItem, monitor, targetItem) ->
        draggedItem = monitor.getItem()# Item that has been dragged and eventually dropped.
        coordsDrop = monitor.getClientOffset()# Coords of the drop action.
        diff = monitor.getDifferenceFromInitialOffset()# Comparison of the initial click (dragging start) against the end of the click (dropping start).

        patternId = draggedItem.patternId
        patternPosition = draggedItem.position
        targetId = propsTargetItem.context.patternId
        targetPosition = propsTargetItem.context.position
        isCursorAboveHalf = GeoService.isAboveHalf(ReactDOM.findDOMNode(targetItem), coordsDrop.y)

        # Extract positions in the array of children.
        oldPosition = draggedItem.position# Current position of the item, which will be the old position as soon as the item is moved. (by the server through sockets)
        newPosition = calcDropPosition(targetId, patternId, patternPosition, targetPosition, isCursorAboveHalf)# Position where we will move the dragged item.

        # Dispatch only if the position has changed and is set.
        if oldPosition isnt newPosition and newPosition?
            draggedItem.moveDnDPattern(Object.assign({}, draggedItem, {newPosition: newPosition, oldPosition: oldPosition}))

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

gaearon picture gaearon  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

BrennanRoberts picture BrennanRoberts  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

djeremh picture djeremh  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

antoineBernard picture antoineBernard  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

user1736 picture user1736  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ