1

If got a problem using jQuery and I don't know how to fix it. Simply said Ive got the following:

var overlay;

if(condition == "test") {
    overlay = $("<div></div>");
}
else if (condition == "test2") {
    console.log("first-log");
    overlay = $("<span></span>");
}

console.log("second-log");
overlay.prependTo("body");

If the condition matches the 'if', everything works fine, the overlay is filled with content and will prepend to the body.

While the condition matches the 'else if', I get a error that overlay is undefined.

So I've putted some console.log()'s to see what my code is doing. Both console.log action are fired, but in my browser console I'm first seeing the 'second-log' and after that the 'first-log'.

My code is trying prepend before the 'if / else if' is finished, even if the condition matches.

I tried looking for a answer but I couldn't find anything at all so I hope someone here can help me out. Thanks!

jsfiddle of my code

ronnyrr
  • 1,481
  • 3
  • 26
  • 45
  • i guess the code should be overlay = $(""); – abc123 Dec 10 '13 at 08:54
  • Noticed and changed that. But this is just a dummy code, wrote quick. My own code is more complex so this is just a example. – ronnyrr Dec 10 '13 at 08:55
  • Is the code called more than once somehow? Is it in an event handler, setTimeout, something else? – Boldewyn Dec 10 '13 at 08:56
  • And what changes, when you add an `else` statement? `else { console.log(condition);}` – Boldewyn Dec 10 '13 at 08:57
  • 6
    The code you gave is fine, must be something in the unposted code that is causing the issue. – codefactor Dec 10 '13 at 08:59
  • If the prepend is happening before the if/else completes, there must be some more relevant complexity missing in your simplification - wrapped in a function? Asynchronously called with setTimeout? – Krease Dec 10 '13 at 09:01
  • I've added a JSFiddle in my post, it's pretty big but if you guys can get trough it that would be awesome. All my console.log()'s with "test" are logged after the prependTo is undefined. – ronnyrr Dec 10 '13 at 09:14
  • Syntax error in line 6 (stray closing parenthesis), and you forgot to embed jQuery. Fixed it here: http://jsfiddle.net/EBcG9/2/ But I can't see an error. – Boldewyn Dec 10 '13 at 09:36

4 Answers4

0

You should initialize the var overlay at the beginning of your program.

  • Whoever gave -1: why? This is a good fix given the posted code. `var overlay = $('');` fixes the problem for the missing `else` case. – Boldewyn Dec 10 '13 at 09:07
  • I've tried this. The overlay isn't undefined anymore as expected. But the content I added to the overlay in de 'else-if' isn't added. – ronnyrr Dec 10 '13 at 09:19
  • @Boldewyn - its likely because the answer isn't clear about what its being initialized to. As the code in the question stands, it also doesn't change any behavior for when `condition=="test2"` – Krease Dec 10 '13 at 16:26
0

I solve this kind of problems mostly with a callback or promises. With callback you could try this:

var overlay = $("");

testCondition = function(callback) {

  if(condition == "test") {
    overlay = $("<div></div>");
  }
  else if (condition == "test2") {
    console.log("first-log");
    overlay = $("<span></span>");
  }

  callback(overlay);

}

and call this function like this:

testCondition(function(callback){
   overlay.prependTo("body");
});

Here is a fiddle

As you can check in console, the right element gets prepended ;)

Igl3
  • 4,900
  • 5
  • 35
  • 69
  • Don't know, how this could possibly help in the first place. Just adding noise to a perfectly good `if`/`else`. (Don't get me wrong, I love promises myself.) – Boldewyn Dec 10 '13 at 09:05
  • Yes I know, it is kind of a dirty workaround here, but with this much information he gave it is the only working answer I could give. @ronnyrr: if you could add some more Code, we could find a better solution maybe ;) – Igl3 Dec 10 '13 at 09:08
  • How about @user3085570's answer? Works perfect without the overhead. Your's will fail too, when `condition == 'test3'`. – Boldewyn Dec 10 '13 at 09:09
  • Thats true...I will fix this, but keep the answer as additional hint, when he ever gets in kind of "undefined" async problems. – Igl3 Dec 10 '13 at 09:13
  • Thanks the answers and comments! I've added a JSFiddle in my post, it's pretty big but if you guys can get trough it that would be awesome. All my console.log()'s with "test" are logged after the prependTo is undefined. – ronnyrr Dec 10 '13 at 09:15
0

There dosen't seem to be anything wrong with your code, I just tested it and it's working!

Your code tested - http://jsfiddle.net/9Pb7u/

If all else fails a simple fix would be to put the prependTo inside the if statements - Also make sure you add some text or styling to the div and span otherwise they probably won't be visible until you look at the source.

if(condition == "test") {
    $("<div>TEST</div>").prependTo("body");
} else if (condition == "test2") {
    $("<span>TEST 2</span>").prependTo("body");
}

Working http://jsfiddle.net/9f93d/

Wez
  • 10,555
  • 5
  • 49
  • 63
  • I guess my code is a bit to complex to use this. Check my JSFiddle to know what I mean. – ronnyrr Dec 10 '13 at 09:22
  • I guess so, but that is the example you gave. All I get from your JSFiddle is syntax errors - perhaps fix those and include the relevant libraries first. – Wez Dec 10 '13 at 09:25
0

The key to the problem is in your update with the jsfiddle code. Based on your jsfiddle link, it seems to have this basic structure:

if (resource=="iframe") {
  console.log("resource is iframe");

} else if (resource=="json") {
    $.getJSON("someUrl", function(data) {
        console.log("resource is json");
    });
}

console.log("at the end - one of the above log statements should be hit");

However, I assume the problem you tried to simplify for the question is that your case for handling resource=="json" isn't being hit.

This is likely because the call to getJSON is executing asynchronously - the function inside that if block is not executing inline, when you expect it, but later, when the getJSON call has results, and after the rest of the outer function has finished execution

One way of fixing this is by changing the structure using a callback (similar to Igle's answer) to make sure your handling code isn't executed until afterwards:

function executeAfterIf() {
    console.log("at the end - one of the above log statements should be hit");
}

if (resource=="iframe") {
  console.log("resource is iframe");
  executeAfterIf();

} else if (resource=="json") {
    $.getJSON("someUrl", function(data) {
        console.log("resource is json");
        executeAfterIf();
    });
}

In this basic refactoring, executeAfterIf is the callback function called after either case of your if block is handled.

There are, of course, other patterns to handle this sort of thing; which one you choose depends on the code in the rest of your project.

Community
  • 1
  • 1
Krease
  • 15,805
  • 8
  • 54
  • 86