Cannot break nested functions in separate functions in Javascript/jQuery - javascript

I am trying to add on input method to several dom elements with same class. It is working when the on input function is nested inside the each function. When I try to separate them into two separate functions it doesnt work.
This is the working version
$('.textField').each(function(index, element){
var currentField = $(this);
var currentFieldCheckboxId = "#" + currentField.attr('name')+"Checked1";
// Look for changes in the value
currentField.on('input', function(event){
// If value is NOT empty
if ($.trim(currentField.val()) != '' ) {
// if text fields are unchecked
if (!$(currentFieldCheckboxId).is(":checked")){
$(currentFieldCheckboxId).click();
}
} else {
// If text fields are empty
if ($(currentFieldCheckboxId).is(":checked")){
$(currentFieldCheckboxId).click();
}
}
});
});
NOT working version. It doesnt go into the not empty condition even though .textField isnt empty.
$('.textField').each(function(index, element){
var currentField = $(this);
var currentFieldCheckboxId = "#" + currentField.attr('name')+"Checked1";
// Look for changes in the value
currentField.on('input',qwer(currentFieldCheckboxId,currentField,event));
});
function qwer(currentFieldCheckboxId,currentField,event){
// If value is NOT empty
if ($.trim(currentField.val()) != '' ) {
console.log("not empty field " + currentField.val());
// if text fields are unchecked
if (!$(currentFieldCheckboxId).is(":checked")){
$(currentFieldCheckboxId).click();
}
} else {
console.log("Empty field " + currentField.val());
// If text fields are empty
if ($(currentFieldCheckboxId).is(":checked")){
$(currentFieldCheckboxId).click();
}
}
}

What you want to do is pass a function (a function object, qwer in your case) to another function (the on function). What you are actually doing is calling that function(qwer), and passing the result to another function (and the result is actually undefined, since you return nothing from qwer).
qwer <- that is the function object
qwer(currentFieldCheckboxId,currentField,event) <- that is the result of the function being called
You need to create another function to be called instead, if you want to pass some parameters to qwer.
Try this:
currentField.on('input', function(event) {
qwer(currentFieldCheckboxId, currentField, event);
});

Related

How to attach multiple data to a jquery object using .data() in a plugin

