Search code examples
jquerycssajaxcallbackpositioning

Jquery custom function not positioning divs on ajax loaded content


I have written a custom function that positions absolute divs inside a container calculating the top positions and heights:

$.fn.gridB = function() {
    var o = $(this); //EDITED from var o = $(this[0]);
    o.each(function() {
        var a1top = o.find('.article1').position().top;
        var a1height = o.find('.article1').height();
        var a0top = o.find('.article0').position().top;
        var a0height = o.find('.article0').height();
        var a2top = o.find('.article2').position().top;
        var a2height = o.find('.article2').height();
        var a3height = o.find('.article3').height();
        var a4height = o.find('.article4').height();
        var a5height = o.find('.article5').height();
        if (a0height > a1height + a1top) {
            $('.article3', o).css('top', a0top + a0height + 20);
        } else if (a0height < a1height + a1top) {
            $('.article3', o).css('top', a1top + a1height + 20);
        }
        $('.article4', o).css('top', a2top + a2height + 20);
        $('.article5', o).css('top', a2top + a2height + 20);
        $('.article6', o).css('top', a2top + a2height + a5height + 40);
        $('.article7', o).css('top', a2top + a2height + a5height + 40);
        var lastChildPos = o.find('div:last-child').position().top;
        var lastChildHeight = o.find('div:last-child').height();
        o.height(lastChildPos + lastChildHeight + 20);
    });
};​

The container has a class ".fours" and the srcipt works perfect on window load. But when it is called after an ajax infinite scroll load it fails to position the absolute divs correctly inside the next ".fours" container:

function loadArticle(pageNumber) {
    $('a#inifiniteLoader').fadeIn('fast');
    $.ajax({
        url: "wp-admin/admin-ajax.php",
        type: 'POST',
        data: "action=infinite_scroll&page_no=" + pageNumber + '&loop_file=loop',
        success: function(html) {
            $('a#inifiniteLoader').fadeOut('1000');
            $("#content").append(html); // This will be the div where our content will be loaded
            $('.fours:last').preloader_index();
            $('.fours').gridB(); // EDITED from $('.fours:last').gridB();
            $('.article a').on({
                mouseenter: function() {
                    if (!$('.preloader', $(this).parent('.article')).length > 0) {
                        $(this).stop().css('opacity', '1');
                    }
                },
                mouseleave: function() {
                    if (!$('.preloader', $(this).parent('.article')).length > 0) {
                        $(this).stop().css('opacity', '0');
                        $('.article-info', $(this).parent('.article')).stop().fadeTo(200, 0);
                    }
                }
            });
        }
    });
    return false;
}​

There is something wrong but i'm pretty close. If i put .fours:last when i call the function gridB() after the success of ajax the script calculates only the top position of the divs ignoring the heights. If i remove :last the script does not calculate both top position and heights.

Any help?

EDIT: Here is an example of the related HTML. Another div with class

 <div id="content">
<div class="fours">
  <div class="article article0">
     <div><img src="url" /></div>
  </div>
  <div class="article article1">
     <div><img src="url" /></div>
  </div>
  <div class="article article2">
     <div><img src="url" /></div>
  </div>
  <div class="article article3">
     <div><img src="url" /></div>
  </div>
  </div>
<!-- Next ".fours" div is loaded here with ajax function -->
</div>

EDIT 2: In the gridB function I changed the line var o = $(this[0]); to var o = $(this); and changed function call from $('.fours:last').gridB(); to $('.fours').gridB();. It worked but now the script positions all absolute div's inside the ajax loaded next sets with the values of the first set of articles. I think it's closer to the solution. There must be a way to target the container loaded by ajax. :last does not work.


Solution

  • Regarding the comment in your last edit you could do the following to reference the last <div class="fours" /> added:

    success: function(html) {
        var $html = $(html);                       // Wrap HTML in jQuery object.
        $('a#inifiniteLoader').fadeOut('1000');
        $("#content").append($html);               // Add created object.
    
        $html.preloader_index();                   // Use the same object.
        $html.gridB();                             // Call gridB using the same object.