I'm trying to get the value of an input element on a html page using jQuery. I can get the element value using .val() if I call it from a script tag in the html page. However, when I call the same function from a seperate js file it returns undefined.
Anyone have anyidea what is going on here?
index.html
$(document).ready(function() {
console.log($("#amount").val()); // This works
externalFunction(); // This returns undefined
});
file.js
function externalFunction() {
console.log($("#amount").val());
}
EDIT
I should clarify that the div which contains the input element is hidden.
style="display: none;"
Would this make a difference?
When I call the same function from a seperate js file it returns
undefined.
If you mean the function returns undefined.
This is the correct behaviour because you returned nothing.
You have to use return statement.
function externalFunction() {
return $("#amount").val();
}
let value=externalFunction();
console.log(value);
if function is not found in your actual file.
Use export statement or require in order to make function visible in other file also.
As described in the question, that's simply not possible.
Instead, I suspect that you aren't calling externalFunction at the same time you're calling the console.log. Instead, I suspect you're calling it earlier, before the input exists.
There are only two reasons val ever returns undefined:
You call it on an empty jQuery object (because nothing matched the selector, for instance, because you called the function too soon).
You call it on a jQuery object whose first element is not an input or select (and thus has no value property).
Related
When dynamically creating an element of type select, there are two problems when setting the onclick method:
It is impossible to simply set the onclick with element.onclick="updateInput(this.articleIndex)";
This results in a final HTML tag where no onclick is shown at all.
When set by e.setAttribute("onclick","updateInput(this.articleIndex)");, it does appear in the final HTML. And the updateInput method does get called.
However the functionality seems to be broken, as the argument always evaluates to undefined
Here a simple example of my problems:
var selectElem = document.createElement("select");
selElem.id="articleSelector_"+this.articleIndex;
console.log("the index of the article is " + this.articleIndex);
selElem.setAttribute("onclick","updateInput(this.articleIndex);");
//selElem.onclick="updateInput(this.articleIndex)"; //this does not work
The log shows the correct number. Inside the updateInput method, the argument is of value undefined instead of the number previously shown in the log.
Try attaching handlers with pure Javascript, and not with HTML, without onclick = "... (which is as bad as eval).
The this in your script refers to the calling context of the function - what is it?
You might want:
element.addEventListener('click', () => {
updateInput(this.articleIndex);
});
(arrow functions retain the this of their surrounding scope)
it is impossible to simply set the onclick with element.onclick="updateInput(this.articleIndex)";
What that code does is it assigns the string "updateInput(this.articleIndex)" to the onclick which makes no sense and certainly not what you want.
Even if you remove the quotes:
element.onclick = updateInput(this.articleIndex);
It is still incorrect because it assigns the result of the updateInput() function to the onclick which is again not what you want.
You need to assign a function name to the onclick like this:
element.onclick = updateInput;
However, this doesn't allow you to pass a parameter as you wish. To do so, you need to use an anonymous function:
element.onclick = function() {
updateInput(this.articleIndex)
};
When set by e.setAttribute("onclick","updateInput(this.articleIndex)");, it does appear in the final HTML. And the updateInput method does get called.
This works because it sets the attribute onclick and it is a string type, so everything is correct. It is equivalent to using the anonymous function above. The only difference is this, which in this case refers to the element itself, while in the above code it depends on the context that the code appears in. That's why in this case the argument always evaluates to undefined because the select element doesn't have an articleIndex property.
The problem is the value of the context this when that element is clicked, the context this is not available anymore at that moment.
You have two ways to solve this problem:
You can use the function addEventListener to bind the event click, and bind the function/handler with the desired context this:
The function bind binds a specific context to a function.
selElem.addEventListener('click', updateInput.bind(this));
function updateInput() {
console.log(this.articleIndex);
}
As you need a specific value, you can use data attributes. That way, you don't need to worry about the context this.
selElem.dataset.articleIndex = this.articleIndex;
selElem.addEventListener('click', function() {
updateInput(this.dataset.articleIndex); // Here you can get that value.
});
I'm working on a project where some form elements depend on another form input to have a certain value, or possibly multiple elements with specific values before that input is shown.
The idea is that when the form is generated, the wrapping div for each input has a data-depends-on attribute with a comma-separated list of each field that it depends on to be shown, and the values for each that it's expecting to be shown.
I almost have the front-end / JavaScript code down to do the lifting, but for some reason my jQuery.each() loop in a JavaScript function isn't running even though I've confirmed the array I'm trying to loop through a. has content, and b. that the functioning is actually being called when it is expected to do so.
First, I have the actual function call (which is called whenever a dependency input is changed):
checkShowField(keyed_depends, current_vals, targeted_element);
And then the function checkShowField() definition:
function checkShowField(keyed_dependencies, current_values, targeted_element)
{
var hide_field = null;
jQuery.each(keyed_dependencies, function(key, value)
{
if (value != current_values[key] && hide_field == null)
hide_field = false;
});
if (hide_field == null)
$(targeted_element).slideDown();
else
$(targeted_element).slideUp();
}
Also please note that the function call is placed in the proper place, and is actually being called. I just added the code on here to show everyone context of how the function is being called. The function call is wrapped in $(document).ready(function() {...}.
So as you can see, in the function "checkShowField", I have a jQuery.each loop that should be looping through keyed_dependencies array, but in actuality, the loop isn't even running once. Thoughts?
You can check, if keyed_dependencies in argument list has a property length. If so, jQuery assumes an array and might actually fail to run you loop.
If that is the case, try using vanilla JS:
for (var key in keyed_dependencies) {...}
Hope that helps.
It looks like the keyed_dependencies is not really what you think it is. Try adding debugger; statements before the .each line and maybe in the function as well. Then use inspector/debugger to review the data in the variables.
I have to set a specific value to an element if the element is exists.
var a = jQuery("#abc");
if(a) {
a.val("something");
}
For this, I've to check a.length to check the element is exits.
What happen if I directly set the value without checking the element is present or not?
Because, If I do the following
jQuery("#abc").val("dfd");
I don't get any error in chrome when the element is not present. So, can I continue to use like this?
or
any workaround?
Help appreciated!
What happen if I directly set the value without checking the element is present or not?
Nothing. Calling jQuery methods on an empty jQuery object (set) doesn't cause a problem, it just does nothing. This is one of the great things about the set-based concept used in jQuery. The equivalent DOM code (document.getElementById("abc").value = "something";) would throw an error, but the jQuery version doesn't.
Specifically, if the jQuery set is empty:
Calling setter methods (like your val call) becomes a no-op.
Calling getter methods — for instance, var x = $("#foo").val(); — returns the value undefined.
Calling traversal methods — for instance, var divs = $("#foo).find("div"); — gives you a new empty set.
You only need to check (using if (a.length) as you said, or if (a[0])) if you actually care.
jQuery("#abc").val("dfd");
I don't get any error in chrome when the element is not present. So, can I continue to use like this?
Yup.
jQuery's val() method simply sets (or gets) the value of each matching element. If there are no matching element, there will be no value to set (or get). You don't need to check if the element exists first.
From jQuery's val() documentation:
Description: Set the value of each element in the set of matched elements.
If there are no matched elements, nothing will happen.
Try with -
jQuery("#abc").length > 0
Yes, you can safely continue. JQuery just executes a function on all elements found by the selector - if there are none, it does nothing. There's no error.
I am learning to program in Javascript. I have created a jsfiddle here - http://jsfiddle.net/vvMRX/1/
function turnRed(node,f){
setTimeout(f,2000,[node]);
}
(function pageLoaded(){
turnRed(document.body,function(node){
alert(node);node.style.backgroundColor = '#ff0000';
});
})();
I am trying to use a setTimeout call on a function to change the body background color. I pass document.body as a node. In the callback, I change the node.style.backgroundColor but it does not work. Interestingly enough, using document.body.style.backgroundColor directly works. If I put an alert(node), it correctly identifies it as html bodyelement.
What am I missing here?
Appreciate responses.
Here's the following error that's being thrown in your JS:
Uncaught TypeError: Cannot set property 'backgroundColor' of undefined
The reason for this is because in your setTimeout, you're passing node in an array. However, in your callback, you're accessing the node directly. Two ways of addressing this are:
Update your callback to access the node within the array.
(function pageLoaded(){
turnRed( document.body, function(node){
alert(node);
// Updated code below
node[0].style.backgroundColor = '#ff0000';
});
})();
The other way would be to update your setTimeout and pass node directly.
function turnRed(node,f){
setTimeout(f,2000,node);
}
Here's an updated fiddle: http://jsfiddle.net/vvMRX/3/
You mentioned that using document.body.style.backgroundColor worked - which makes sense - since document.body will point to the element that contains the content. For most pages, this is almost always the <body> element. However, for frameset documents, this would return the outer frame. (w3.org reference)
Finally, regarding the alert - what's up with that, right? You call alert(node), and it displays [object HTMLBodyElement], which means you were passing the correct element, right? (At least, that's what I would think too!)
What's actually happening is that alert is alerting the value of your array.
Here's a fiddle demonstrating that: http://jsfiddle.net/4Lf3J/
You should see three alerts.
In the first alert, I've updated the original alert to call node.constructor. Object.prototype.constructor will return a reference to the object that created the instance (MDN reference).
In this case, we'll see
function Array() { [native code] }
This hopefully will re-enforce the idea that you're passing an array.
The second alert is actually calling alert(document.body.constructor), which is what we EXPECTED to see originally. In this case, we see:
function HTMLBodyElement() { [native code] }
Finally, a third alert shows the values 1,2,3,4,5, which is just an alert of a simple array with those values (again, re-enforcing the idea that alerts will alert the value of an array - which is why you thought the alert was correct).
Hopefully this helps as you continuing learning JavaScript!
In your function turnRed you are passing node in an array. Try this:
function turnRed(node,f){
setTimeout(f,2000,node);
}
I tried this in the fiddle it works.
In this case i guess that you should use document.bgColor property directly
You can obtain more information and code samples here:
http://www.javascripter.net/faq/backgrou.htm
http://www.webcodingtech.com/javascript/change-background-color.php
This question already has answers here:
Why does jQuery or a DOM method such as getElementById not find the element?
(6 answers)
Closed 3 years ago.
Althought I pushed a parameter to getElementById I wonder from where is this 'is null' error coming from?
TypeError: document.getElementById(...) is null
[Break On This Error]
document.getElementById(elmId).innerHTML = value;
Line 75
In addition to this i wonder why title and time did not show unless I click one of these playlist pictures?
Make sure the script is placed in the bottom of the BODY element of the document you're trying to manipulate, not in the HEAD element or placed before any of the elements you want to "get".
It does not matter if you import the script or if it's inline, the important thing is the placing. You don't have to put the command inside a function either; while it's good practice you can just call it directly, it works just fine.
All these results in null:
document.getElementById('volume');
document.getElementById('bytesLoaded');
document.getElementById('startBytes');
document.getElementById('bytesTotal');
You need to do a null check in updateHTML like this:
function updateHTML(elmId, value) {
var elem = document.getElementById(elmId);
if(typeof elem !== 'undefined' && elem !== null) {
elem.innerHTML = value;
}
}
It means that the element with the id passed to getElementById() does not exist.
You can use JQuery to ensure that all elements of the documents are ready before it starts the client side scripting
$(document).ready(
function()
{
document.getElementById(elmId).innerHTML = value;
}
);
I got the same error. In my case I had multiple div with same id in a page. I renamed the another id of the div used and fixed the issue.
So confirm whether the element:
exists with id
doesn't have duplicate with id
confirm whether the script is called
I have same problem. It just the javascript's script loads too fast--before the HTML's element loaded. So the browser returning null, since the browser can't find where is the element you like to manipulate.
In your code, you can find this function:
// Update a particular HTML element with a new value
function updateHTML(elmId, value) {
document.getElementById(elmId).innerHTML = value;
}
Later on, you call this function with several params:
updateHTML("videoCurrentTime", secondsToHms(ytplayer.getCurrentTime())+' /');
updateHTML("videoDuration", secondsToHms(ytplayer.getDuration()));
updateHTML("bytesTotal", ytplayer.getVideoBytesTotal());
updateHTML("startBytes", ytplayer.getVideoStartBytes());
updateHTML("bytesLoaded", ytplayer.getVideoBytesLoaded());
updateHTML("volume", ytplayer.getVolume());
The first param is used for the "getElementById", but the elements with ID "bytesTotal", "startBytes", "bytesLoaded" and "volume" don't exist. You'll need to create them, since they'll return null.
Found similar problem within student's work, script element was put after closing body tag, so, obviously, JavaScript could not find any HTML element.
But, there was one more serious error: there was a reference to an external javascript file with some code, which removed all contents of a certain HTML element before inserting new content. After commenting out this reference, everything worked properly.
So, sometimes the error might be that some previously called Javascript changed content or even DOM, so calling for instance getElementById later doesn't make sense, since that element was removed.