6

I'm doing an application with Phonegap and I'm using a self-built slide transition to change the pages. It works like this:

Every page is a div with 100% height and width, so if I change the Page, I set the next div right to the currently active and slide both to the left side.

Now to the Problem: the sliding works fine, but it's executed before the content of the right div is completely loaded. So the right div slides in empty, and only after a few hundred miliseconds the content will appear.

I tried it with document.ready, but as I've read this event is only executed the first time the DOM is loaded.

Does anybody know how I can wait for the DOM to be completely rendered again after I've manipulated the DOM with Javascript?

Anupam
  • 7,966
  • 3
  • 41
  • 63
Michael Kunst
  • 2,978
  • 25
  • 40
  • you need to loop through the images on the new page and make sure they all have a real .height property (meaning they are done loading) before you kick-off the animation. – dandavis Oct 29 '13 at 21:47

8 Answers8

3

In your case, you can pick one element in the content of the next div and keep checking it with $(...).length. If the value is > 0, the DOM is loaded and you can change the page.

You may want to try this function:

Function.prototype.deferUntil = function(condition, timeLimit) {
    var ret = condition();

    if (ret) {
        this(ret);
        return null;
    }

    var self = this, interval = null, time = ( + new Date());
    interval = setInterval(function() {
        ret = condition();
        if (!ret) {
            if (timeLimit && (new Date() - time) >= timeLimit) {
                // Nothing
            } else {
                return;
            }
        }
        interval && clearInterval(interval);
        self(ret);
    }, 20);

    return interval;
};

Usage:

(function() {
    console.log('Next page loaded');
}).deferUntil(function() {
    return $('#nextDiv').length > 0;
}, 3000);

The above example will check the div that has id="nextDiv" in every 20ms (not longer than 3 seconds). When the div is loaded, it will show 'Next page loaded' in the console.

You can try on this fiddle

anvoz
  • 722
  • 1
  • 9
  • 20
1

There is a DOMNodeInserted event that is supposed to work like document.ready but for individual DOM nodes. But it is deprecated and has lots of issues. StackOverflow users found a good alternative to it that works quite well in all mobile browsers: Alternative to DOMNodeInserted

Community
  • 1
  • 1
srgstm
  • 3,649
  • 2
  • 24
  • 26
1

Here is a function that will trigger a callback once all images matching a jquery selector have finished loading

Js Fiddle Sample

//css
input {width: 420px;}

//html
<div id="container"></div>
    <input type="text" value="http://goo.gl/31Vs" id="img1">
    <br><input type="text" value="http://wall.alafoto.com/wp-content/uploads/2010/11/Fractal-Art-Wallpapers-09.jpg" id="img2">
    <br><input type="text" value="http://pepinemom.p.e.pic.centerblog.net/ssg8hv4s.jpg" id="img3">
    <br><input type="button" value="Load images" name="loadImages" id="btn">

        <div id="message"></div>

//javascript

//Call a function after matching images have finished loading
function imagesLoadedEvent(selector, callback) {
    var This = this;
    this.images = $(selector);
    this.nrImagesToLoad = this.images.length;
    this.nrImagesLoaded = 0;

    //check if images have already been cached and loaded
    $.each(this.images, function (key, img) {
        if (img.complete) {
            This.nrImagesLoaded++;
        }
        if (This.nrImagesToLoad == This.nrImagesLoaded) {
            callback(This.images);
        }
    });

    this.images.load(function (evt) {
        This.nrImagesLoaded++;
        if (This.nrImagesToLoad == This.nrImagesLoaded) {
            callback(This.images);
        }
    });
}

$("#btn").click(function () {
    var c = $("#container"), evt;
    c.empty();
    c.append("<img src='" + $("#img1").val() + "' width=94>");
    c.append("<img src='" + $("#img2").val() + "' width=94>");
    c.append("<img src='" + $("#img3").val() + "' width=94>");
    evt = new imagesLoadedEvent("img", allImagesLoaded);
});

function allImagesLoaded(imgs) {
    //this is called when all images are loaded
    $("#message").text("All images loaded");
    setTimeout(function() {$("#message").text("");}, 2000);
}
Rainer Plumer
  • 3,693
  • 2
  • 24
  • 42
0

You could use jQuery ajax to load the content, and on success run a function with the slide.

$("#page1").load('page2.html', function() {
    //do your custom animation here
});

Althoug I'm not completely sure how you're loading the content. Is it static (Already there but just not visible?) Or is it loaded with ajax?

EDIT: You could just do a small .delay() or setTimeout with a few millisec, and then animate the sliding.

Robin Jonsson
  • 2,761
  • 3
  • 22
  • 42
  • 1
    Thanks for your answer. The content is in the mobile database, so I'm taking it out from there, Insert it into the div and then slide it in. The thing with the set Timeout is, that big pages need about 600ms, while small pages need about 50ms. I dont want to wait 600ms for the small pages just because the big ones need this time.. The content is sometimes static and sometimes loaded out of a javascript variable. – Michael Kunst Oct 26 '12 at 09:07
  • Is there a callback from your database query on completion that you can wait for? If you are using ajax, you can use $(document).on('ajaxComplete', function(){/*Do animation*/}); – Francis Oct 29 '13 at 18:55
0

I had a similar problem making a masonry site responsive. I use window.onload which waits for all elements to complete loading before initialising masonry.js. I also placed the window.onload inside .onchange function and it fired everytime the viewport resized.

I am sure applying similar principles will solve your problem.

otherDewi
  • 1,098
  • 10
  • 24
0

try once

$(window).bind('load',function(){
//code
});
0

Maybe you can set an event on your div.

myDiv.onafterupdate = myHandler;

function myHandler() {
   // Do here what you want to do with the updated Div.
}

Does this help you?

Arthur Borsboom
  • 323
  • 2
  • 10
0

In jquery you could use $() just after your DOM manipulation code.

$(function(){
//code that needs to be executed when DOM is ready, after manipulation
});

$() calls a function that either registers a DOM-ready callback (if a function is passed to it) or returns elements from the DOM (if a selector string or element is passed to it)

You can find more here
difference between $ and $() in jQuery
http://api.jquery.com/ready/

AJchandu
  • 141
  • 2
  • 9