0

I'm setting up a page with the following functionality:

  1. User is shown 5 images.
  2. Some visual effects are binded to the images.
  3. If user scrolls to the bottom of page another 5 images are loaded.
  4. Html of a container <div> is updated using .html() function.
  5. Visual effects are binded to the new 5 images.

The visual effect is to highlight some predefined areas of the image, using Image Mapster.

Problem:

The visual effects on all previous images disappear after I add the new five images.

Questions:

Does calling the .html() function remove bindings previously set on the existing html?

How can I update the html without removing previously set bindings?

Here is a simplified version of the code:

CODE checking if bottom of page is reached on scroll down:

$(window).scroll(function() {
    if($(window).scrollTop() + $(window).height() == $(document).height()) {
        console.debug("_____________ DEBUG _____________: reached bottom()");
        // check if there are images to load, if so call Visualize()
        if ( there are more images to load in a buffer)
            ShowMore();
        }
    }
});

CODE showing 5 more images:

function ShowMore() {
  console.debug("_____________ DEBUG _____________: in /ShowMore()");
  
  // get the html of the image container div
  old_html = $('#image_result_container').html();

  // ajax request to get the 5 more images from server
  $.ajax({
    url: "/GetImages/",
    type: "POST",
    contentType: "application/json",
    data: JSON.stringify({'visualize_ids': visualize_ids}),
    dataType: "json",
    success: function( response ) {

      // some complex manipulation that creates the html for the 5 images just loaded
      new_html = old_html + <div>...some stuff in here...</div>

      // I set the html of the container to the new html
      $('#image_result_container').html(new_html);

      // this part calls the ImageMapster function only on the last 5 images using an id value that I won't explain for conciseness reasons...
      for (i = 0; i < 5; i++) {
        ImageMapster( some_id, i );
      }
  });
}

What the ImageMapster() function does is basically bind a visualization function to the image element:

var map = $('#vis_image_' + ann_id + '_' + im_count_id);
map.mapster({ all the cool effects go here... });

I attached below the code for the visual effect (for completeness) but that doesn't really matter for the question.

CODE for the visual effect:

function ImageMapster( ann_id, im_count_id ) {
  console.debug("_____________ DEBUG _____________: in /ImageMapster()");
  console.debug(" $> ann: [" + ann_id + "] im_count: [" + im_count_id + "]");
  var map = $('#vis_image_' + ann_id + '_' + im_count_id);
  map.mapster({
    areas: [
    {
      key: 'subject',
      staticState: true,
      fillColor: '6699ff',
      fillOpacity: 0.4,
      stroke: true,
      strokeColor: '6699ff',
      strokeWidth: 3
    },
    {
      key: 'object',
      staticState: true,
      fillColor: '8ae65c',
      fillOpacity: 0.4,
      stroke: true,
      strokeColor: '8ae65c',
      strokeWidth: 3
    }
    ],
    mapKey: 'name'
  });
}
Community
  • 1
  • 1
Matteo
  • 7,924
  • 24
  • 84
  • 129
  • 2
    Yes, when you update the contents with new HTML, that portion of the DOM is completely rebuilt, and nothing remains in effect from what you did to any of those removed DOM elements. – Pointy Oct 20 '15 at 18:42
  • @Pointy - Thanks for the info! And do you have a solution to that? – Matteo Oct 20 '15 at 18:44
  • 1
    You can have a single outer container and then append new `
    ` sub-containers with each batch of images. Appending new content does not affect previous content.
    – Pointy Oct 20 '15 at 18:45

3 Answers3

2

The way jQuery selectors work is they bind to the matches when the code runs. When the HTML that the selectors match are removed, so is the bind as they match the exact code. Not the pattern.

The shortest way to handle this is to use jQuery(selector).append() to add your new code at the end of the element opposed to replacing everything via .html(). That way your previous binders will carry over.

http://api.jquery.com/append/

Practically
  • 506
  • 4
  • 10
0

$().html() destroys elements, then creates new elements. The binding was on the old (now destroyed) elements. You need to rebind if you use $().html(). You can get around rebinding by NOT using $().html() and instead using $().detach() and $().attach() against your existing elements.

Patrick Gunderson
  • 3,263
  • 17
  • 28
0

You can use Jquery element.clone(true,true); with obviously some changes to your existing code and that should work very easily.