CollapsiblePanelExtender: Can not get object in onLoad of page (AJAX Toolkit) - javascript

I need to add a Javascript event for CollapsiblePanelExtender on Javascript pageload of the page. Following is the definition of CollapsiblePanelExtender:
<cc1:CollapsiblePanelExtender ID="cpe" runat="Server" TargetControlID="pnlInstances"
BehaviorID="cpe" ImageControlID="lnkWebroleAction" ExpandedImage="~/App_Themes/Default/images/MonitorDownArrow16.png"CollapsedImage="~/App_Themes/Default/images/MonitorLeftArrow16.png"
CollapsedSize="0" Collapsed="false" ExpandControlID="lnkWebroleAction" CollapseControlID="lnkWebroleAction"
AutoCollapse="false" AutoExpand="false" ExpandDirection="Vertical" SuppressPostBack="true" />
And following is the Javascript code I am executing:
window.onload = pageLoad1();
function pageLoad1() {$find("cpe").add_expandComplete(coll_ExpandedComplete);
}
The problem is $find("cpe") returns null on this event. If I execute the same function from button click I can find the object.
Which other load events of Javascript I can use? I have tried $(documnt).ready.

You're not assigning the pageLoad1 function to window.onload, you're calling it immediately and assigning the value it returns (i.e. undefined).
You have to write:
window.onload = pageLoad1; // No parenthesis.
function pageLoad1() {
$find("cpe").add_expandComplete(coll_ExpandedComplete);
}
Or, alternatively, write a pageLoad() function, which will be called automatically by the framework when the page finishes loading:
function pageLoad() {
$find("cpe").add_expandComplete(coll_ExpandedComplete);
}

I agree with OP; there is (as original answerer pointed out) an error in the original post which is sufficient to make it look like there is not a real problem here; but I have a complex JS/Ajax driven page, and some code which tries to get some ASP.NET Ajax CollapsiblePanelExtender objects by their BehaviorID in a JS function which /is/ called on PageLoad.
These objects are usually ready, but sometimes aren't; if if try to run the code with a slight delay (100ms) they are ready. But delaying for a fixed time is not great; what event can I use, to know that these ASP.NET Ajax objects have finished building themselves?

Related

Why runs the alert before the redirect?

Can somebody explain here, why I get the alert before the redirect?
and is there a way to switch them?
function test() {
window.location.href="https://www.google.com";
window.onload = alert("It's loaded!")
}
here is an example:
jsbin: https://jsbin.com/zenidafihu/3
There are three different issues here:
Loading a new location is async
Assigning a new value to location won't stop everything until the new page has loaded. It will assign the value and then, at some point in the future, the browser will load the new page. In the meantime, everything will keep going as normal.
onload expects to be passed a function
alert("It's loaded!") calls the alert function (immediately) and is evaluated as the return value of that call (which is not a function). That return value is then assigned to onload.
To assign a function, you need to have an actual function, such as:
onload = alert.bind(window, "It's loaded!");
or
onload = function () { alert("It's loaded!"); };
Each page is a separate JS environment
When you leave the page, you create a new execution environment. All variables and data is lost. (Although you can store stuff via localstorage and cookies, and pass stuff to other origins through URLs).
It isn't possible for a page you are leaving to do anything to the page you are going to. You can't set an onload handler for the next page.
The redirection won't start until your current Javascript thread has finished executing. So nothing will happen re the location until the function ends i.e. until the Alert has been dismissed.
JavaScript is asynchronous language. So code for your alert will not wait for complete execution of your first statement i.e. redirection.

Javascript window.location calls getting lost?

