0

I've got the code below, I've already set variable ShowLoading in another function. Could this be the reason? IE variables in javascript not being passed over when you start a new function? I also tried without opening a new function and adding onto an existing but with no Joy.

The DIV#Loading is based after the javascript.

$(document).ready(function() {
if(ShowLoading == true){
    $("#Loading").show();
}else{
    $("#Loading").hide();
}
});

ShowLoading is set here:

if ($.trim(ObjNumber) != ''){
    $.post('#URL#', {ObjNumber: ObjNumber}, function(data) {
        var ShowLoading = "No";
        $('div#Results-Data').html(data);
    });
}
Earunder
  • 177
  • 1
  • 11
  • 6
    depends on if ShowLoading is a global variable, or a local variable. Since you don't show how/where you set it, we can't really help you. – Marc B Sep 16 '14 at 15:15
  • 4
    Separately: When you find yourself writing `if (flag == true`, stop and hit backspace ~8 times before typing the `)`. – T.J. Crowder Sep 16 '14 at 15:16
  • 1
    Probably not working because you're running this as the page loads but have the `ShowLoading` variable in another function which wouldn't have run yet. – Nischaal Cooray Sep 16 '14 at 15:16
  • Update the question with the declaration of the `ShowLoading` variable – Himal Sep 16 '14 at 15:17
  • ShowLoading must not be a string, you are checking for a boolean. Try working with === instead of == to avoid falsy/truey (does that word exist? :)) values. Also, maybe you should give the following reading a go: http://speakingjs.com/es5/ch10.html Edit: About == and === : http://stackoverflow.com/questions/359494/does-it-matter-which-equals-operator-vs-i-use-in-javascript-comparisons – CunningFatalist Sep 16 '14 at 15:23
  • Since you are declaring the `ShowLoading` inside a function you won't be able to access it from outside that function.take a look at [how to show loading spinner in jquery](http://stackoverflow.com/questions/68485/how-to-show-loading-spinner-in-jquery) for a better solution. – Himal Sep 16 '14 at 15:25
  • 1
    What's the scope for ShowLoading? From the example, it looks local to the if function – ltotally Sep 16 '14 at 15:27

4 Answers4

1

If you use typeof() you can check to see if ObjNumber is undefined do not test it as ' ' if your expecting a number. Your test is not going to work if your checking for someObject != ' ' use typeof(someObject) === undefined then you will be getting back true if undefined and then you can show the div and hide it for false. You can also do tests to see if the object is a number, function or any javascript type. The only problem with your code is your if statement none of your code for showing or hiding is wrong. Keeping everything wrapped in the $(document).ready() is best practice so you know the DOM is fully loaded prior to manipulating the DOM. remember the DOM has nothing to do with your object ObjNumber and based on your question ObjNumber is loaded in after DOM_ready and is loaded in by a POST.

Do not test strings of "No" and "Yes", you should use a Boolean [true|false] for simple yes|no tests. Strings should not be used for this type of test. "Yes" and "No" mean nothing to a computer.

I would also like to point out you do not have a scope problem (assuming that the value ShowLoading is being initialized at some point prior to its test). Every time you call $() and passing in the search criteria. You are setting the scope of the DOM element search. It will start from the root of the DOM tree and traverse to the point of finding the element that meets that criteria. So when you call $("#Loading"), it will return the DOM element that has the id "Loading". This will return the correct DOM element every time. You do not have any scope problems with your current example. The return element will be in a local object within the scope of the function that called it.

The reason you would want to check that the DOM is fully loaded prior to doing anything with the DOM is to avoid errors like "undefined value has no attribute". If you attempt to access the DOM element prior to it being loaded you will get this error due to accessing an undefined object. All javascript actions should wait till DOM is fully loaded. All starting points for your code must be wrapped in a DOM ready check.

$(document).ready(function() {
  if (typeof(ObjNumber) === undefined){
    $("#Loading").show();//ObjNumber is undefined show loading screen and start loading stuff.
    //post your data and do what ever you need to do for loading here
  }else{
    $("#Loading").hide();//ObjNumber is defined. hide loading screen. everything is loaded.
  }
});

