jQuery.each not running in function - javascript

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.

Related

Passing function variables into a second function changes variable values

I imagine this is just a Javascript-oriented feature that I'm not aware of, but coming from a C# back-end environment means I assume a lot of JS's functionality works the same, which isn't usually the case.
With the below code, I am trying to pass the values of field and section further down into a second function defined on rows.each, however when I check in the debugged the field and section variables being used in the line if (classList.contains(field) && classList.contains(section)) have different values that what I expect them to have.
They are obviously being changed somewhere, but I am unsure for what reason.
function setValidationRowToFailure(field, section) {
var rows = $("#PeekInstruction .validation-row");
rows.each(function(field, section) {
var classList = $(this).find(".validation-row-value").attr("id");
if (classList.contains(field) && classList.contains(section)) {
$(this).removeClass("validation-row-success");
$(this).addClass("validation-row-failure");
}
})
}
To further support my point that the original values of field and section aren't being used, they are actually grey in my IDE. This is definitely a scope issue.
Your problem seems to be, that the arguments defined here:
function setValidationRowToFailure(field, section) {
are being shadowed by these ones:
rows.each(function(field, section) {
You should be fine by removing the arguments inside the function passed to .each:
rows.each(function() {
Or just rename them:
rows.each(function(index, element) {
Note, that jQuery's .each passes an index variable as the first argument: https://api.jquery.com/each/#each-function

jQuery val undefined

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).

Passing code as function argument in Javascript and that code uses variable defined in the function

I have following javascript code. I am trying to achieve a hide/display generic function on change in select form field. Lets take an example. Suppose I have a select field where values are "none", "auth", "other" and if user selects "auth" then display another form field. I may have such situation many places in the form for different select fields. Hence I have written this function below profile_field_toggler
function escapeJquerySelectorStr(str) {
if (str) {
return str.replace(/([ #;?&,.+*~\':"!^$[\]()=>|\/#])/g,'\\$1');
}
return str;
}
function profile_field_toggler (cotroller_id, reciever_id, block_code) {
parsed_controller_id = "#"+escapeJquerySelectorStr(cotroller_id);
parsed_reciever_id = "#"+escapeJquerySelectorStr(reciever_id);
selected = jQuery(parsed_controller_id + " option:selected").val();
if(block_code()) {
jQuery(parsed_reciever_id).removeClass("hide");
} else {
jQuery(parsed_reciever_id).addClass("hide");
}
}
Here I make call to the generic function i.e profile_field_toggler. Last argument of the generic function accepts conditional code, so I am passing it in the call below selected == "auth" . BUT selected has no scope in this call hence it will not work (as I want to refer the selected variable in the generic function). So how can I solve this problem? Please note, I must want to keep the condition such as selected == "auth" or selected != "xyz" or selected == "undefined" in the caller only, because they may vary.
jQuery(document).ready(function() {
profile_field_toggler("base[remove_option]", "general_passwordassword_block", function() {selected == "auth"});
});
Any idea how to solve this problem?
A closure can only access variables in its own scope, but definitely will not (and can not) have any knowledge of the scope of the function that eventually calls it.
In this particular example - perhaps "block_code" should take selected as an argument.
It looks weird, but I found the solution. It seems you can pass selected in the call from caller only and even if it is defined in the generic function, it will work. Check this out. I just added return so that condition can be evaluated. and it worked. I tested with all different conditions and it is working ..sweet, but weird.
jQuery(document).ready(function() {
profile_field_toggler("base[remove_option]", "general_passwordassword_block", function() {return(selected == "auth")});
});

Passing values from Greasemonkey sandbox into anonymous functions

This is my first question, probably very silly indeed :)
I have a selection of values in an array, returned from GM_listValues().
As I loop over the collection, I want to dynamically create buttons that call a function to delete the stored value, and reload the page.
deleteB.addEventListener("click", function() {deleteTrip(names[i]);pageSelect();}, false);
Above is the line I am using to attach the event to the button (deleteB). However, when I press the button, javascript tries to access the array of listValues (names) with the count variable (i). Naturally, this will not exist, as the loop is now done, and names is not global anyway.
What I want to know is if there is a way to copy the string value of names[i] while I am creating the function in the button, so as to not need a reference to names[i] in the code.
I know this is probably a really simple answer, but its got me stumped, this is some of my first work with javascript.
Thanks in advance.
Use a closure to remember the value;
function createDeleteFunc(name) {
return function(){deleteTrip(name);pageSelect();}
}
for() {
...
deleteB.addEventListener("click", createDeleteFunc(names[i]), false);
...
}
The problem is that all functions you create reference the same i variable. When they are called, they try to delete names[i], but i is now equal to names.length so it doesn't work.
The solution is to make a separate reference to names[i] for each function. This is usually done with a closure (à-la Paul's answer)

How to programmatically change an inputs onblur?

I am trying to change the value of the onblur attribute of a text input after the page has finished loading.
When I do the following, it simply fires the function:
ip.onblur = stopCalcUpInt(this,10);
When I do the following, I have success:
ip.onblur = function onblur(event){stopCalcUpInt(this,10);}
Unfortunately, the whole point of this is to be able to dynamically set the second parameter for stopCalcUpInt(). If I hard code a value for it... it works fine... but any attempts to pass varibles to this fails... instead of putting the value of the variable as the second param it just puts the plain text of the variable name itself. Here is ideally what I am TRYING to do:
ip.onblur = function onblur(event){stopCalcUpInt(this,this.value);}
In this example, when I alert the ip.onblur I get:
It depends what this is intended to refer to. In an event handler this refers to the element on which the event is being handled. If that's what you want then your code looks good as written; this will point to ip.
If you intend this to refer to the this from outside the event handler and not ip then try this:
var self = this;
ip.onblur = function(event) { stopCalcUpInt(self, self.value); };
The answer to getting this to work was super easy, yet not overly obvious. Instead of:
ip.onblur = function onblur(event){stopCalcUpInt(this,this.value);}
I did this:
ip.setAttribute('onblur','stopCalcUpInt(this,\'' + ip.value + '\');');
Works perfectly... no more banging my head against the wall! Yay!
ip.onblur = function() {stopCalcUpInt(this,this.value);}
ip.onblur is an event handler... i.e. it's a function
Now, when you alert a function, FF will show you the source code for that function (if it's user defined).
That is why you're seeing the plain text of the variable name.
For an event handler, this is the element that is currently handling the event. So, if you're setting the onblur handler of an input box, you will have access to the contents of that input box.
The code sample that you provided:
ip.onblur = function onblur(event){stopCalcUpInt(this,this.value);}
should work correctly. Try
ip.onblur = function onblur(event){alert(this.value); stopCalcUpInt(this,this.value);}
if you want to be sure
Is stopCalcUpInt expecting a number in the second parameter? The value attribute will return a String, while in your hardcoded example you're passing a number type. Try this:
ip.onblur = function onblur(event){stopCalcUpInt(this,this.value * 1);}
As explained in QuirksMode:
Since multiplying assumes numbers,
JavaScript makes the string a number,
if possible.

Categories