I am having some trouble with a bit of code. I have a function that does some stuff to some data, calls a remote system (activating a script on that system and passing in the data), and then makes another call to the same system to activate a different script (which acts on the data saved above). The problem is that the 1st call to the remote system appears to get lost in the execution.
This is being run in Safari, uses jquery; the function is tied to a button click, which is defined in the javascript code with an onclick function (i.e. it is not defined in the html button definition).
Here's a rough breakdown of the function (cleaned out for viewing purposes - I hope I left enough to make it clear):
function compareJSON() {
// loop through the objects, testing and changing data
// ...
dataSession=({ //build object for output });
$.each( dataSession.chapters , function( indexC, value ) {
//compare objects to some others, testing and changing data
});
// ...
//Call remote script on other system
urlString="url://blah.dee.com/Blar?script=SaveJSON&$JSONobject=";
window.location= urlString + JSON.stringify(dataSession);
//Call remote script on other system
window.location="url://blah.dee.com/Blar?script=EditJSON";
}
The last three lines of code are the two calls. It uses the window.location to actually trigger the remote system, passing the data through the URL. But I need BOTH scripts to get called and run. It appears that only the LAST script in the sequence ever gets run. If I switch them around it remains whatever is in last place.
Is there something about the window.location that doesn't actually process until the end of the function?
This script actually used to be a series of separate function calls, but I figured I was running into asynchronous execution that was causing the various script calls to not register. But once I put the code into this single function, it was still happening.
Any clues would be helpful.
Thanks,
J
Modifing the value of window.location is reserved exclusively for instances in which you'd like to cause a browser redirect.
It looks like you want to trigger a page request instead. You say you already have jQuery loaded, if so, you can trigger such a request using jQuery.get or a similar function.
For example:
// Loads the myscript.php page in the background
$.get('myscript.php');
// You can also pass data (in the form of an object as the second argument)
$.get('myscript.php', { name: "John", time: "2pm" });

How can one simulate events triggered on load when adding javascript to a page through the browser's console?

I'm currently working on a script to be placed on a 3rd-party site...in order to test it I'm opening the 3rd party's site and running the script in the browser's console (Chrome). Some code I need to executed on window.load(), but that code isn't being executed with this method of testing. I'm assuming it's because the code bound by load to the window is being bound after the load event has taken place, thus never being triggered. My question has two parts:
Is the reason that window.load is not being triggered in fact because it's being added after the load event has been triggered? Or is this wrong and there is likely a problem elsewhere?
How best can one simulate events triggered on load when appending javascript through the console like this?
if(document.readyState === "complete"){ will detect if the load is already complete.
You could easily use an else and then put in the load event handler if it hasn't finished loading yet. Something along the lines of:
if(document.readyState === "complete"){
// do stuff
}else{
// attach load handler
}
What I like to do is define a pageLoaded type function that I can run at a later point with my code, that way I can call it immediately if the page is already loaded, or let the load handler call it when the page load does fire. Something like:
var pageLoaded = function(){alert("Page is ready!");}
if(document.readyState === "complete"){
pageLoaded()
}else{
// attach load handler, calls pageLoaded()
}
Of course, since you tagged your question as jQuery you could always just wrap all your code in jQuery's handy dandy ready function shorthand:
$(function(){
// do stuff
});
This passes your anonymous function to jQuery where it will do something very similar if not identical to the above vanilla javascript.
Define your event in a function and then call that function from the console.
function do_this_on_load() { alert("Loaded!") }
$(window).load(do_this_on_load);
Then you can from the console run:
do_this_on_load();
to see what it does on the page.

Run js function once when fired more than once

I have a Div that uses jQuery to load a file/contents with a javascript function..
function DoWork() {
// Do Stuff
}
Let's say the user can reload the Div and pull the same file/contents with the same js function DoWork(). The problem is, when the file is reloaded, the previous loaded function DoWork() is still running. How can I kill the previous fired DoWork() and restart it?
Javascript is single-threaded, which means only one thing can be executing at a given moment. If DoWork is already "running" it's either a) blocking all other JS code, and you have no choice but to let it finish since you have no way to execute any interruption code until it finishes on its own, or b) DoWork is scheduled to fire off on an interval via setTimeout() or setInterval().
If it's the latter case, setTimeout() and setInterval() return an ID. Store that ID somewhere and call clearTimeout(doWork_timeout_id) or clearInterval(doWork_interval_id) according to how you started it.
You can build a simple function that use: setTimeout and then each call to DoWork will call first to: clearTimeout. I don't really like this solution because you will waste CPU on setTimeout.
So another option will be to use web worker in DoWork (It will do lots of other good things for you in case you are working with big data as it's running in another thread) - then you get an option to send 'stop' message each time you start the work of DoWork().
Are you using ajax to load the div's contents? if so, the better way is as follows:
var doWorkAjax=null;
function DoWork(){
if (doWorkAjax) doWorkAjax.abort();
doWorkAjax = $.ajax(url, data, function(result){
....
doWorkAjax=null;
});
}

asynchronous javascript prepare function

To speed up my application I want to prepare some data before DOM is ready and then use this data when DOM is ready.
Here's how it might be:
var data = function prepareData(){
...
}();
$(document).ready(function() {
// use data to build page
}
How to prepare the data for later use?
Thanks
You need should use parentheses around the function expression for clarity (and because in a similar situation where you're defining and calling a function but not using the return value, it would be a syntax error without them). Also, when you use a function expression, you want to not give it a name. So:
var data = (function(){
...
})();
or use a function declaration instead:
var data = processData();
function processData() {
...
}
(Why not use a name with a function expression? Because of bugs in various implementations, especially Internet Explorer prior to IE9, which will create two completely unrelated functions.)
However, it's not clear to me what you're trying to achieve. When the browser reaches the script element, it hands off to the JavaScript interpreter and waits for it to finish before continuing building the DOM (because your script might use document.write to add to the HTML token stream). You can use the async or defer attributes to promise the browser you're not going to use document.write, on browsers that support them, but...
Update: Below you've said:
because prepareData is long time function and I assumed that browser can execute this while it's building DOM tree. Unfortunately '$(document).ready' fires before prepareData is finished. The question is how to teach '$(document).ready' to wait for ready data
The only way the ready handler can possibly trigger while processData is running is if processData is using asynchronous ajax (or a couple of edge conditions around alert, confirm, and the like, but I assume you're not doing that). And if it were, you couldn't be returning the result as a return value from the function (though you could return an object that you continued to update as the result of ajax callbacks). Otherwise, it's impossible: JavaScript on browsers is single-threaded, the ready handler will queue waiting for the interpreter to finish its previous task (processData).
If processData isn't doing anything asynchronous, I suspect whatever the symptom is that you're seeing making you think the ready handler is firing during processData has a different cause.
But in the case of asynchronous stuff, three options:
If you're not in control of the ready handlers you want to hold up, you might look at jQuery's holdReady feature. Call $.holdReady(true); to hold up the event, and use $.holdReady(false); to stop holding it up.
It's simple enough to reschedule the ready handler. Here's how I'd do it (note that I've wrapped everything in a scoping function so these things aren't globals):
(function() {
var data = processData();
$(onPageReady);
function processData() {
}
function onPageReady() {
if (!data.ready) {
// Wait for it to be ready
setTimeout(onPageReady, 0); // 0 = As soon as possible, you may want a
// longer delay depending on what `processData`
// is waiting for
return;
}
}
})();
Note that I happily use data in the onPageReady function, because I know that it's there; that function will not run until processData has returned. But I'm assuming processData is returning an object that is slowly being filled in via ajax calls, so I've used a ready flag on the object that will get set when all the data is ready.
If you can change processData, there's a better solution: Have processData trigger the ready handler when it's done. Here's the code for when processData is done with what it needs to do:
$(onPageReady);
That works because if the DOM isn't ready yet, that just schedules the call. If the DOM is already ready, jQuery will call your function immediately. This prevents the messy looping above.

Categories