Javascript: Problems with invoking functions within a function - javascript

I am trying to clean up this spaghettified code and I decided to separate the methods into separate functional objects and then call them within a single validate function. The code runs correctly on the first function and returns an alert box correctly. However, when I fix the first alert and resubmit the form the second function fires an alert at me to fix something, I click okay and immediately get an alert on the third function. Obviously I need to put in some code to stop the program from running after I click okay to the second functions alert so I can fix the issue, but how?
var checkboxes = document.getElementsByName('days');
var valid = false;
function textFieldValid(){
var textFieldsReq = document.getElementsByName('textFieldReq');
for( var i=0;i<9;i++ ){
if ( !textFieldsReq[i].value ){
alert ( 'You need to fill in the required* text field!' );
textFieldsReq[i].focus();
return false;
}
}
};
function checkboxesValid(){
for ( var i = 0;i<checkboxes.length;i++ ){
if ( checkboxes[i].checked ) {
valid = true;
break;
}
}
if ( !valid ) {
alert( 'You need to select at least one day!' );
checkboxes[0].focus();
return false;
}
}
function lodgeValid(){
var lodging = document.getElementsByName('lodge');
for( var i=0; i<lodging.length; i++ ){
if( lodging[i].checked ){
valid=true;
break;
}
}
if ( !valid ) {
alert( 'You need to select at least one option!' );
lodging[0].focus();
return false;
}
}
function validate(textFieldsReq){
textFieldValid();
checkboxesValid();
lodgeValid();
};

You need to return true/false from each of the tests and then
var checkboxes = document.getElementsByName('days');
function textFieldValid() {
var textFieldsReq = document.getElementsByName('textFieldReq');
for (var i = 0; i < 9; i++) {
if (!textFieldsReq[i].value) {
alert('You need to fill in the required* text field!');
textFieldsReq[i].focus();
return false;
}
}
//if valid return true
return true;
};
function checkboxesValid() {
//create local variables
var valid = false;
for (var i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].checked) {
valid = true;
break;
}
}
if (!valid) {
alert('You need to select at least one day!');
checkboxes[0].focus();
return false;
}
//if valid return true
return valid;
}
function lodgeValid() {
var lodging = document.getElementsByName('lodge'),
valid = false;
for (var i = 0; i < lodging.length; i++) {
if (lodging[i].checked) {
valid = true;
break;
}
}
if (!valid) {
alert('You need to select at least one option!');
lodging[0].focus();
return false;
}
//if valid return true
return valid;
}
function validate(textFieldsReq) {
//check whether all the tests are turnig true
return textFieldValid() && checkboxesValid() && lodgeValid();
};

Related

I am getting confused about how do i write a switch case instead of the if condition using javaScript only

here is my validation function which I wanted to define using the switch case but I'm confused about how to fit this particular code in the switch case.
function validation() {
var formrdvalid = false;
var fname = document.getElementById("fname").value;
var city = document.getElementById("city");
var radios = document.getElementsByName("gender");
var agree = document.getElementById("invalidCheck").checked;
if (fname == "") {
alert("please enter firstname");
}
if (city.selectedIndex === 0) {
alert("select the city");
return false;
}
if (!formrdvalid) {
for (var i = 0; i < radios.length; i++) {
if (radios[i].checked) {
formrdvalid = true;
}
}
}
if (!formrdvalid) {
alert( "please select gender");
return false;
}
if(agree === false){
alert("agree terms and conditions");
}
if (!fname||!city || !radios || !agree ) {
return false;
} else {
return true;
}
}
I think it's possible. And sometimes (maybe not in your case) it's really useful.
To do so, you should declare a variable that represent whole state of form, like this:
var formrdvalid = false;
var fname = document.getElementById("fname").value;
var city = document.getElementById("city");
var radios = document.getElementsByName("gender");
var agree = document.getElementById("invalidCheck").checked;
// this represents state of the form, including all important info
// like a table
var state = `${formrdvalid}|${fname}|${city}|${radios}|${agree}`;
// now you should just list all valid states
switch(state) {
case `true|myform|London|22|true`:
case VALID_STATE2:
case VALID_STATE3:
return true;
default:
return false;
}
Sometimes it is more convenient to define invalid cases and return true by default.

