Pass Hash from URL to a Function with Delay - javascript

I am trying to pass a has such as http://mysite.com/#32132 via JS to a custom function.
Here's the function:
var downloadVideo = function(passed){
console.log(passed);
}
And here's how I'm getting and passing the hash from the URL:
if(window.location.hash){
var hash = window.location.hash;
hash = hash.substring(1, hash.length); // Remove the # from the hash
setTimeout('downloadVideo('+hash+')', 3000)
}
After 3 seconds, I just get an error in the console:
Uncaught ReferenceError: 32132 is not defined
I've tried different ways of calling downloadVideo. With quotes, without quotes, without the plus signs. Nothing seems to work. If I console.log the hash var immediately before the setTimeout it displays it correctly.

You need to represent it as a string if there's anything more than just numeric characters...
// ------------------v--------v
setTimeout('downloadVideo("'+hash+'")', 3000);
But better to pass a function that closes over hash...
setTimeout(function() { downloadVideo(hash) }, 3000);

You can use a closure to do that:
setTimeout(function() {
downloadVideo(hash);
}, 3000);

1) You don't need the second argument in your has substring - if omitted, the substring matches to the end of the string
2) with timeouts it's better to use anonymous functions; evaluated strings are, well, evaluated. Generally a bad idea.
3) the error is coming because you're passing a string without quotes. Fixing point 2 to use an anonymous function would make this error both more visible and harder to commit in the first place
4) you could always apply the timeout in the function, rather than in the call to it
Anyway:
setTimeout(function() { downloadVideo(hash); }, 3000);

Assume that the value of hash is test then:
'downloadVideo('+hash+')'
...evaluates to:
downloadVideo(test)
Notice that there are no quotes around the string test so it's treated as though it refers to a variable (that doesn't exist). This is one of many reasons not to pass strings to setTimeout. It's a bad practice, as described here:
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/eval#Don%27t_use_eval!
It's far better to pass a function to setTimeout. It's safer, easier to read, and doesn't suffer from the problem you've see here. When no arguments are required, simply refer to the function by name:
setTimeout(downloadVideo, 3000)
If arguments are required, as they are in your case, then you'll need to pass a reference to an anonymous function and have that function call the function that you want to invoke:
setTimeout(function() {
downloadVideo(hash);
}, 3000)

Related

JS / Jquery .load and .length

