What follows is my Javascript document, that runs in $(document).ready(). The Javascript is loaded from the footer of my site. For the purposes of simplification, I've put [...] in place of irrelevant code.
// When the document is ready, run the display scripts
$(document).ready(function() {
// Define the frame height functions
function getDocHeight(doc) {
[...]
}
document.domain = 'mysite.com';
function resizeIframe() {setIframeHeight('date-price-book');}
function setIframeHeight(ifrm) {
[...]
}
function AutoResize() {
resizeIframe();
resizeIframe();
setTimeout("AutoResize()", 500);
}
AutoResize();
[... more Javascript code...]
When I run the page, I get the error: Uncaught ReferenceError: AutoResize() is not defined.
I can stop this error from occurring by commenting out the line AutoResize(); (final line in my example code above). But why is this error being thrown? Surely the AutoResize() function has just been defined in the lines immediately above it?
Thanks for your help!
setTimeout("AutoResize()", 500);
When the setTimeout above is executed, it evalutayes the string in global scope. AutoResize() is hidden inside the closure so it is not found.
Assign a reference to the function by using the name.
setTimeout(AutoResize, 500);
other option is a closure
setTimeout(function() { AutoResize(); }, 500);
You would use the closure method if you want to send a parameter to the function.
Because you're defining AutoResize inside the $(document).ready(function () { ... } ); closure, it's not available globally (which is nice).
When you use a string instead of a function reference when calling setTimeout (which is bad), there is an assumption that the function call that the string will resolve to is globally available (because setTimeout runs in window/global scope).
I'm not sure. It works when I try this part.
function AutoResize(){
console.log('test');
setTimeout('AutoResize()',1000);
}
AutoResize();
Maybe it's somewhere else that something is going wrong.
Related
I want to call jquery function in side of java script. My code is:
<script type="text/javascript">
function calljs(){
getUserMail(usermMail);
}
$(function() {
function getUserMail(usermMail) {
***some code*****
}
});
</script>
I got error from browser console:
ReferenceError: getUserMail is not defined.
How to solve this problem?
As far as i understand, the method is not defined when the method is being called. So define it before it is getting called
<script type="text/javascript">
function getUserMail(usermMail) {
***some code*****
}
function calljs(){
getUserMail(usermMail);
}
$(function() {
//
});
</script>
hope it helps
If it is really compulsory to put the function with in the jquery's ready callback (which I don't think is compulsory) use the following way
<script type="text/javascript">
var getUserMail = null;
function calljs(){
if ( null !== getUserMail ) {
getUserMail(usermMail);
}
}
$(function() {
getUserMail = function (usermMail) {
***some code*****
}
});
</script>
You can simply do ,
$(document).ready(function(event) {
getUserMail(usermMail);
});
and define it like ,
function getUserMail(usermMail){
. . .
}
or using jquery ,
$(document).on('click', ".selector", function);
trigger a function on an event
getUserMail is not defined in a scope that is accessible to calljs. This is why you get the ReferenceError; in the context in which you tried to invoke getUserMail there was no function with that name available.
// At this point nothing is defined
function calljs(){
getUserMail(usermMail);
}
// now calljs is defined as a global and can be invoked from anywhere
$(function() { // this line is calling a function named $ (an alias for jQuery)
// and passing it an anonymous function as a parameter.
function getUserMail(usermMail) { // This function is being defined inside
// the scope of the anonymous function,
// it can be used anywhere inside the
// anonymous function but not outside it.
// ***some code*****
}
});
// we are now outside the scope of the anonymous function,
// getUserMail is no longer in our scope and can't be called from here.
The easiest and likely best solution for most situations would be to make sure that any functions that call each other are in the same scope.
From what I can tell you don't really need calljs, you were just trying to use it to poke a hole into the scope of the anonymous function where getUserMail is defined.
Instead you should probably get rid of calljs and move any code that is calling getUserMail inside the ready callback. If getUserMail needs to wait for the ready callback to be fired before you call it, any code that invokes it also should be inside the ready callback too. (Things like event handlers that call it should already be inside the ready callback anyway.)
If there is a reason that you can't move it into the ready callback, such as something in another .js file needs to be able to call it etc, your application might be too complicated to be realistically maintained as jQuery soup. It might be worth the effort to port it to a framework such as Ember or Angular.
Also so you know, there is no need to use the type attribute on your script tags. JavaScript is the only language that has wide support in the browser and all browsers default to using JavaScript for script tags.
I have a script that I didn't write already running on a page. I'd like to, in a script I did write, be able to execute a function from the original script. Here's a simplified example of what I'm trying to do:
(function ($) {
$.fn.myExistingFunction = function (options) {
function doMyThing(text) {
alert(text);
}
}
}(jQuery));
jQuery(document).ready(function($) {
$.fn.myExistingFunction.doMyThing("alert text");
});
However, when I run this, I get the console output:
Uncaught TypeError: Object function (options) {
function doMyThing(text) {
alert(text);
}
} has no method 'doMyThing'
But it clearly has the method! I can see it right there. What am I getting wrong here?
You can only access that method from the scope of the plugin function. It is not defined in the global scope.
So you can't call that function. All you can do in your code is call functions that are available through what's called the scope chain where the function is called. In your case that is everything that is either defined in your function($){} or in global scope. But the function in the plugin is neither.
When you call $.fn.myExistingFunction.doMyThing you are treating doMyThing like an field in the myExistingFunction object. But actually it is defined inside the function. Maybe this code makes it clearer:
$.fn.myExistingFunction = function (options) {
var doMyThing = function(text) {
alert(text);
}
var hi = "hello";
}
In hi and doMyThing are local variables in the scope of myExistingFunction. If the plugin wasn't designed to expose the functionality to external code you can't access the variables.
An example of a plugin that was designed to expose some of its internal functions would be the jQuery UI datepicker (documentation). It needs functions like parseDate and formatDate interally, but these utility functions are likely to be useful for general development as well, which is why they have been added to the datepicker object explicitly.
I think your code needs a major rewriting, 'cause as it is it will never work, in fact your function doMyThing is not a property of $.fn.myExistingFunction, it is simply declared inside of it, and due to how the scope works in javascript, you'll never be able to call it.
In the rails.js that came with my rails (3.0.x, still with prototype), I see the following structure:
(function() {
// ...
document.on("click", ...
})();
What exactly is accomplished with the wrapping of the whole code in the anonymous function? Is this a valid way to delay the code until the dom has loaded or only the document object?
In my project, I currently have a lot of setup code inside a Event.observe(document, 'dom:loaded', function() { ... } block. I was wondering, if I should adopt the pattern above when I refactor my code.
You have stumbled across the module pattern. It is useful because variables inside the immediately invoked function are local and don't pollute the global namespace.
(function(){
var something = 17;
//can use something inside here
}());
//but not here anymore
Not ethat there is no difference in timeing since the function is immediately invoked (in the final () bit)
The self-invoking anonymous function will trigger what is inside immediately, which has nothing to do with delaying the code.
To make the code block inside be executed after the DOM is ready, you have to have DOMready listener. I guess the code you mentioned Event.observe(document, 'dom:loaded', function() { ... } is the one.
myfunc() runs successfully when called from within the same js file. but it is undefined (Firebug) when called from an HTML page:
JS file:
$(function() {
myfunc() {
alert('inside myfunc');
}
alert('outside myfunc');
myfunc(); //this successfully runs myfunc()
});
HTML:
<script>
$(function() {
myfunc(); //this doesn't run myfunc(). It's undefined
});
</script>
But when I change myfunc() declaration to:
myfunc = function () { ... }
It's no longer undefined, and runs successfully.
Sorry for this very noob question, but what just happened? Why did it work when I changed the way I declared the function?
It's a matter of scope.
In
$(function() {
myfunc() {
alert('inside myfunc');
}
alert('outside myfunc');
myfunc(); //this successfully runs myfunc()
});
it is only available inside the anonymous function (function() { }), so it would also be unavailable if you were to call it outside of the anonymous function but inside the same js file.
While if you declare it using
myfunc = function () { ... }
myfunc is a global variable and the function is available everywhere.
In the first snippet, myfunc only exists with in the scope of the anonymous function you've defined. In the second snippet, myfunc is not within any visible scope. Finally, in the third snippet when you define myfunc at the top level, it's available at the global scope so any other part of your javascript will be able to call it successfully.
If you find yourself still having trouble understanding variable scope in Javascript, you might want to try reading through some of the results for "javascript scope" on Google for a more thorough explanation.
I am writing an AngularJS web app and have a function outside of any scope that needs to call a function inside of a scope. I call the function and follow the instructions given in this answer.
function returnDest(callback) {
$(document).ready(angular.element(document.getElementById('body')).scope().getTask(function() {
if(callback) {
callback(locationInfo);
}
}));
}
It works often, but sometimes the function does not successfully run. A debugger gives me:
Uncaught TypeError: Cannot read property 'getTask' of undefined
I do not know why the function is being called on undefined when $(document).ready should have the function fire only after the DOM has been loaded. The same error pops up if I use $(window).load(). What can I do to ensure this function runs successfully?
For reference, here is the line in the HTML file where the 'body' element is defined
<body style="background-color:#e6e8f3" ng-app="app" ng-controller="controller" id="body">
$(document).ready should be outside of your function:
$(document).ready(function returnDest(callback) {
angular.element(document.getElementById('body')).scope().getTask(function() {
if(callback) {
callback(locationInfo);
}
})});
You're using .ready incorrectly. The moment you call returnDest, which is happening before the DOM is ready, it tries to get an element with the ID of body. Since it's not loaded, body can't be accessed. Instead, omit the body ID and use it like this:
function returnDest(callback) {
$(document).ready(function() {
angular.element(document.body).scope().getTask(function() {
if (callback) {
callback(locationInfo); // Not sure where locationInfo is coming from
}
});
});
}
angular.element returns a jQuery object.
ready() expects the argument you pass it to be a function that it will call when the document is ready.
It sounds like you need to wrap everything you are trying to pass to ready in function () { ... }.