13

EDIT: See update!

I have the following html:

<body>
  <span id="milestone1">
  </span>   
  <img id="image1" src="blabla.jpeg" style="width:400px;height:200px;" />
  <div id="divOverlayOverImage1" style="position:absolute; top:100px; left:40px; width:400px;height:200px;" onclick="DoFunkyStuff();"><div>
</body>

At first the divOverlayOverImage1 is positioned over Image1, covering it, but if I run the code below, the #divOverlayOverImage1 element will no longer covering the #image1 element.

$("#milestone1").after('<div style="width:500px; height:500px; background-color:blue;">');

I want to have an event that notifies me when #image1 changes its position, so I can update the position of #divOverlayOverImage1.

NOTE: I do not have full control over the dom. the $("#milestone1").after('<div style="width:500px; height:500px; background-color:blue;">'); command is run by a third party.

UPDATE: I do not have full control of the DOM, so I cannt put a callback to the element add function, as it is not me making this call. Also, I cannot modify HTML like crazy. I just come to a set of websites, append and overlay to a specific image throung JavaScript and that's it. There are other competitiors that change the HTML as well.

Dragos Durlut
  • 166
  • 1
  • 1
  • 7
  • Possible Dupe: http://stackoverflow.com/questions/355015/jquery-event-to-detect-when-element-position-changes – Abhitalks Aug 05 '13 at 09:35
  • My suggestion is that you put both image1 and divOverlayOverImage1 in a container like a div, and set that divOverlayOverImage1's position to relative.Then they will worked out automatically and you need nothing to do. – Clxy Aug 05 '13 at 09:42
  • what is that third-party and how/when does it call? – Zim84 Aug 05 '13 at 09:49
  • @Zim84: It isn't something speific. Let's just say that it's some ads that keep poping up and moving the content up and down. – Dragos Durlut Aug 05 '13 at 09:50

4 Answers4

7

If you have full control over the DOM, and I assume you have, you can add a call to every change you make in the DOM that will affect that <span>.

function yourFunction() {
    $("#milestone1").after('<div style="width:500px; height:500px; background-color:blue;">');
    updateMyOverlayPosition();
}

if that doesnt work, you might try this one here: Detect changes in the DOM

edit

if you want events:

$('#image').on('adjustOverlay',function(e) {
    // adjust the position of the overlay
}

$("#milestone1").after('<div style="width:500px; height:500px; background-color:blue;">');
$('#image').trigger('adjustOverlay', {extra: "info", some: "parameters"});

edit2

Since you don't have full control over changes in the DOM and you can get surprised you can either go with the link I already provided above or check in an interval if the overlay is still where it needs to be. This doesn't solve the problem in the way you want it, but there is no native event on DOM-changes, so you have to stick with some sort of work-around.

var checkTime = 100; //100 ms interval
var check = setInterval(function() {
    // adjust overlay position
}, checkTime);

edit3

next possible solution: if you know how affecting code is inserted in the DOM, you can try to change that method so that it always runs your adjustOverlayPosition() or fires an event, if you like events. Example: if it is inserted with jQuery's .after() you can modify that function:

jQuery.fn.extend({
    // since the .after() function already exists, this will
    // actually overwrite the original function. Therefore you need
    // the exact code that was originally used to recreate it.
    after: function() {
        return this.domManip( arguments, function( elem ) {
        if ( this.parentNode ) {
            this.parentNode.insertBefore( elem, this.nextSibling );
        }
        // call the function directly
        adjustOverlayPosition();
        // or call an event
        $('#image').trigger('adjustOverlay', {extra: "info", some: "parameters"});
    }
});

Drawback: this solution can be risky and works only if you know the code that is used originally. So it would also depend on the jQuery version.

Community
  • 1
  • 1
Zim84
  • 3,404
  • 2
  • 35
  • 40
2

One workaround is to reorganize your layout. Wrap your image and overlay into a div. That way they will always remain that way.

<div id="wrap">
    <img id="i1" src="..." />
    <div id="overlay" />
</div>

#wrap {
    position: relative;
    width: 400px;
    height: 200px;
}

#overlay {
    position: absolute;
    top: 100px; 
    left: 40px; 
    width: 400px;
    height: 200px;
}
Abhitalks
  • 27,721
  • 5
  • 58
  • 81
  • 3
    truly a solution to that specific problem, but not to the general problem of "event when dom changes". – Zim84 Aug 05 '13 at 09:44
  • Yes, of course. That is why I have +1'ed your answer, as you have answered specifically what the op is after. I just wanted to give him ideas for workaround to save a few complexities! – Abhitalks Aug 05 '13 at 09:50
1

If wrapping the img with a ovelay is only your requirement, I think you can go with a pure css Solution:

Try the demo

HTML

<p id="milestone1">
First Overlay
</p>   
<div class="img-overlay-container" style="width:400px;height:200px;">
 <img id="image1" src="blabla.jpeg"/>
 <div id="overlay1" onclick="alert('clicked');">
 </div>
</div>  
<p id="milestone2">
Second Overlay
</p>       
<div class="img-overlay-container" style="width:100px;height:400px;">
 <img id="image2" src="blabla.jpeg"/>
 <div id="overlay2" onclick="alert('clicked');">
 </div>
</div>  

CSS

.img-overlay-container{
  position: relative;
  display:inline-block;
}
.img-overlay-container > img{

}

.img-overlay-container > div{
  position:absolute; 
  top:0px; 
  left:0px; 
  width:100%;
  height:100%; 
  background: rgba(3,3,3,.1);
}
Akhil Sekharan
  • 12,467
  • 7
  • 40
  • 57
-1
function changePosition(callback) {
  $("#milestone1").after('<div style="width:500px; height:500px; background-color:blue;">');
 callback();
}

Then you can call changePosition(function() {// Add your event handler function}).

Hope this will help you!

Deepak Biswal
  • 4,280
  • 2
  • 20
  • 37