I am working on a website in ASP.NET and I need to run a JavaScript function on page load from a content page and I also have a user control that needs to have some JavaScript executed on page load. I'm new to JavaScript and I'm not completely familiar with how our pages work (I'm also new on this project) but here's what I know.

The master page of our site implements some JavaScript on load and it allows the content pages to do on load events by allowing them to implement body_onload

function mp_onload()
{
    if(window.body_onload != null)
    window.body_onload();
}

On one of out content pages, I have several user controls that also need to execute on load functions. I've tried to do chain the events like this but am not having any luck.

In the user control:

function body_onload()  {
        addLoadEvent(cpWidget_onload);
    }
    
    function cpWidget_onload()  {
        makeExpandCollapse508('WidgetCollapsiblePanel');
    }
    
    function addLoadEvent(func) {
        var oldonload = window.onload;
        if(typeof window.onload != "function")
            window.onload = func;
        else
            window.onload = function() {
                oldonload();
                func();
            }
    }

On the content page:

function body_onload()    {
    makeExpandCollapse508('SelectPlanTypesCollapsibleExtender');
}

I stepped through this code in FireBug, but it doesn't seem to ever enter the cpWidget_onload function. I'm guessing that the content page's body_onload is getting deleted by the user control's body_onload?

Thanks in advance! Any help is greatly appreciated.

I think what you need to do is to take the onload into a variable and run it right away, and then run your function. A sample way to do it is below.

if (window.addEventListener) {  // anything but IE
  if (window.load) {
    window.__load = window.load
    window.__load()  // run the existing onload
    // then call your function here
  }
  else {
    window.addEventListener('load', function() {
      // call your function here
    }, false);
  }
}
else {  // IE
  if (window.load) {
    window.__load = window.load
    window.__load()  // run the existing onload
    // call your function here
  }
  else {
    window.attachEvent('onload', function() {
      // your function here
    });
  }
}  // ensure images are loaded

Mduncan8,

I'm pretty certain you need something called an "Event Router".

An Event Router establishes for a particular event, an "observer" - a function which is a member of a javascript object with a private array of "listeners" (functions you wish to run whenever the event fires) and a couple of public methods to add and remove listeners. When the event fires, the observer simply loops through the array of listeners, calling each in turn.

There are many better (and several confusing) explanations on the web.

You will find many formulations of the Event Router (in javascript and other languages), sometimes under different names, eg. "Observer Pattern", or "Publisher/Subscriber model".

Thus with a short function, you have a reusable mechanism to vary the code that runs whenever any event fires.

Here's a demo based on a formulation of Event Router that I find particularly understandable:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Airshow :: Untitled</title>
<style type="text/css">
button.addRemove {
	font-family: verdana;
	width: 150px;
}
</style>

<script>
function EventRouter(el, eventType) {
	var lsnrs = [];
	this.addListener = function(lsnr) { lsnrs.push(lsnr); };
	this.removeListener = function(lsnr) {
		var i = lsnrs.length;
		while(--i >= 0) {
			if(lsnrs[i] === lsnr) {
				lsnrs.splice(i,1);
				return true;
			}
		}
		return false;
	};
	el[eventType] = function(evt) {
		evt = evt || window.event;
		for(var i=0; i<lsnrs.length; i++) { lsnrs[i].call(this, evt); }
	};
};

function fnA(){ alert('a'); }
function fnB(){ alert('b'); }
function fnC(){ alert('c'); }

var windowOnloadHandler = new EventRouter(window,'onload');
windowOnloadHandler.addListener(fnA);//should alert('a') after the page has loaded
function fireWindowOnload(){
	window.onload();
}
</script>
</head>

<body>

<p>You should have seen alert "a" when the page loaded.</p>
<p>Now add/remove one or more events, then click the "Re-fire ..." button.</p>
<p>
	<button class="addRemove" onclick="windowOnloadHandler.addListener(fnA);">Add alert("a")</button>&nbsp;
	<button class="addRemove" onclick="windowOnloadHandler.addListener(fnB);">Add alert("b")</button>&nbsp;
	<button class="addRemove" onclick="windowOnloadHandler.addListener(fnC);">Add alert("c")</button>&nbsp;
<br />
	<button class="addRemove" onclick="windowOnloadHandler.removeListener(fnA);">Remove alert("a")</button>&nbsp;
	<button class="addRemove" onclick="windowOnloadHandler.removeListener(fnB);">Remove alert("b")</button>&nbsp;
	<button class="addRemove" onclick="windowOnloadHandler.removeListener(fnC);">Remove alert("c")</button>&nbsp;
</p>

<p>
	<button onclick="fireWindowOnload();">Re-fire the window.onload event</button>
</p>

</body>
</html>

By calling the listeners with the line lsnrs[i].call(this, evt); , we ensure that each listener function can be written in the normal way, as if it were a solo handler, ie :

  • Accepts the event (evt) as a formal parameter
  • this can be used in the code to refer back to the event's target object

Neither of these features is used in the demo above.

Airshow

Another thing - with simulated events as in the demo, where a button is clicked to trigger the window's load event. Here, this would still refer to the window, but evt would be the button's click event not the window's load event. You can confirm this by alerting as follows :

function fnA(evt){
	alert('A : ' + (this==window) + ' : ' + evt.type);
}

You can (probably) take advantage of this feature should you need to test whether the listeners are being run in response to the genuine window load event or a simulation thereof.

if(evt.type === 'load') {
    //... genuine window load event has fired
}
else {
    //... window load event has been triggered by a no-load event
}

Airshow

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.