JNat
JNat

Reputation: 1496

How to prevent onload from running always?

I have a function I want to run when the homepage of a website is first loaded. However, I don't want that function to run if, instead of getting to the homepage by accessing it directly, I get there because I clicked on a link on the site that directs me there.
For this, I direct every link that gets you to the homepage to home.html#loaded instead of home.html. I also created the function below to be the one onload executes:

function onloadPreventer(fun) {
    if (window.location.hash != "#loaded") {
        //alert(window.location.hash);
        window.location = window.location + "#loaded";
        //alert(window.location.hash);
        fun;
    };
};

This function should only execute the function fun if there is no #loaded after home.html. However, it always executes fun.
However, the weird part is that it does not add #loaded once again:

When I first go to home.html (without hash) -- and if I comment out the alert statements -- it first gives me nothing, then gives me #loaded and then runs fun. All as it should.
If I go to home from another page, I'm already first loading home.html#loaded. The page alerts nothing, onloadPreventer does not add another #loaded at the end of the current location, but fun runs anyway.

The above function is called from inside the <body> tag, through an onload event:

<body onload="onloadPreventer(anotherFunction(arg))">

Unlike what the comments below suggest, fun does run. My problem is that even if the page has the hash #loaded, the rest of the code inside the if statement does not run, but fun still does.

What's wrong with this code?
And is there another way (possibly simpler) to accomplish what I am trying to accomplish?

Upvotes: 3

Views: 12342

Answers (3)

Oriol
Oriol

Reputation: 288120

It seems you are confused with functions:

function foo(){ /* ... */ } /* does NOT call foo */
function bar(){ /* ... */ } /* does NOT call bar */
foo;                        /* does NOT call foo */
foo(arg);         /* DOES call foo with arg as argument  */
foo(bar);         /* does NOT call bar, and DOES call foo with bar as argument */
foo(bar(arg));    /* DOES call bar with argument arg, and DOES call foo
                     with the returned value of bar as argument */

Then, you are calling a function if, and only if, you use parentheses.

(Alternatively, you can make browser to call functions for you, e.g. making them event handlers, or delayed functions with setTimeout or setInterval. In those cases you don't use parentheses.)

In your case, you can use

function onloadPreventer(fun) {
    if (location.hash !== (location.hash = "#loaded")) {
        fun(); // DOES call fun
    }
}

But fun must be a function, not the returned value by a function:

<body onload="onloadPreventer(
     function(){anotherFunction(arg);} /* does NOT call anotherFunction */
)">

But better separate scripts from content:

function fun() {
    anotherFunction(arg);
}
document.body.onload = function onloadPreventer() {
    if (location.hash !== (location.hash = "#loaded")) {
        fun(); // DOES call fun
    }
};

Upvotes: 3

rafaelcastrocouto
rafaelcastrocouto

Reputation: 12161

This works like a charm:

DEMO

$(window).load(function(){
  var load = "#loaded";
  if (window.location.hash != load) {
    window.location = window.location + load;
    document.write(load);
  };
})

Your problem is in here: onload="onloadPreventer(anotherFunction(arg))

The "anotherFunction" is running because of the () after it.

You can use onload="onloadPreventer(anotherFunction) or use event listeners since we are no longer in the dark ages!

Upvotes: 1

Homungus
Homungus

Reputation: 1114

This works in my tests:

I have two rudimentary pages:

<html><head>
<script type="text/javascript">
var callWhenNoHash = function() {
    console.log('called');
};
window.onload = function() {
    if (window.location.hash != '#hash') {
        callWhenNoHash();
    }
};
</script></head>
<body><a href="test2.html">test2</a></body>
</html>

and:

<html><head></head><body>
<a href="test1.html#hash">test2</a>
</body></html>

everything works as expected.

Upvotes: 1

Related Questions