I have two plugins
$.fn.expect = function (expectation) {
return this.each(function () {
$(this).data('expectation', expectation);
});
}
$.fn.isExpected = function () {
return $(this).data('expectation').call(this);
}
The first is supposed to attach a series of conditions
Example: $input == 2, $input.ToUpperCase() == $input, ($input / 2) == 1)
The second allows me to call the data attached to the first plugin and evaluate the conditionals whenever needed.
The problem is that my code in its current state only allows me to attach a single expectation per jquery object
Example:
$(input1).expect("$(this).val() == 2");
$(input1).expect("$(this).val() == 4");
$(input1).val(2);
$(input1).isExpected(); //this returns false as it now expects 4
Also, I need to be able to attach conditions at different points in the code, so that rules out writing something like
$(input1).expect("$(this).val() == 2 || $(this).val() == 4");
Thanks in advance for any suggestions
You can store an array, an object or whatever you want in the object data storage. So you could initialize an array, store it in the data storage, and then in the next call, just push the desired values to the data storage (or better, push multiple values at once):
$.fn.expect = function (expectation) {
// get all the arguments as an array
var expectations = Array.prototype.slice.apply(arguments);
// for each matched element
return this.each(function () {
// gets the current expectations or set an empty array for the expectations
var $this = $(this),
data = $this.data('expectations') || [];
// add all the passed expectations to the expectations array
data = data.concat(expectations);
// save the expectations
$this.data('expectations', data);
});
};
$.fn.isExpected = function () {
// reference to the current object
var self = this;
// use Array.prototype.every to test every expectation
return $(this).data('expectations').every(function(expected) {
// Apply the eval in a specific context using an intermediate function
return (function() { return eval(expected); }).apply(self);
});
}
Then you could ads one or several expectations at once:
$(input1).expect("$(this).val() == 2", "$(this).val() == 4");
Check my working example:
$.fn.expect = function (expectation) {
// get all the arguments as an array
var expectations = Array.prototype.slice.apply(arguments);
// for each matched element
return this.each(function () {
// gets the current expectations or set an empty array for the expectations
var $this = $(this),
data = $this.data('expectations') || [];
// add all the passed expectations to the expectations array
data = data.concat(expectations);
// save the expectations
$this.data('expectations', data);
});
};
$.fn.isExpected = function () {
// reference to the current object
var self = this;
// use Array.prototype.every to test every expectation
return $(this).data('expectations').every(function(expected) {
// Apply the eval in a specific context using an intermediate function
return (function() { return eval(expected); }).apply(self);
});
}
// Sets the input
var input = $('#test');
// Add the expectations to the field, multiple at once, or multiple or single at different instances
input.expect("$(this).val() > 0", "$(this).val() > 10");
input.expect("$(this).val() == 15");
// Text button
$('#button').click(function() {
console.log(input.isExpected());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="test">
<input type="button" id="button" value="Test it!">
Hope it helps.

Only execute function if value is NOT empty [duplicate]

This question already has answers here:
How to check if a value is not null and not empty string in JS
(11 answers)
Closed 4 years ago.
I have the following html, which is part of a webform:
<input type="hidden" name="userID" id="control_COLUMN43" value="%%userID%%">
The value of this field is dynamically generated by a database. It's possible that the value of this field is empty.
Next to this, I created a function which sends the value of this field (via Ajax) to another database, upon a submit of the webform.
What I want to do now is: only execute this function if the value of the field "userID" is NOT empty. If it's empty, I don't want this function to be executed.
So I assume it will be something like this, but I'm struggling to find the correct way to do this:
if (#control_COLUMN43 !=== "") //this is the id of the field
{
function SendAjax()
{
if
{
//code
}
else
{
//code
}
}
}
else
{
//don't execute function
}
Or the other way around I guess?
Can anybody help me with this?
Thanks in advance!
Use like this
// Also u can add null check
if(data !== '') {
// do something
}
If, however you just want to make sure, that a code will run only for "reasonable" values, then you can, as others have stated already, write:
if (data) {
// do something
}
Since, in javascript, both null values, and empty strings, equals to false (i.e. null == false).
The difference between those 2 parts of code is that, for the first one, every value that is not specifically an empty string, will enter the if. But, on the second one, every true-ish value will enter the if: false, 0, null, undefined and empty strings, would not.
You should not declare functions inside the conditions. If you do then at the time of execution if the condition is not met, function will not be available which may lead to errors. Hence, you should place the condition inside the function.
You can modify your condition to following
function SendAjax() {
if (document.getEelementById("control_COLUMN43").value) {
//code
}
}
You can access the value of the input by using getElementById(id).value
and declare your function outside the if block like:
function SendAjax()
{
if
{
//code
}
else
{
//code
}
}
if (document.getElementById('txt_name').value) //this is the id of the field
{
SendAjax()
}
else
{
//don't execute function
}
The if statement you need, without JQuery, should be like this:
if (document.getElementById("control_COLUMN43").value !=== "") {
// .. commands
}
First get your hidden input value using document.getElementById() and then check if it is null like following:
var userId = document.getElementById("control_COLUMN43");
if (userId) //this is the id of the field
{
SendAjax()
}
else
{
alert("UserId is null);
}
function SendAjax()
{
if
{
//code
}
else
{
//code
}
}
In if condition check $("#control_COLUMN43").val()
It can be null or '' so you can apply condition accordingly.
You can check empty value like this
function isEmpty(str) {
return (!str || 0 === str.length);
}
var val = document.getElementById('control_COLUMN43').value;
var col = isEmpty(val);
if (col) {
function SendAjax(){
if
{
//code
}
else
{
//code
}
}
}
else
{
//don't execute function
}
There are several issues at once:
You are mixing up declaring a function with calling it.
To get the value from a control, use document.getElementById("...").value
The proper notation for not === is !==.
This is how it goes:
// Declare the function
function SendAjax()
{
if
{
//code
}
else
{
//code
}
}
// Get value
var value = document.getElementById("control_COLUMN43").value;
// Call the function conditionally
if (value !== "")
{
SendAjax();
}
The code you write in if condition is not correct ID value must be get like:
if(document.getElementById("control_COLUMN43").value != ''){
//Your code here
}
Basically you have to check value property of the input element. Using dom selectors first you can select a element using id then you can access value attribute for element. If it's not null or undefined or just empty spaces then you can call your function
function handleClick(){
// Extract value from input element
let val = document.getElementById('input').value;
// Check value is empty or not
if(val){
// If not empty
console.log('Value is : ' + val);
}
else{
// If empty
console.log('Empty input');
}
}
<input id="input" type="text">
<button onclick="handleClick()">SUBMIT</button>
// get the contents of the form element
var control_COLUMN43 = document.getElementById("control_COLUMN43").value;
// process the data
if( control_COLUMN43 != "" ) {......

How to access the first element of the checkbox array without using each?

I have a Jquery event that will collect the list of selected checkboxes and I am currently experimenting their behaviours by trying to access them 1 by 1.
$('#sub').click(function () {
var cb = $("input[type='checkbox']:checked");
var count = cb.length;
alert(cb[0].prop('checked'));
if (count == 0) {
alert('No subjects selected');
return false;
} else {
return confirm(count + " row(s) selected, proceed?");
}
});
Accessing cb directly won't work for some reason.
I need to do something like this :
cb.each(function (i) {
alert($(this).prop('checked'));
});
But this will require me to loop through all of them when I only need the first element of the array, to see if it's true.
Are there any methods and can someone tell me why my first approach didn't work? I tried using for loop but no luck.
What you are trying to do is to check whether at least one item is selected, since cb has only checked items you can just check whether the set has atleast one item like
$('#sub').click(function () {
var cb = $("input[type='checkbox']:checked");
if (!cb.length) {
alert('No subjects selected');
return false;
} else {
return confirm(count + " row(s) selected, proceed?");
}
You can use eq()
alert(cb.eq(0).prop('checked'));
or cb[0] will return dom object
alert(cb[0].checked);
Ref : https://learn.jquery.com/using-jquery-core/faq/how-do-i-pull-a-native-dom-element-from-a-jquery-object/
This:
var cb = $("input[type='checkbox']:checked");
Doesn't return a single element, it potentially returns many.
This will target the first checked checkbox:
var cb = $("input[type='checkbox']:checked:first");
This will target the first checkbox regardless of state:
var cb = $("input[type='checkbox']:first");

jquery each as 'named function'

I want to use this syntax
var x = function() {
//do something here
}
on an each function
$("#firstname, #surname").each(function( index ) {
if ($(this).val() == '') {
errors += 1;
}
});
Is this possible, and what is this called (I called it 'named functions' is this right)?
EDIT
So something like this
var errors = $("#firstname, #surname").each(function( index ) {
if ($(this).val() == '') {
errors += 1;
}
return errors;
});
console.log("you have".errors()."errors");
When a function is used like this:
$(...).each(function() {
...
});
it is called an anonymous function or lambda function.
I have never heard the term "named function" but I guess you could call it like that, when you assign the function to a variable.
jQuery.each returns like nearly all jQuery-methods the first argument, which is the equivalent of $("#firstname, #surname"). This is very important to understand as it is one of the key-mechanics of jQuery and enables you to do cool stuff like method chaining, e.g. $("#firstname, #surname").each(do something).each(do even more). That means, you can not return your errors in the each method and pass it to a variable outside of the construct.
You could increment a global variable:
var errors = 0
$("#firstname, #surname").map(function() {
if ($(this).val() == '') {
errors++
}
});
console.log("you have" + errors + "errors");
Note the string concatenator +, not ..
Another idea might be to use the jQuery.map method, which indeed enables you to return a value:
var errors = $("#firstname, #surname").map(function() {
if ($(this).val() == '') {
return 1
}
return 0
});
But this would just leave you with an array of 1 and 0 elements which is more or less the same with what you have started. You would need to add another loop to summ the elements together.
Finally let's get to the jQuery.filter method, which should be just what you need:
var errors = $("#firstname, #surname").filter(function() {
return $(this).val() == "";
}).length;
console.log("you have " + errors + " errors");
Filter will return only those elements where the passed function returned a truthy value, so in this case, all elements that had an empty value. You could not only count the elements but immediately highlight the empty form elements:
var errors = $("#firstname, #surname").filter(function() {
return $(this).val() == "";
}).css("background-color", "red").length;
console.log("you have " + errors + " errors");
Your example has a simple solution because you can just use filter and observe the length of the result, but in general, reduce() is the operation to use when you want to aggregate something about all of the items in a collection into a single value.
jQuery doesn't have a reduce() method, but ES5 arrays do, so you could use it like this:
var errorCount = $("#firstname, #surname").toArray().reduce(function(count, item) {
return count + ($(item).val() === '' ? 1 : 0);
}, 0);
As already stated, filter() is what you should be using here, but hopefully this will help you at some point in the future.

How can I set the contents of an array inside an object to false if it is null?

I am using the following to get some data and load it into an object:
test.qs = data;
The object qs then looks something like this:
[
{"answer":null,
"answered":true,
// many more fields here
"answers":{"correct":null,"response":null}},
{"answer":null,
"answered":true,
// many more fields here
"answers":{"correct":null,"response":null}}
]
How can I make it so that if the response value in the array is null then it is changed to false?
var x=[
{"answer":null,
"answered":true,
// many more fields here
"answers":{"correct":null,"response":null}},
{"answer":null,
"answered":true,
// many more fields here
"answers":{"correct":null,"response":null}}
];
var string=JSON.stringify(x).toString().replace(/\:null/g, ":false");
var json=jQuery.parseJSON(string);
This will change all null's into false
Try this:
$(test.qs).each(function () {
$(this).each(function (i) {
for(var props in this) {
if(test.qs[i][props] == null)
test.qs[i][props] = false;
}
});
});
Note:
You need jQuery to perform this code + depending on where you are pasing the code, it should be available globally, so if the code doesn't work add next one where your variable is declared:
window.test = test;
As I understand it: You want to change the value of "response" to false if it has the value "null". Assuming that each object in your Array has the same structure, than this should work:
for(var i = 0; i < test.qs.length; ++i)
{
if(test.qs[i]["answers"]["response"] == null)
{
test.qs[i]["answers"]["response"] = false;
}
}

Categories

Resources