I'm new to Jquery/javascript with almost all of my experience being in PHP. I am now finding the importance of how things are ordered :)
So I'm trying to load some <div>s into the container #text-container using .load and then count them. My understanding of jquery's load function is that the 2nd argument is a callback function which will only run once all data has been loaded. But it is always reported as 0 even if there are 4-5 divs being placed in the container. Am I missing something?
1.txt
<div>1</div><div>2</div>
Code:
$("#text-container").load("1.txt",alert($("#text-container div").length));
This is just an example but I need to use that number to do a whole bunch of maths in other functions. So if I call those instead of alert and try to run .length in there they all get 0 and my math doesn't work :(
Ideas?
You need an anonymous function for the callback
$("#text-container").load("1.txt", function(data) {
alert( $("#text-container div").length )
});
This is just an example but I need to use that number to do a whole
bunch of maths in other functions.
Note that it's async, so you can't use it until it's actually there, and why would your .txt file contain DIV elements, seems like the wrong file extension to me ?
Answer
$("#text-container").load('1.txt',function(){
alert($("#text-container div").length);
});
Explaination
First let us talk about the callback function passing, the right syntax:
$(selector).load(source,callback);
Suppose you have some function named as gg and we want to use it in place of callback
function gg(){
//some code for task 1
}
now lets use it as callback
(the wrong way)
$(selector).load(source,gg());
Note: when you write the function with parenthesis (), the function is called at the same time, so you just need to pass the identifier
(the right way)
$(selector).load(source,gg);
OR USE ANONYMOUS FUNCTION
$(selector).load(source,function(){
// some code for task 1
});
Note: Instead of defining a function only for callback and if you are not using it again it is preferred to use anonymous function
You are not doing what you think you do. You pass the result of alert() as an argument.
$("#text-container").load("1.txt",alert($("#text-container div").length));
is equivalent to :
var data = alert($("#text-container div").length); // data = 0
$("#text-container").load("1.txt", data);
What you want is to pass a function as an argument :
var callback = function() {
alert($("#text-container div").length);
}
$("#text-container").load("1.txt", callback);
or shorter :
$("#text-container").load("1.txt", function() {
alert($("#text-container div").length);
}

Only call constructor behaviour if particular function isn't called

Apologies - I have no idea to how to describe this. Example:
function OutputNumber(number) {
this.outputThisInstead = function (otherNumber) {
console.log(otherNumber);
}
console.log(number);
}
Desired usage:
new OutputNumber(1);
Console output: 1
new OutputNumber(1).outputThisInstead(2);
Console output: 2
Naturally, 1 will always be written to the console, irrespective of what else is called on the object.
I'm after this particular syntax, as well as the behaviour - attaching a function onto the initialisation. It feels impossible since the object must be constructed before any function is called on it, but is this achievable any other way?
It would be possible with a time delay (e.g., in a browser environment, setTimeout or similar) and a flag. Not desirable, but possible.
Without that, no, you can't base the action of the constructor on something that hasn't happened yet. You'd have to instead pass something into the constructor to let it know what was going on.
Browser example (again, I don't recommend this):
function OutputNumber(number) {
var handle = 0;
this.outputThisInstead = function (otherNumber) {
if (handle) {
clearTimeout(handle);
handle = 0;
}
console.log(otherNumber);
}
handle = setTimeout(function() {
console.log(number);
}, 0);
}
From your comment on the question:
This is the end of a sequence of chaining objects/functions, that I'm experimenting with. For example:
Assert.that(1).is.not(2).because('output this message if fails');
Here not(2) returns an object on which because can optionally be called. The behaviour of the object would depend on because being called.
Rather than have the behavior of an earlier function in the chain depend on a later function in the chain, I'd probably add an .end() at the end of something:
Assert.that(1).is.not(2).because('output this message if fails').end();
end would output whatever message/messages was/were stored by the previous functions. No need for black magic. Obviously this suffers from the fact that people could fail to put the .end() on, but you need some kind of trigger that it's okay to do the output, if you want the output to change based on an optional subsequent function call.
Not possible. By the time you do new OutputNumber(1) the function has already been called. A chained method will have no access to its preceding call.
It's possible to declare outputThisInstead as "static":
function OutputNumber(number) {
console.log(number);
}
OutputNumber.outputThisInstead = function (otherNumber) {
console.log(otherNumber);
}
new OutputNumber(1); //1
OutputNumber.outputThisInstead(2); //2
But if you want to create an object with the new operator the function will always log the number parameter.
You can also achieve similar behavior to the one you want with partial apply of the function (here). This is also called Currying or Schönfinkeling. The idea is that you can fill the function's parameters one after another and when the full set of parameters is available the function is being executed. You can see a currying example here.

JavaScript methods, calling method without parentheses

Hello there I have a question with the that I need some help with to increase my knowledge and understanding of JavaScript.
Within my init method please look at this particular line with the .on method where I am saying when button is clicked we’re going to refer to the contactForm object by using the this keyword and then we’re going to call the .show method.
.on( 'click', this.show );
Now the question is – if show is a method, then why aren’t we doing this, why aren’t we calling the method like this?
.on( 'click', this.show() );
Am I correct in saying it’s because we don’t want to call the show method immediately, if JavaScript came across the init method would parse all of this code, and then it would come to this section right here – this.show() - and it would immediately execute this function. But I don’t want it to do that, I only want that function to be called on the condition that the corresponding button is clicked.
When the show method is written as this.show does the absence of the parentheses stop the show method from automatically executing ?
var contactForm = {
init: function() {
$('<button></button>', {
text: 'Contact Me!'
})
.insertAfter('article:first')
.on( 'click', this.show() );
},
show: function() {
console.log('showing');
}
Sorry if I haven't been descriptive enough or accurate enough with my terminology. Any succinct and clearly explained answers would be massively appreciated.
Yes, what you are describing is correct, however, you're looking at it the wrong way.
It seems, as if you regard function names without parentheses to be some sort of special case, but in reality, it's the other way around.
It is important that you understand the concept of expressions and operators.
Operators
() is a regular operator, as is - for example, which negates a value. Operators are always applied to values: -5 negates the value 5, -(-5) negates the expression (-5) which is 5 again.
() on the other hand tries to call the expression to its left as a function: expr().
Functions are values
Functions in JavaScript are values that you can pass around just like you can wit the value 5:
var five = 5;
var returnFive = function() { return 5; };
var five2 = five;
var returnFive2 = returnFive;
alert(five2);
alert(returnFive2());
There's really nothing more to it: functions are just values, that happen to support some special magical () operator that "calls" them.
For this reason, it's perfectly valid to do any of
show()
(show)()
((show))()
etc, because (expr) simply evalutes to expr.
Evaluating expressions
Operators take one or multiple values, operate on it, and yield some other value:
4 // No operator, expression evaluates to 4
4 + 4 // This expression evaluates to 8
returnFive // No operator, expression evalutes to the function value
-5 // Unary operator, takes one value, negates it
returnFive() // call operator, executes the function, evaluates to its return value
What I hope you take away from this is, that functions aren't that special, there is no intrinsic connection between show and that pair of parentheses.
When the show method is written as this.show does the absence of the parentheses stop the show method from automatically executing ?
Yes and no – This suggests that show without the () is a special case to be handled separately, but that's not true. It's like saying "-5 is more normal than 5" and the absence of - makes something a positive number. It's the other way around, however: 5 is the "default", if you will, and -5 the special case. It's the same thing with show.
Applying this to your example
The on() function expects to be given some sort of callback, i.e. a function. If you pass show(), what are you passing? The evaluated expression show(). What is this? Whatever show() returns, of course. As such, on() has "no idea" that you have done something with show(), all it gets is some value without a connection to show().
Of course, the show() function might itself return a function, because, as we have learned, functions are just values like 5 and "foo" that can be passed around.
In that case, the on() function is still being passed a function which will be called on the corresponding event.
You are correct. When you reference a method (or any function, actually) without adding the parenthesis, the runtime will interpret that as a function reference.
So, on your example, you're effectively passing the show function to the on function, so that it can be executed later. Functions that receive other functions as parameters, or that return other functions as result are called "high-order functions"

Using setInterval in JavaScript without using an inline, anonymous function

What I'm trying to achieve is that initially data will be loaded and then be updated every ten minutes using the same function.
Consider this code:
var updateNamespace = (function() {
var object = '#updates',
load = 'loader';
return {
update: function() {
$(object).addClass(load).load('update.php', function(reponse, status, xhr) {
if (status == 'error') {
$(this).html('<li>Sorry but there was an error in loading the news & updates.</li>');
}
$(this).removeClass(load);
});
}
}
})();
setInterval(updateNamespace.update(), 600000);
I get this error:
useless setInterval call (missing quotes around argument?)
How can I fix this?
What's a better and more elegant way of writing this or using the setInterval function?
Thanks.
You need to use:
setInterval(updateNamespace.update, 600000);
(Note the removed invocation() operator.)
Your code, as written, will actually invoke updateNamespace.update when you call setInterval. Hence,
setInterval(updateNamespace.update(), 600000);
evaluates to
setInterval(undefined, 600000);
You want to pass setInterval a REFERENCE to your function, not the result of its invocation.
For some reason JavaScript wants to see quotes around the method your calling. As if it was a string. Not sure why it works like that. Matt H. said if you pass a reference that will fix the problem. But it won't work if you need to pass in an argument. So I don't know maybe JavaScript just saves the method as a string and then coverts to back to normal when it's used.
try setInterval('updateNamespace.update()', 600000);
Note the quotes around the function call

How to make Javascript timer work for variable parameter

The Javascript timer event has this basic syntax:
var t=setTimeout("javascript statement",milliseconds);
I have this function that gets called onkeyup() for some text box. I want the numeric_value_search() function to be called after a certain amount of time, which is 5 seconds in this example.
The key line is the 5th line. I have four different ways that it might be written, each of which gives the specified error:
timer=setTimeout(numeric_value_search(boundBox),5000);
ERROR: useless setTimeout call (missing quotes around argument?)
timer=setTimeout("numeric_value_search(boundBox)",5000);
ERROR: boundBox is not defined
timer=setTimeout("numeric_value_search("+boundBox+")",5000);
ERROR: missing ] after element list
timer=setTimeout(numeric_value_search("+boundBox),5000);
ERROR: data is passed nicely and there are no explicit errors but the timer doesn't work
var timer;
function chk_me(boundBox){
console.info(boundBox.id);
clearTimeout(timer);
// --- timer code here --- e.g. timer=setTimeout("numeric_value_search("+boundBox+")",5000);
}
As #kgiannakakis already said,
setTimeout(function() {
numeric_value_search(boundBox);
}, 5000);
is the way to go.
The reason is simple: When using a string argument it's like using eval() which is usually evil. When passing a function however you not only avoid putting code inside a string (which breaks syntax highlighting and might require escape orgies) but also have the possibility of using a closure to access variables in the current context without embedding them into a string (which might lead to code injection if not done properly).
Try this:
setTimeout(function() {
numeric_value_search(boundBox);
}, 5000);

Categories