Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The behavior you are describing has little to do with lazy evaluation: root of the problem is order of execution.</p> <p>In your code (without the <code>log()</code> on <code>block_pos_at_mousedown</code>) <code>mouseDeltaFromClick</code> seems to change before <code>block_pos_at_mousedown</code> (I must say that I don't know how exactly <code>log()</code> changes the order). Let's hold on that.</p> <p>The <code>observable.combine</code> method expects <code>Property</code> as a first argument - <code>EventStream</code> you have passed will be automatically converted. Now, <code>mouseDeltaAndBlockPos</code> changes (and consequently fires all callbacks) whenever <code>mouseDeltaFromClick</code> <strong>or</strong> <code>block_pos_at_mousedown</code> changes.</p> <p>So, when <code>mouseDeltaFromClick</code> fires before <code>block_pos_at_mousedown</code> the callback at the end of code is called with new delta <strong>but with old block position</strong> (because <code>back_pos_at_mousedown</code> was converted to <code>Property</code>). The old value is <code>[0,0]</code> so the block snaps to the top left corner on each click.</p> <p>How to fix it? The safe way is to assume nothing about order of execution of unrelated callbacks and write it again with this in mind. I came up with this: </p> <pre><code>function xyFromEvent(v){ return [v.clientX, v.clientY]; } function getDelta(t){ var a = t[1]; var b = t[0]; return [a[0]-b[0], a[1]-b[1]]; } function add(p1, p2) { return [p1[0] + p2[0], p1[1] + p2[1]]; } $().ready(function () { var block = $("#clickable-block"); var html = $("html"); var blockDragging = block.asEventStream('mousedown').map(true) .merge(html.asEventStream('mouseup').map(false)) .toProperty(false); var deltas = html.asEventStream('mousemove').map(xyFromEvent).slidingWindow(2,2).map(getDelta); // Just like deltas, but [0,0] when user is not dragging the box. var draggingDeltas = Bacon.combineWith(function(delta, dragging) { if(!dragging) { return [0, 0]; } return delta; }, deltas, blockDragging); var blockPosition = draggingDeltas.scan([0,0], add); blockPosition.onValue(function(pos) { block.css({ top : pos[1] + "px", left : pos[0] + "px" }); }); }); </code></pre> <p>And jsFiddle: <a href="http://jsfiddle.net/aknNh/25/" rel="nofollow">http://jsfiddle.net/aknNh/25/</a></p> <p>EDIT: In comments <strong>raimohanska</strong> had suggested another solution using <code>flatMap</code>: <a href="http://jsfiddle.net/TFPge/1/" rel="nofollow">http://jsfiddle.net/TFPge/1/</a></p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload