I wrote a function named search that I expected to be called when the link was clicked, as the code snippet below shows:
<script>
function search() {
console.log('Searching');
}
</script>
Click here
However, the code does not work as I expected, which causes this error (in Chrome) when the link is clicked:
Uncaught TypeError: search is not a function
I tried logging search to see why the error was thrown:
Click here
<script>
function search() {
console.log('Searching');
}
</script>
Click here
This time, the console logged an empty string each time the link is clicked. What puzzles me is that search is actually defined somewhere else as an empty string, making my function definition useless.
So I want to know what happens when a click event is triggered, and when is search here defined?
It turns out search actually is referring to to the a element's search property which is a property that controls search parameters, which happens to be an empty string in this case. This is because with an HTMLAnchorElement, it is special as it is used to create hyperlinks and navigate to other addresses, and thus the search property is used to control parameters of searches by hyperlinks (similar to that of the Location) object. Setting the search property of an anchor element will then in turn set the global Location instance's window.location.search. This creates a naming conflict and because an empty string is not a function the error is thrown.
Use a different name for the function to remove this conflict. Note that if you don't use an a, you'll see it work just fine:
<script>
function search() {
alert("foo");
}
</script>
<div onclick="search();">Click me!</div>
Li357's answer explains most of what's going on, but to add a point, the reason that
<a onclick="search();">Click me!</div>
results in search referring to the anchor's search property is that inline handlers have an implicit with(this) surrounding them. To the interpreter, the above looks a bit like:
<a onclick="
with(this) {
search();
}
">Click me!</div>
And search is a property of HTMLAnchorElement.prototype, so that property gets found first, before the interpreter gets to looking on window for the property name.
It's quite unintuitive. Best to avoid inline handlers, and to avoid using with as well. You could add the event listener properly using Javascript to solve the problem too:
function search() {
console.log('Searching');
}
document.querySelector('a').addEventListener('click', search);
Click here
Change the name of the function. Just tried your code and it worked once I changed the name of the function.
<body>
<script type="text/javascript">
function test() {
console.log('Searching');
}
</script>
Click here
Related
download
<script type="text/javascript">
function download() {
alert("hello");
}
</script>
When I click the link, I don't see an alert. Instead it says the function doesn't exist. Why?
When I rename download to downloadx, it still doesn't work, so it's not the name of my function that's a problem.
First of all as #gmo said your code will never work outside JSFiddle because of the name of the function.
Read More about it HERE (Can't use “download” as a function name in javascript)
From now on i'll use downloadx as the function's name
Instead another problem caused by JSFiddle makes your code non functioning even if you use downloadx.
simple-example-doesnt-work-on-jsfiddle
JSfiddle wrap your code inside a window.onload function, so the download function is outside of the scope.
//<![CDATA[
window.onload=function(){
function downloadx() {
alert("hello");
}
}//]]>
SOLUTION 1 JSFiddle
you should declare it directly on window
window.downloadx = function() {
alert("hello");
}
SOLUTION 2 JSFiddle
Select No wrap - in <head>
On the left column in JSFiddle
NB
In any case you should use another name for the function, this is the reason why it doesn't work outside JSFiddle.
I still think it's a duplicate question from here: Can't use "download" as a function name in javascript
And related exclusive on the function name in a tag.
...<a> elements have a download attribute in HTML5 as explained
here...
Maybe a workaround is possible, but definitely not recommendable to mess with browser native functions.
But.. if you still think that it's not.. please try this:
(no hacks needed)
function download() {
alert("hello");
}
function downloadx() {
alert("hello");
}
download <-- not working
<br />
downloadx <-- works
<br />
<span onClick="download();">download</span> <-- works
The last one use download as function name and also work, why?
Because it's not an <a> tag.
I've got my fiddle here, but I can't understand why it's not calling my function on the 'onmouseout' event.
http://jsfiddle.net/foreyez/Xf6LW/
any ideas?
Works fine, you just needed to put the function in the head (or body after the element is in the DOM) of the document.
jsFiddle example
It's because the functions you create in the JavaScript panel are not global when you have the onLoad option selected. Your JavaScript gets wrapped in a function.
If you do want them to be global you have to either do what j08961 suggested, by changing that dropdown to say no wrap (body or head) will work
The best solution would be to not set your event handlers from HTML, that's bad practice anyway, then you're not relying on global functions or mixing HTML and JS.
<div id="myDiv">
</div>
document.getElementById('myDiv').onmousemove = function() {
alert('here');
}
Side note: you should have noticed the error in the console saying that myFunc is undefined or something like it.
I think it's cause for jsfiddle, it declares all the javascript AFTER the HTML. The HTML is going to run and look for a myFunc and not find it. Then it's going to load the JS and it won't even run it.
Here you can see the changes : jsfiddle.
make myFunc as a global function;
I searched my code using firebug and got following generated code.
window.addEvent('load', function() {
//window.myFunc makes myFunc as a global function
// It can be accessed from any were inside current window.
window.myFunc = function myFunc(x)
{
alert('yo');
}
// function below is not available gloably.
function myFunct1(){
alert('yo1');
}
});
see jsfiddle
In my HTML-head i have this script included:
<script id="mode" type="text/javascript" src="article.js"></script>
With a button click I'd like to change the source of the script to customers.js so that it then looks like this:
<script id="mode" type="text/javascript" src="customers.js"></script>
The point is that I don't want the article.js to be included in my page then anymore, so I can't just use .append().
So, click on the article button -> only article.js included, click on the customers button -> only customers.js included.
I tried to solve this with jQuery this way, but I doesn' seem to work...:
$("#btArticle").click(function(){
$("#mode").attr("src","article.js");
});
$("#btCustomers").click(function(){
$("#mode").attr("src","customers.js");
});
Do you know where my mistake is?
Update: There are methods with the same name in customers.js and article.js. So there's a onSave() method in both of them and when I clicked the customer button before, I want the onSave() method of customers.js to be executed, not the one in articles.js.
The point is that I don't want the article.js to be included in my page then anymore, so I can't just use .append().
Once the script has been downloaded and evaluated, anything it leaves lying around will remain unless explicitly removed; they're not linked to the script element itself and removing it won't have any effect on them.
The only way to get rid of the stuff article.js leaves lying around is to remove or overwrite each and every thing it creates and keeps.
Concrete example:
// article.js
var foo = "bar";
jQuery(function($) {
$(".stuff").click(function() {
alert("You clicked stuff!");
});
});
If the article.js listed above is processed, you can remove the script element that loaded it, and that will have no effect on the foo global variable or the event handler that it hooked up.
If you want to have scripts that you can unload, have them use the module pattern with a single global symbol they add by assigning to a property on window, e.g.:
// article.js
window.articleScript = (function() {
var foo = "bar";
jQuery(function($) {
$(".stuff").bind("click.article", function() {
alert("You clicked stuff!");
});
});
function remove() {
$(".stuff").unbind("click.article");
try {
delete window.articleScript;
}
catch (e) { // Early IEs throw incorrectly on the above
window.articleScript = undefined;
}
}
return {
remove: remove
};
})();
You can then remove it by doing this:
articleScript.remove();
Re your comment on the question:
Maybe I should've mentioned that there are methods in both files with the same name.
If you have global function declarations in customers.js that use the same name as global function declarations in articles.js, when you load customers.js, it will replace those functions.
So if you have this in articles.js:
function foo() {
alert("Articles!");
}
...and this in customers.js:
function foo() {
alert("Customers!");
}
And you have a button:
<input type="button" onclick="foo();" value="Foo">
When you've loaded just articles.js and not customers.js, clicking that button gives you "Articles!". If you then load customers.js, clicking the button will give you "Customers!".
That works because the event handler calls foo(), but the event handler itself is not foo. The onclick attribute creates a hidden event handler for you. The equivalent jQuery would be:
$("input[type='button'][value='Foo']").click(function() {
foo();
});
Note that just doing .click(foo) will do something very different: It will hook up the function that foo points to at that moment as the event handler. Even if you change what foo points to later (by loading customers.js), that won't change the fact that the old function is hooked up as a handler.
FWIW, from the question and your comments, I think I'd recommend sitting back and reviewing your strategy for this page/app. All of this swapping of code in and out and such seems like a design problem.
You are not actually loading and running the respective scripts, you are just changing the source for that tag. Use .getScript() to load and run the appropriate JavaScript file:
http://api.jquery.com/jQuery.getScript/
First I am using the jQuery colorbox plugin that is working fine so far but then I want to close the colorbox using a button. Unfortunately I can't just trigger the click event on that button by selecting its ID using jQuery, instead of that the button must call a javascript function called closepan() (this behavior is unfortunately mandatory for me).
I tried to create the function
closepan() {
$.colorbox.close();
}
first case : inside the
$(document).ready(function(){...});
but then I got the error closepan is undefined.
second case : before the
$(document).ready(function(){...});
but then it's the colorbox method that is undefined!
I gave up after gazillion hours of fiddling with several solutions I've found all around stackoverflow.com regarding this topic! I can't figure out how to make this working!
In other words, how to create a function named closepan() that can execute $.colorbox.close(); while being available globally for my button?
No matter where you create a variable or function if you create it on window it will be available globally.
window.closepan = function() {
// hello there
}
function closepan() {
if($.colorbox) {
$.colorbox.close();
}
}
However, at the point where someone clicks your button all external scripts should have been loaded so that check shouldn't be necessary...
Don't forget to put the keyword function in front of your declaration...
function closepan() {
$.colorbox.close();
}
Working JSFiddle
I have this html...
<a onclick="search.analysisSelect('2');" href="javascript:void(0);">A Product</a>
...And whenever I click that link in the browser (IE, FF, and Chrome), it fails. It tells me that the function does not exist. However, if I type that exact function call into the console of firebug, it runs fine. So the function does exist.
Exact error message: "search.analysisSelect is not a function"
I have recently changed the "search" object name to "searchTab" and the onclick works fine.
Why is the onclick failing for the search object? I am baffled...
Here is the search object. This is stored in a separate js file loaded when the page loads.
var search = {
analysisSelect: function(pub) {
$("#tabs").tabs("select", "#analysis");
analysisGrid.refreshSlickGrid(pub, '0', '1', '0');
}
};
Oh, I forgot to mention that I also have an init() funciton defined in the search object, which is called on an onclick event for another html element, and that fires off with no issues. Wtf...
Where did you define search.analysisSelect()? It should be defined before the anchor tag.
generally using inline javascripts is not a good idea, consider using an external javascript file and bind that function to the anchor onclick event like this:
window.onload = function() { // ensures that the document is loaded before finding the anchor element
// assign an Id to the anchor tag like this: <a id="idOfAnchorTag" href="#">A Product</a>
var elem = getElementById('idOfAnchorTag');
elem.onclick = function() {
search.analysisSelect('2');
}
}
There is some strange javascript voodoo going on in the inline event handler. search is not being resolved to window.search, it is hitting something else and I don't know what it is.
See http://jsfiddle.net/yPhZ8/
However, I can tell you how to fix it. Use window.search instead.
<a onclick="window.search.analysisSelect('2');" href="javascript:void(0);">A Product</a>
See: http://jsfiddle.net/yPhZ8/1/
I just had this exact problem today. Turns out, you can't have an HTML element with an ID the same as the function.
Don't ask me why, I'd just say it has something to do with extremely lazy parsing.
My Example:
<dd style="margin-left: 2px;"><input type="button" name="info[add_benefit]" id="add_benefit" value="{L_ADD_BENEFIT}" class="button2"
style="width: 100%;" onclick="add_benefit();" /> </dd>
The onclick method would return an error saying that the function didn't exist. Apparently it thought the button itself was the function, but the button was a button, hence the error.