why does my for loop only work on the first element?

I stumbled upon a problem that i have no idea how to fix. I want to be able to check when a radio button is checked. If one of the five buttons is checked, it should give the feedback. Somehow with my code, when i check the first radio button, it works. But if i check the 2nd or 3rd ... It gives me the alert message: please give a rating. So that means either the for loop in the function radioChecker is not working as intended, or i don't know.
{
let validation = document.querySelector('.type__style');
let validation2 = document.getElementById("label__text");
const init = () => {
const $button = document.getElementById('send__button');
$button.onclick = () => {
revealText();
setTimeout(dissapearText, 4000);
}
const radioChecker = () => {
let radios = document.querySelector(".stars").querySelectorAll("input");
for (let i = 0; i <radios.length; i++) {
if (radios[i].checked) {
console.log("yes");
return true;
} else {
return false;
}
}
}
const revealText = () => {
if (validation.value === "") {
validation.focus();
window.alert("Please enter your name.");
return false;
} else if (validation2.value === "") {
validation2.focus();
window.alert("Please fill in commentary.");
return false;
} else if (radioChecker() === false) {
window.alert("Please give a rating.");
return false;
} else {
document.querySelector('.feedback').style.opacity = 1;
console.log('work');
return true;
}
}
const dissapearText = () => {
document.querySelector('.feedback').style.opacity = 0;
}
}
init();
}
This is because you have a return true in the loop. The moment it returns true on the first loop it will break the loop.
const radioChecker = () => {
let radios = document.querySelector(".stars").querySelectorAll("input");
for (let i = 0; i <radios.length; i++) {
if (radios[i].checked) {
console.log("yes");
return true;
}
}
return false;
}
Explanation:
So, the for loop check all radios. if any radio is checked, it will immediately return true.
After running full loop, if it did not find any radio is checked, it will return false.

Showing alert on second occurrence