You do not need to set ObjNumber to the global scope like everyone is telling you. if you want to pass ObjNumber to another function to do loading then just do this.

$(document).ready(function() {
  if (typeof(ObjNumber) === undefined){
    $("#Loading").show();//ObjNumber is undefined show loading screen and start loading stuff.
    loadStuff(ObjNumber);
  }else{
    $("#Loading").hide();//ObjNumber is defined. hide loading screen. everything is loaded.
  }
});


function loadStuff(obj){
  //load some stuff using obj
}

This will eliminate any problems you have with loading up the global scope with a bunch of values that can turn your code into a rats nest.

To make this example even smaller you can assume that the object ObjNumber is undefined prior to DOM_ready as you're getting ObjNumber from a POST and you can't POST prior to the DOM loading. So you can show the loading screen at DOM_ready and simply hide it when load is finished. I have changed this next example from a POST to a GET as you're not posting data your really getting date.

/* have the loading screen set to display by default
* only hide it once the object is loaded.
* this way you don't have to keep checking if its 
* loaded just simply load it then hide the loading display.
*/
$(document).ready(function() {
  var ObjNumber;
  $.get("my url path to get value", function(data){
    ObjNumber=data;
    $("#Loading").hide();
  });
});

I would also like to comment that you should be using a GET when getting a value not a POST. POST is for setting values not getting values.

Patrick W. McMahon
  • 3,059
  • 1
  • 15
  • 28
0
  1. ShowLoading should be global.
  2. ShowLoading should take boolean values true or false, instead of No and something else different from No.

Hope it's useful!

Academia
  • 3,484
  • 6
  • 28
  • 47
-1

You should move ShowLoading to the global scope.

outside of your function initialize a global var;

var ShowLoading = false; // or true

modify your function

if ($.trim(ObjNumber) != ''){
    $.post('#URL#', {ObjNumber: ObjNumber}, function(data) {
        ShowLoading = false; // remove var to use global variable.
        $('div#Results-Data').html(data);
    });
}

your should be ok.


Another approach is to create a function which toggles loading element.

function Loader(what) {
   if(what == "show") {
      $("#Loading").show();
   } else if(what == "hide") {
      $("#Loading").hide();
    }
}

Show whenever you you want to show your loader you call Loader('show'); or Loader('hide'); to hide it;

if ($.trim(ObjNumber) != ''){
    Loader('show');
    $.post('#URL#', {ObjNumber: ObjNumber}, function(data) {
        Loader('hide');
        $('div#Results-Data').html(data);
    });
}
Oden
  • 734
  • 8
  • 21
-1

You are declaring ShowLoading variable in what seems a different scope, so, you cant access it from another function

This is your code:


$(document).ready(function() {
  if(ShowLoading == true){
    $("#Loading").show();
  }else{
    $("#Loading").hide();
  }
});
...
if ($.trim(ObjNumber) != ''){
    $.post('#URL#', {ObjNumber: ObjNumber}, function(data) {
        var ShowLoading = "No"; // this variable is only accessible 
                                // from this scope
        $('div#Results-Data').html(data);
    });
}

To fix the problem with the scope, I suggest (as the simplest alternative) to declare the variable in a common parent scope, something like that:


var ShowLoading; // declare the variable here
$(document).ready(function() {
  if(ShowLoading == true){
    $("#Loading").show();
  }else{
    $("#Loading").hide();
  }
});
...
if ($.trim(ObjNumber) != ''){
    $.post('#URL#', {ObjNumber: ObjNumber}, function(data) {
        ShowLoading = false; // you assign the variable as normal
                            // this variable can be accessed 
                            // from parent and sibling scopes too
        $('div#Results-Data').html(data);
    });
}

NOTE: Although there is no variable types on javascript, is preferable where possible to keep consistence on variables of use true/false for boolean, this would make the code a little more readable

