My knowledge of JavaScript is very basic, and I'm somewhat familiar with the Chrome console. I am posting here as being uncertain about the correct terms to use, but hope to keep this question short and focused.
I have a browser page that uses JavaScript as certain elements change values. I know basically which .js file is responsible for this, but I would like to:
a) know which function is initially called when an element changes - i.e. be TOLD by the Chrome console.
b) put a "stop" in that function at a certain point, or add a line of code, or determine the value(s) of a local execution context
Are (a) and (b) possible? Using the Chrome console alone? adding console.log('status here is '+this.status) all over is very time-consuming.
Determine the context values (b)
To know the values of the local execution context, you can attach a hanlder function to the change event in your html element and log the value to the console output (console.log(myValue)). For input elements, for exmaple, a simple way to do it is adding the onchange attribute to the html element passing the handler function.
You can also add a breakpoint in the handler function using the F12 Developer Tools. Read more about it here: Google Chrome - Pause Your Code With Breakpoints
Example:
// This function will be called when you change the value and move the focus
// to a different element or when you click enter
function myHandler(input){
console.log(input.value);
}
<input value="123" onchange="myHandler(this);" />
You could also use onkeydown. For more events you can check: W3Schools - Dom Object Events
Event order (a)
Regarding the event order (a), you can reference to ths other question:
What is the event precedence in JavaScript?
I'm a python/data guy mucking around in a little bit of web, fundamentally clueless about JS and the dom and all that. So something really weird happened, and even though I found a solution, I'm trying to understand the mechanics of why.
The scene: a common problem
There's like a million prior SO questions that go along the lines of "I had some working jQuery/JS that manipulated some HTML. Then instead of hard-coding the relevant HTML, I created it programatically somewhere else and dragged it in via AJAX. Suddenly everything broke."
Invariably, the answer goes like this: "you can't do that. Hook up your code to something higher up the parent-child chain, event delegation is a magic thing and it will save you."
So that happened to me, I spent an hour or so reading prior SOs and learning about event delegation, and, indeed, it saved me, and my code worked.
But I don't understand why it was broken in the first place. So I'm hoping someone can explain the underlying theory to me, and that way I'll come to a deeper understanding of the whole dom bit.
Some Broken Code
$(document).ready(function(){
$("#autopubs").load("pubslist.html");
// Obviously, the stuff in pubslist.html is what the next line was
// supposed to work on
$('.collapse').on('show.bs.collapse', function () {
$('.collapse.in').collapse('hide');
});
});
probably no surprises about the solution. wrap autopubs in an outer div and hook the collapse thing to that. Done, worked, deeply dissatisfied.
But I still don't understand why this is necessary. Here's my mental model of what the broken code should have been doing.
Ok, the document's finished loading! Let's execute our code!
First line: let's go get this file and add it to the DOM. This is out there in the world as state, and now we're going to mutate it, as one does with state.
Ok, now it's part of the DOM. We're done with that line. Let's go to the next line.
Ok, now we want to hook up a bunch of event listeners to everything with the class collapse. Cool, let's look up the present state of the DOM. Hey look, there's all this stuff in there with the collapse class. Bam. Hooked up.
Except 4 never happened, because the second line of code apparently couldn't see all the stuff that the first line added.
Intuitively, there are two plausible reasons for this:
The second line executed before the first one finished getting the file in. If that's true, then I've learned something important about javascript (or jquery, or ajax, or something): lines don't always execute in order, or at least don't always finish before the next one starts.
The first line didn't actually mutate any state at all. The DOM isn't state. It's something else, something... maybe even immutable? The first line tinkered around with something else entirely, something the second line couldn't touch because it was trying to tinker with the DOM.
Honestly, both of those possibilities seem kind of bizarre to me. But there's obviously something I fundamentally don't understand going on under the hood here. Can someone help me?
JavaScript makes heavy use of asynchronous behaviour. Lines execute in order within the same function, but that doesn't mean they "complete" their action.
If you look at the documentation for load (http://api.jquery.com/load/) you can see that it takes an optional complete parameter. That is a callback. It is a function that will be ran when the operation completes. Calling load itself only makes the loading start, sort of "in the background".
So you could do this:
$(document).ready(function(){
$("#autopubs").load("pubslist.html", function() {
$('.collapse').on('show.bs.collapse', function () {
$('.collapse.in').collapse('hide');
});
});
});
The callback to load is ran after it completes.
Why your original hack-solution actually works? It attaches the event handler to an existing outer div, and the loaded HTML is put inside later, when it loads.
Your first assumption is correct. When calling ajax its asynchronous which means it will run a callback when complete. In this case jquery already calls a callback to append the content to the div but that happens after a delay of maybe 100 to 200ms or so.
The other code however can be run instantly but doesn't find anything because the async call isnt finished yet.
In jQuery if you check the documentation for load you will see something along the lines of (arg1, [arg2], [complete]) where complete will be a closure or callback function.
If you wrap the code within that callback function instead of below it than that code will be executed after the content is loaded and added.
EDIT
The load load is also one of the convenience / shorthand method in jquery. For more documentation check Ajax
Furthermore the DOM is very mutable and your first line that does the request does perform an operation on the dom. Due to the fact that it is async it will tell the script to continue running while it waits for its data which is why it fails.
Hope this helps abit! You've got the right picture :)
If I correctly understand, you should refer the new loaded DOM only on a 'complete' callback. Take a look here:
http://api.jquery.com/load/
$( "#result" ).load( "ajax/test.html", function() {
alert( "Load was performed." );
});
The first line did get executed, it changed the state. After that, you hooked an event to the change and that will get called everytime there is a change, but not for the first one since it has already happened before the event was hooked up.
jQuery.load is asynchronous, meaning you need to provide any code to execute after the content is added via callback. You have a working example at the bottom of the documentation page.
As others stated JavaScript wont wait with finishing the load function before executing the following lines. Therefore, you can use the callback parameter of the load function (or any other function that takes time, like AJAX or animations). So your first assumption is correct. AJAX (asynchronous JS) is a huge thing, you should dig into it :)
Additionally, you still can use delegation in your case:
$(document).on('show.bs.collapse', '.collapse', function () {
var collapse = $(this); // the individual $('.collapse') element triggering the event
});
This will bind the show.bs.collapse event to all .collapse elements, regardless if they exist now or are added later. Here the original selector is the $(document). In simple words:
"Hey document, whenever the event show.bs.collapse gets fired on an element with the selector '.collapse', run the following code."
You distinguish between direct and indirect event delegation or binding. In your example, you use direct binding, since you are ultimately selecting all now-existing .collapse elements and then do stuff with them:
$('.collapse').on()
You have to understand that this works only for currently existing elements that get selected when running that line. This wont apply for dynamically added elements of the same class.
I am editing a complex website.
Some jQuery functions are called in response to clicking on different elements (links, div, anchor, etc.).
How can I see what JavaScript function is called when I press on an element?
In each of the functions, add a console.log(functionname). so whenever the function is called, you will see a line in console telling you the function's name.
I believe you can do this with the Profile button although I haven't used this myself yet.
you can place a breakpoint on some inside function and see if the program hits it (in firebug you can use script tab for placing breakpoint)
In chrome/safari you can inspect the call stack on any breakpoint. I'm positive that firebug will let you do the same thing.
So set a breakpoint at the place where you wan to see what's calling it and then inspect the call stack to see what chain of calls led you to that point.
Warning: jQuery does a lot of anonymous functions so it can be a little tricky to trace back.
In many website pages, there are a lot of javascript codes to support the functionalities. The programmer can attach the event on the element via many methods. They can add the event directly in the element definition like
<input type="button" onclick="dosomething();">
or they can do this by javascript codes like:
<script>
document.getElementById('ele').onclick = function(){};
</script>
And usually there are so many codes here so that it's sometimes difficult for us to identify which event function are called after the element event is triggered.
So my question is: is there any method or plug-in can help to identify the next running javascript statement or function entry point after one element event is triggered?
One thing you could do is, define a function that will grasp all events assigned to each type of elements and show them somewhere on the page(preferably at the bottom). To trigger that, function you may add a button which should be clicked.
Of course, all this must be done in debugging state and you would certainly want to remove the button and the display panel when releasing the App.
We used to do this for our project, may not be elegant but it does serve the purpose.
There's no code that "emulates" the debugging of plugins like Firebug - however in case of "simple" onclick function simple alert will just show it:
var element = document.getElementById('ele');
alert(element.onclick);
And to programmatically trigger it:
element.onclick();
There seem to be a number of weird things one could do if one wanted, for hooking up page-load type events. Here are some specific questions:
I know about the auto-hooked-up pageLoad function. Are there any others like it?
Where do I hook up events like those from, e.g., Sys.Application.add_init or Sys.WebForms.PageRequestManager.getInstance().addPageLoading?
What's the difference between the first two of those and pageLoad, if any?
Rather importantly, what is the "correct" way to be sure that the ASP.NET AJAX files are all loaded before you start hooking up event handlers, processing the page, etc.? My current approach is to use the auto-hooked-up pageLoad to hook up the rest, but this seems kind of hacky.
The built-in pageLoad function is just a shortcut to the Sys.Application.load event. There is another one - pageUnload. Find more info here.
You can hook those events up almost whenever you like - using the pageLoad function, invoking the add_init/add_load method inside a script block or calling ScriptManager.RegisterStartupScript from server-side. Just make sure you call that JavaScript within the form tag (see #4). By default all those events occur after the page is loaded so your code should have already been executed by then.
Technically there should be no difference between using pageLoad and the load event - the first is just easier to hook up.
By default the ASP.NET Ajax script files are rendered just after the beginning of the form tag. This means that those files will get loaded before any other JavaScript statement defined within the form tag gets executed.