Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you listen for a HTML element moving in JavaScript?

I have an HTML element that I need to track another element. Specifically, I need to have the top left and top right corners of both elements be positioned the same. When a window gets resized, the resize event gets triggered and I can adjust the position of the dependent element. However, if the element being tracked is repositioned (but not resized), I do not see any DOM event.

How can we find out if a DOM element has been moved? We are using the latest jQuery.

Here is a code sample.

Note that elementOne and mouseTracking divs are there to show elements that get moved for "some" reason that is outside the control of my code.

  1. This code works for the elementOne case.
  2. MouseTrackingTracker does not track a moving element.
  3. ResizerTracker does not put the border around the complete text in the overflow case.

I would like the trackingDivs to move and resize no matter the reason for the tracked element's reasons for changing.

This code relies on the window resize being the hooked event. Hooking some event that fires when the element changes its dimensions is closer to what I need.

<!DOCTYPE html>
<html>
<head>
  <link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" rel="stylesheet" type="text/css"/>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6/jquery.js"></script>
  <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.js"></script>
  <style type="text/css">
#elementOne { float : right;width : 200px; display:inline-block}
#resizer { float : left; display:inline-block}
.trackedDiv { width:50px; height:50px; background-color: blue }
.trackingDiv { position:absolute; z-index: 1; border:3px green; border-style: solid;}
</style>
<script>
  $(function() {
      $( window ).bind("resize",function(){
          $("#elementOne").trigger("reposition");
          $("#mouseTracking").trigger("reposition");
          $("#resizer").trigger("reposition");
       });

       var repositionFunction = function(selfish, element){
           var self = $(selfish);
           var offset = self.offset();
           var selfTop = offset.top;
           var selfLeft = offset.left;

           var selfWidth = self.width();
           var selfHeight = self.height();
           $(element).css({
              top: selfTop,
              left: selfLeft,
              width : selfWidth,
              height : selfHeight
           });
       }
       $(document).mousemove(function(ev){
           $("#mouseTracking").position({
             my: "left bottom",
             of: ev,
             offset: "3 -3",
             collision: "fit"
           });
         });

       var timedShort = function() {
           $('#resizer').html("Really short").resize();
           setTimeout(timedLong, 10000);
       }
       var timedLong = function() {
           $('#resizer').html("Really longggggggggggggggggggggggggggggggggggggggggggggggggggg text").resize();
           setTimeout(timedShort, 10000);
       }
       setTimeout(timedLong, 10000);

       $("#elementOne").bind("reposition",
               function() { repositionFunction(this, "#elementOneTracker"); });
       $("#mouseTracking").bind("reposition",
               function() { repositionFunction(this, "#mouseTrackingTracker"); });
       $("#resizer").bind("reposition",
               function() { repositionFunction(this, "#resizerTracker"); });
  });
  </script>
</head>
<body>
  <div class="trackedDiv" id="mouseTracking">tracks mouse</div>
  <div class="trackingDiv" id="mouseTrackingTracker"></div>
  <div style="clear:both;"></div>
  <div class="trackedDiv" id="resizer">resizer: resizes</div>
  <div class="trackingDiv" id="resizerTracker"></div>
  <div class="trackedDiv" id="elementOne">elementOne: floats to the right</div>
  <div class="trackingDiv" id="elementOneTracker"></div>
</body>
</html>
like image 799
Pat Avatar asked Aug 16 '11 07:08

Pat


3 Answers

You can fire custom events with jquery whenever you reposition the element.

$( window ).bind("resize",function(){

   $("#elementOne").css({
      top: 200,
      left: 200
   }).trigger("reposition");

});

// and now you can listen to a "reposition event"

$("#elementOne").bind("reposition",function(){

   var self = $(this);
   $("#elementTwo").css({
      top: self.css("top"),
      left: self.css("left")
   });

});

So you can provide event hooks yourself with some manual coding, which is useful since cool events like DOMAttrModified and so on, are not fully supported in all browsers. The downside, you have to do it all yourself.

like image 107
BGerrissen Avatar answered Oct 17 '22 21:10

BGerrissen


Unfortunately, there are no reliable events to tell you when an element moves or is resized. You could resort to polling the element, though that won't necessarily be the most performant solution:

setInterval(repositionElement, 10);

Another option is to make your element "track" the other element purely through CSS. For this to work, you'll need a "wrapper" around the element you're tracking, and the other element:

#wrapper-around-element-to-track
{
    position: relative;
} 

#tracked-element
{
    position: absolute;
    /* set top and left to position, if necessary */
}

#tracking-element
{
    position: absolute;
    /* set top and left to position, if necessary */
}

Since you're already using jQuery, you can also use the resize event plugin to simulate the resize event on any element, but if I recall the last time I looked at it, it simply does the polling like I mentioned.

like image 32
Jacob Avatar answered Oct 17 '22 20:10

Jacob


There is the DOMAttrModified event, but its only impleneted in Firefox and Chrome. But as you need a JavaScript function to start the element moving, you can firing a custom event with Jquery in this place.

like image 21
Andreas Köberle Avatar answered Oct 17 '22 21:10

Andreas Köberle