WARNING: this solve the scope issue, but still remains another issue: a Race Condition, if your $(document).ready event handler is called before your callback for post, your "show loading" will never be hidden.

To fix this another issue, I suggest to hide the #Loading element in the post callback, this way:


/*var ShowLoading; No need for ShowLoading and it doesnt really help*/
$(document).ready(function() {
  $("#Loading").show();
});
...
if ($.trim(ObjNumber) != ''){
    $.post('#URL#', {ObjNumber: ObjNumber}, function(data) {
        // instead of setting ShowLoading = "No", we can hide the element
        // from here 
        $(document).ready(function() {
          // wait for document ready before hiding #Loading element
          // to avoid accessing uninitialized DOM
          $("#Loading").hide();
        });
        $('div#Results-Data').html(data);
    });
}

NOTE: if you are trying to check if ObjNumber is a number, is preferable to use something like that:


if (!isNaN(ObjNumber)){
...
}
dseminara
  • 10,767
  • 2
  • 18
  • 21
  • This is not a solution he is testing for a number and his test he is using is `if ($.trim(ObjNumber) != ''){` the test he is currently using is for string. your solution is not a good one. he should be testing if it is a valid object and then can test if its a valid number. – Patrick W. McMahon Sep 16 '14 at 15:47
  • I only fixed the scope and race condition problem with the code as is, he doesnt ask anything about ObjNumber – dseminara Sep 16 '14 at 15:49
  • 1
    he is not having a scope problem he has a problem with his if statement. To know if he has a scope problem we would have to know more about his code and we do not. so based off of what he has given us the only real problem, assuming the object that has been past is in scope, its clear that he is testing for a number based on the name of the object and you will see he is testing it with ObjNumber !='' this is not the correct way to test for this and will give him false positives so he is not showing/hiding at the correct times. nothing else about his code can be assumed. – Patrick W. McMahon Sep 16 '14 at 15:52
  • You have over complicated a simple solution and just down voted a good clean working solution. You should really reconsider your actions as your hurting good solutions that should be promoted and your promoting solutions that should not be used. based on your comment on my solution you clearly did not look at my solution as you state that it did not solve the scope problem when it clearly did. – Patrick W. McMahon Sep 16 '14 at 15:59
  • Just improved my answer based on your feedback, thanks! – dseminara Sep 16 '14 at 16:02
  • Your just taking other good data from people that know what where talking about and down voting us while putting it in your response. Based on your actions the site should really down vote you. – Patrick W. McMahon Sep 16 '14 at 16:05
  • I am only downvoting answers with no-solutions – dseminara Sep 16 '14 at 16:12
  • well you down voted my solution and it works if you actually read it. – Patrick W. McMahon Sep 16 '14 at 16:16
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/61361/discussion-between-patrick-w-mcmahon-and-dseminara). – Patrick W. McMahon Sep 16 '14 at 16:18
  • I just explained on the comments why I believe your solution is not well enough, the initial code posted by Ashley is taking into account parallel loading, you broke it and turned it into sequential (also, she really want to know the thing about the scope) – dseminara Sep 16 '14 at 16:19
  • $(document).ready() checks to see if the DOM is ready and that is the best time to start executing as you would know when all javascript files have been loaded. This has nothing to do with ObjNumber and based on your comments i know you have no idea what your solution is doing. – Patrick W. McMahon Sep 16 '14 at 16:21
  • 1
    also if the DOM is not fully loaded and you attempt to show() or hide() that element you can get undefined value has no attribute errors. This will happen in your code. Once more stop down voting things you don't understand. Your comment about parallel loading and sequential loading shows that you don't know how the browser is loading objects. – Patrick W. McMahon Sep 16 '14 at 16:24
  • Sorry, I missed that argument, I will cancel my downvote on your question (since I considere it the best for now) and find a way to improve my own answer. My answer still look fine to me but I missed the potential issue about DOM – dseminara Sep 16 '14 at 16:31
  • you must check dom ready prior to doing anything with the dom. Thank you for the up vote – Patrick W. McMahon Sep 16 '14 at 16:45