Is there any way to make my browser tell me what is the first JavaScript that is executed when I click on for instance a div.
Let me break it down:
Code example:
<div id='hello'> Hi There </div>
jQuery('hello').bind('click', function() { alert('hello') });
The code above will naturally display hello when I click on it. But is there a way to make firebug or console in Chrome to automatically break on the first very first JavaScript call without explicit set the break point.
In a complex JavaScript web pages there is a lot of binds but takes hours to find what is the actual code behind it.
you can get all events of an element with console.log($(element).data("events"));
So if I'm following the question you have this scenario:
jQuery('#hello') //function call 1
.bind('click', function(){ function call 2
alert('hello');
});
One method to do this would be to override the function you want to test. You cache the actual function, overwrite it with yours to do debugging in, then execute your cache with the original arguments.
(function(){
var _jquery = jQuery;
jQuery = function(){
console.log('debug');
_jquery(arguments);
}
})();
Related
I came across a peculiar issue when trying to make an ajax call and isolate the actions of the function to itself. Here is the code snippet
$(document).on('click', 'input.action', function(event) {
var self = this;
$.ajax({
url:'http://date.jsontest.com/',
method:'GET',
cache:false,
dataType:'json',
success:self.process,
error:function(){self.process(false);}
});
self.process = function(data) {
if (data) {
alert(data.time);
}
else {
alert("Operation Failed!");
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div class="container">
<input type="button" value="Get Time" class="action"/>
</div>
Let me briefly explain what I am trying to do, on click of the button, I wish to receive some data from the server and display the data. I am using a process function to process the received data. In case of an error I reuse the process function in a different way to display the error message. I simply use the self variable to contain all the elements within the parent function. I fully understand the following:
What I know
I do not have to use the self to contain the process function because another method will not have access to it
Because the process method in the snippet above is declared after the ajax call for the program as far as it is concerned the process function is undefined.
I clearly know how to fix it.
Experiment:
Click on the Get Time button
Wait for as long as you want but see no result, which is expected because of the process function is declared after the ajax call
Click on the Get Time button again
It works now! Some time (which is probably not your time :P) is displayed now!!
What I wish to know:
What just happened? why does it work the second time and everytime after? Remember this only works for ajax calls, if it were the case that the assignment is retained in the function after calling it once, then this should work in every situation but it does not. Here is an experiment to show that it does not work the same way when ajax calls are not used: Fiddle - Experiment
The Solution:
I am adding a sample solution based on #Felix Kling's answer below. In the Sample Solution, there are two buttons Get Time and Get Date. I've attached the parameter to retrieve time in case of Get Time and date in the case of Get Date to the object self and it is interesting that once I click on Get Time nothing happens just like before but if I click on either Get Time or Get Date the second time only time is displayed.
What just happened?
In a simplified way, this:
var process;
// First click
ajaxCall(process); // process is still undefined
process = function() { ... };
// second click
ajaxCall(process); // process is defined
process = function() { ... };
The assignment to self.process "persists" between events because self refers to the same element.
Here is an experiment to show that it does not work the same way when ajax calls are not used: ...
It doesn't work in your fiddle because of one big difference: you are trying to execute process immediately. But it doesn't exist, so an error is thrown. At this point the script terminates and won't execute the rest of the function, where the function definition takes place.
In your example here, the execution of process is delayed. The script "doesn't know" that there is no function to call until the response was received.
There is nothing "special" going on here. Yes, accepted that the first time it returns undefined as it is yet to be defined.
But, you're attaching the function to the same element input.action. So, the next time, when you click the button, this already has the process method attached to it, so gets called when clicked again.
Try adding one more button with same class and click each once. Now though you've clicked the first button, clicking the second button will still not create an alert as it has not yet had the process function attached to it.
So I have a simple tab system which I handle with the .load function to load the desired content. The problem is that the page itself which contains this tab system is a ajax loaded content. And for some reason the initial call of the tab function to display the initial tab content won't work. But after manually choosing a tab, the load function loads the content properly.
her some code to look at:
The tab handler:
function loadTab(tab) {
$(".tab_a:eq("+otab+")").removeClass("tab_slc");
$('#tab_content').hide();
$('#tab_content').load("include/tab_downloadVersions.html .tab:eq("+tab+")");
$(".tab_a:eq("+tab+")").addClass("tab_slc");
$('#tab_content').fadeIn(function() {});
otab = tab;
}
at the end I call loadTab(tab); and the thing should be initialized. but for some reason the content remains empty. As soon as you manually click on a tab (I have an on click function which calls loadTab(tab) everything starts working)
Because the code by itself works, I think the problem is caused by the other script which handles the page itself. It is also a .load function which loads the page, which loads this tab system.
So do multiple .loads don't like each other? and if so, what can I change?
Thanks in advance ;)
EDIT: I could't post the entire code for some reason, but if you go here you can see the site in action with all the scripts:
n.ethz.ch/student/lukal/paint.net
The tab system is on the download page.
EDIT:-----------------------------------------------------------------------------------------------------------------------------
Big Update
So this is still the same issue but with a slight twist: I did what was recommended in the comments and put my secondary .load() call inside the success call of the first one.
$("#content").load("pages/contact #contentInside", function() {
$("#OtherContent").load("include/info #OtherContentInside");
});
So this works.
But now I had the great idea to make a giant load function. It is a slightly better function than just the plain load, cause it does some fading and stuff. But now I have the same problem, but even more complicated. I created the load function as a "plugin" so the function itself is in a different script file and therefore I can't access the inside of the success function. I solved this problem with a return $.ajax(); and a .done() call. The problem here is that there is some rare case where it just skips the secondary load function. So I am searching for a guaranteed way of controlling the order of the .load calls. Any idea?
The mock-up website is up to date with the new scripts if you wish to take a look. And people were complaining about potential virus spread from my link. For some reason I can't post long code snippets so the site is the best source I got to show everything. If you know a more trustworthy way to share my code please let me know.
We cannot see the rest of your code to tell where the initial call is being invoked from. A set up like the following should work:
$(function() {
var tab = 0;
loadTab( tab );
});
function loadTab(tab) {
//WHAT IS otab???
$(".tab_a:eq("+otab+")").removeClass("tab_slc"); //<<<==== otab
$('#tab_content').hide();
$('#tab_content').load("include/tab_downloadVersions.html .tab:eq("+tab+")");
$(".tab_a:eq("+tab+")").addClass("tab_slc");
$('#tab_content').fadeIn(function() {});
otab = tab;
}
Update
The reason it does not work initial is because otab is not defined the first time the function is called. You have initialized otab at the end of the function but you are using it at the beginning of the function.
UPDATE 2
I have had a chance to look at your code and I just found out what the issues are:
You do not have DOM ready
You are not calling the function on page load.
The following version of your code should work -- try not to use global variable as you're doing with otab. Since you're loading this script at the end of the page (an you are using event delegation) you may get away with DOM ready. Adding .trigger('click') or click() as indicated below should resolve the issue.
//Tab-loader
//Haeri Studios
var tab = 0;
var otab = tab;
var counter = 0;
//click detect
$(document).on('click', '.tab_a', function() {
tab = counter == 0 ? tab : ($(this).attr('id'));
loadTab(tab);
counter++;
return false;
})
.trigger('click'); //<<<<<===== This will call the function when the page loads
//Tab setup
function loadTab(tab) {
//Content Setup
$(".tab_a:eq("+otab+")").removeClass("tab_slc");
$('#tab_content').hide();
$('#tab_content').load("include/tab_downloadVersions.html .tab:eq("+tab+")");
$(".tab_a:eq("+tab+")").addClass("tab_slc");
$('#tab_content').fadeIn(function() {});
otab = tab;
}
//Initialize << WHAT ARE YOUR INTENTIONS HERE .. DO YOU REALLY NEED THIS PIECE?
$.ajax({success: function() {
loadTab(tab);
}});
A partial answer to this problem was to call the loadTab function inside the success call of the page load function, like charlietfl pointed out. But the problem is that there is no need to call the tabloader every time a new page gets called. So I would rather not have a rare call in every page setup function.
I am a bit disappointed by the system on stackoverflow. It seems like if you have not a high reputation level, no one gives a "S" about your questions. Well but at least some input was give, for which I am very thankful.
So by digging deeper into google I found out that the callback can be manually placed in the function where ever you like.
so if we have a function:
foo(lol, function() {
//This after
});
this does stuff after foo() is done. But what if we have another function inside foo() which we also need to wait for:
function foo(lol) {
bar(troll, function() {
//This first
});
}
The bar function is not relevant to the success call of foo. This causes the unpredictable outcome of calls.
The trick is to control when the success function of foo gets called.
If we add a parameter(callback) inside foo and call this "parameter" (callback();) inside the success call of bar, we can make sure the order is guaranteed.
And that's it:
function foo(lol, callback) {
bar(troll, function() {
//This first
callback(); //<-This callback placement defines when it should be triggered
});
}
foo(lol, function() {
//This after
});
We get:
//this first
//this after
I was thinking about what is best for my JavaScript code.
I have a HTML page that contains some forms. So I bring life to it with JavaScript here we go.
I was thinking about what the best way to exploit my JavaScript code.
First to create a JSON object that has all attributes and methods I need.
For example
var myObject={
menuBtn: null,
init: function(){
$(document).ready(function(){
/* the code will be executed after the load */
});
},
listenToMenuButton: function(){
/* add a listener to the button */
}
};
myObject.init(); // to start working
or instead of that
(function($){
var me = this;
me.menuBtn = null;
me.listenToMenuButton = function(){
/* add a listener to the button */
};
me.init=function(){
/* code to init all elements */
};
})(jQuery);
Can any one advise me what is best and what are the advantages (of the two approaches)?
For example I know that the first implementation allows me to call a method as many times as I want. But the drawback of it is that the user can do some hack on it and call it (from firebug for example) and apply a behavior that was a fake one/
And when should I develop an extension (jQuery)?
I hope you guys can help me to design well my code.
I understand how you feel. I felt like that for a long time until I found this:
http://addyosmani.com/resources/essentialjsdesignpatterns/book/
I am learning javascript, and am trying to adjust the following:
$('#myform').change(function() {
if ($('#sv_I4b').attr('checked')||$('#sv_I4c').attr('checked')){
$('#sv_I5').removeClass('hidden');
} else {
$('#sv_I5').addClass('hidden');
}
});
To be a a function with a name that I can call on different events, such as page load etc.
I don't yet fully understand each element, but I know that:
if ($('#sv_I4b').attr('checked')||$('#sv_I4c').attr('checked')){
$('#sv_I5').removeClass('hidden');
} else {
$('#sv_I5').addClass('hidden');
}
is the core "logic" of the function: if (condition) {then this} else {that}
and more or less understand what is happening there. Which leaves the bounding javascript (is there better terminology than that?):
$('#myform').change(function() {...});
My Questions (are the following true etc):
The dollar I think denotes that it is jQuery
The id my form obviously
pertains the script to events within that form (namespace?)
.change seems to be, a trigger that listens to ... any change taking place
within #myform? so every time a change happens within #myform this
runs? That seems inefficient
function() I don't yet understand what
an anonymous or empty function does, just defines what is contained
in {} as a function?
My goal: to be able to have something like
function myfunction()
{
if ($('#sv_I4b').attr('checked')||$('#sv_I4c').attr('checked')){
$('#sv_I5').removeClass('hidden');
} else {
$('#sv_I5').addClass('hidden');
}
}
and then
$(function() {myfunction});
so I can call that function on page load, but I don't wan't to loose the functionality the .change syntax is providing me (that it changes as the user interacts with the elements on the page also.
Apologies for the general and cumbersome levels of ignorance
You guessed how to define the function correctly — that is,
function myfunction()
{
if ($('#sv_I4b').attr('checked')||$('#sv_I4c').attr('checked')){
$('#sv_I5').removeClass('hidden');
} else {
$('#sv_I5').addClass('hidden');
}
}
works just fine. However, this:
$(function() {myfunction});
Should be written as:
$(myfunction); // Run on page load.
$('#myform').change(myfunction); // ...and also run it when the form changes.
However, that second line won't actually work until the page has loaded unless the form exists at the time the script runs, so you may want to change it to this:
$(function() { // On page load, run this anonymous function:
myfunction(); // Run the function now (where now, at this point, is page load).
$('#myform').change(myfunction); // ...as well as when the form changes.
});
$ is shorthand notation for jQuery, and essentially namespaces any functions to the jQuery framework.
my_form is a DOM selector. $('#my_form') wraps the matched DOM element up as a jQuery object, adding all sorts of useful methods and properties.
.change() is an event listener which, as you guessed, watches for change events on that jQuery object. It is a little inefficient - take a look .on() instead.
the most useful behaviour an anonymous function (closure) is to create private scope, something that javascript doesn't otherwise provide.
I'm binding the window.onload event like this
// It's a little more complex than this, I analyze if there is any other function
// attached but for the sake of the question it's ok, this behaves the same.
window.onload = myfunction;
Onload is triggered twice on my local machine a several times on the production server
If I change it by the jQuery equivalent
$jQuery(window).load(myfunction);
It behaves as expected (executed only once).
Could you help me to understand possible reasons why the first option it's not working as supposed?
Thanks!
The parentheses on your assignment — myfunction() — executes your function. You haven't shown what myfunction does, but this means that the return value from that function is being assigned to window.onload, not the function itself. So, I don't know how that is getting executed, unless you have somehow got that to work, like ending the function with return this;
You want
window.onload = myfunction;
Given the nature of window.onload, it seems unlikely that pure browser events alone are making both calls to myfunction. Therefore, a breakpoint inside your function will help you see the call stack. I've included screenshots for Chrome.
Sample code:
var alertme = function() {
alert("Hello");
}
window.onload = alertme;
function testsecondcall() {
alertme();
}
testsecondcall();
Open your page in Chrome.
After the page has loaded once, open the Developer Tools panel and put a breakpoint on the line inside your function, then refresh the page.
Check the call stack of both times that it breaks. One will be empty (the actual window.onload). The other should give you some information like the following:
On the right, under "Call Stack", you see alertme is called by testsecondcall