I have given a call for the below javascript function on drop down selection.
Basically what my requirement is that ,there can be a lot of vndrCd .
But,When ever the first time vndrCd is "SFGL", alert should not open .
If "SFGL is coming second time then an alert should come . I am not able to put this condition as the call to the method is at every click . Is there a way I can achive this .
function GetOptions(var1) {
varId = var1.id;
var vndrNbrCdList = document.getElementById('TouchCellDetailForm:vendorNbrCodeList').value;
var splitVndrList = vndrNbrCdList.split(',');
if (var1.value == '0') {
varhiddBox.value = '0';
return;
}
for (var j = 0; j < splitVndrList.length; j++) {
if (splitVndrList[j].split('-')[0] == (var1.value)) {
var vndrCd = splitVndrList[j].split('-')[1];
break;
}
}
localStorage.setItem("vendorName", vndrCd);
var vendorName1 = localStorage.getItem("vendorName");
if (vendorName1 == 'SFGL') {
alert("Salesforce vendor has already been selected.Please select some other vendor");
}
}
You can use closure to hold a private variable to indicate whether 'SFGL' has been encountered or not:
function GetOptionsHelp() {
'use strict';
let called = false;
return function GetOptions(var1) {
// ... your code block
if (vendorName1 == 'SFGL') {
if (called) {
alert("Salesforce vendor has already been selected.Please select some other vendor");
} else {
called = true;
}
}
}
And you can call the function like this GetOptionsHelp()(var1)
Try doing something like this as an easy solution:
(function () {
var firstTimeFlag = true;
function GetOptions(var1) {
varId = var1.id;
var vndrNbrCdList = document.getElementById('TouchCellDetailForm:vendorNbrCodeList').value;
var splitVndrList = vndrNbrCdList.split(',');
if (var1.value == '0') {
varhiddBox.value = '0';
return;
}
for (var j = 0; j < splitVndrList.length; j++) {
if (splitVndrList[j].split('-')[0] == (var1.value)) {
var vndrCd = splitVndrList[j].split('-')[1];
break;
}
}
localStorage.setItem("vendorName", vndrCd);
var vendorName1 = localStorage.getItem("vendorName");
if (vendorName1 == 'SFGL') {
if(!firstTimeFlag) {
alert("Salesforce vendor has already been selected.Please select some other vendor");
}
firstTimeFlag = false;
}
}
}());

Recursive function to traverse grid goes crazy

When the user clicks on one of the blocks in the table ( see screenshot ) I want to find all neighbouring blocks with the same color. I am trying to do this recursively, but if I try it with more than three blocks it sometimes goes crazy and calls itself over and over until the program crashes.
As far as I can see, the objects are added to the array, but somehow my tests fails and the same object is added over and over and over.
Any insight on what the problem might be and how to solve it would be much appriciated!
Here's a screenshot
This is the function that is called when the user clicks on a block:
var $matchArray;
$('.block').click(function () {
$matchArray = [$(this)];
var $colorClass;
if ($(this).hasClass('red')) {
$colorClass = 'red';
} else if ($(this).hasClass('green')) {
$colorClass = 'green';
} else if ($(this).hasClass('blue')) {
$colorClass = 'blue';
} else {
$colorClass = 'error';
}
findAllSameColorNeighbours($(this), $colorClass);
});
And this is the recursive method:
findAllSameColorNeighbours = function ($this, $colorClass) {
$this.css('border-style', 'solid');
//LEFT
var $leftBlock = isLeftBlockSameColor($this, $colorClass);
if ($leftBlock != null) {
if (!(arrayContains($matchArray, $leftBlock))) {
$matchArray.push($leftBlock);
findAllSameColorNeighbours($leftBlock, $colorClass);
}
}
//ABOVE
//same as for LEFT
//RIGHT
//same as for LEFT
//BELOW
//same as for LEFT
}
This is how I find the neighboring cells, as far as I can see these work just fine. I have one for each direction:
isLeftBlockSameColor = function ($block, $color) {
var $this = $block;
var $tr = $this.parent().parent();
var col = $tr.children().index($this.parent().prev());
var $leftBlock = $this.parent().siblings().eq(col).children();
var $blockClassMatch = $leftBlock.hasClass($color);
if ($blockClassMatch) {
return $leftBlock;
}
else {
return null;
}
};
Here are some help methods to find out if the object is already in the array or not. I use the index of the row and cell to create a sort of latitude and longditude thing.
arrayContains = function ($array, $object) {
for (i = 0; i < Array.length; i++) {
if (compareIndex($array[i], $object)) {
say('true');
return true;
}
};
return false;
};
compareIndex = function ($obj1, $obj2) {
if ((getRowIndex($obj1)) === (getRowIndex($obj2)) {
if ((getCellIndex($obj1)) === (getCellIndex($obj2)) {
return true;
} else {
return false;
}
} else {
return false;
}
};
getCellIndex = function ($this) {
var $tr = $this.parent().parent();
var index = $tr.children().index($this.parent());
return index;
};
getRowIndex = function ($this) {
var $tr = $this.parent().parent();
var index = $tr.index();
return index;
};
There is a bug in the arrayContains function. The loop will iterates only once, because Array.length is equals to 1(As I tested with chrome browser, but I don't know why). You should use $array.length instead.
arrayContains = function ($array, $object) {
//for (i = 0; i < Array.length; i++) {
for (i = 0; i < $array.length; i++) {
if (compareIndex($array[i], $object)) {
say('true');
return true;
}
};
return false;
};

Save the ultimate expression in selectbox

I wrote this code to save the expressions in a "memory" (textarea) in a select box, the code apparently works.
I would, however, prevent to save an expression already present in the select statement. In this case the code does not work. How so? It seems that there are no errors.
var flag = false;
for (var i = 0; i < select.options.length; i++) {
if (select.options[i].value == document.getElementById('textarea').value) {
flag = true;
break;
}
}
if(!flag){
select.options[select.options.length] = new Option(result, result); //salvo l'operazione in selectbox
document.getElementById('operazione').disabled = true;
}else{
alert("Memoria occupata");
}
Try this
function save()
{
var savedmemory = document.getElementById('operations');
var expression = document.getElementById('code').innerHTML;
var flag = false;
for (var i = 0; i < savedmemory.options.length; ++i)
{
if (savedmemory.options[i].text == result)
{
flag = true;
break;
}
}
if (flag)
{
alert("no.");
}
else
{
//
savedmemory.options[savedmemory.options.length] = new Option(result, result);
}
}
operations is the reference toselect.
code to the textarea.

Categories