Why don't my nested if and else statements work? - javascript

All I want to be able to do is validate an email every time the user enters a new character into the input field. When the input field is empty, it shouldn't show anything, but when it contains letters, it should show where the invalid characters are.
My code works but doesn't show nothing when the input field is empty because it uses the nested 'else' instead of the one it should use. anyone help? thanks in advance. andyy
var tick = "<img src='images/tick.png' width='20' height='20'/>";
var cross = "<img src='images/cross.png' width='20' height='20'/>";
var email_element = document.contact_form.email_field.value;
function validate_email(id) {
if ( email_element != '' ) {
var letters = /^[A-Za-z]+$/;
if ( document.contact_form.email_field.value.match(letters) )
{
document.getElementById(id).innerHTML = tick;
valid = true;
} else {
document.getElementById(id).innerHTML = cross;
valid = false;
}
} else {
document.getElementById(id).innerHTML = '';
}
return valid;
}

The problem is most likely this line:
var email_element = document.contact_form.email_field.value;
You are assigning a global variable equal to the value of the email field, and then never updating that variable again. This does not create an "active" link to the current value of the field, it just stores the value as it was when that line was executed. Which in turn means that the first if statement in your function, if ( email_element != '' ), is evaluating a non-current value of the email field.
Move that line to be the first thing inside your function and then every time the function runs you'll get the latest (current) value of that field.
EDIT: Also, you are not assigning a value to valid in the non-nested else. You should declare valid as a local variable in the function and be sure to set it appropriately in every if and else branch (or default it to false when you declare it). As thomasrutter
said you are not currently declaring valid with the var statement in your function, which means it will be created as a global variable, which in turn means that when you don't give it a value in your non-nested else your function will return whatever value valid already had from the previous call. (And really, based on the code you've posted, you don't need the valid variable at all: you could just say return true; or return false; directly inside each branch of your if/else structure.)

Try replacing the expression email_element != '' with document.contact_form.email_field.value != '' as I suspect email_element is a reference to an element and will never be equal to ''. Better yet, create a local variable email_value and assign it the value of document.contact_form.email_field.value and use it in both places as in,
function validate_email(id) {
var email_value = document.contact_form.email_field.value;
if ( email_value != '' ) {
var letters = /^[A-Za-z]+$/;
if ( email_value.match(letters) ) {
document.getElementById(id).innerHTML = tick;
valid = true;
}
else {
document.getElementById(id).innerHTML = cross;
valid = false;
}
}
else {
document.getElementById(id).innerHTML = '';
}
return valid;
}

When setting email_element, you are getting the value once, by copy, because it's a string. So if when the page loads that field is blank, email_element is now set to '' and remains set to it until you set it again.
Tags are set by reference, so what you probably intended is:
var email_element = document.contact_form.email_field;
. . .
if(email_element.value != '')

Related

How to do something when backspace or delete is pressed

So I am having trouble getting my code to do something when I hit backspace or delete.
The code I have works just fine. It runs the following code, updating the size and value of multiple text input fields.
It calls compute(), which calls update() multiple times through updateAllFields().
function compute(input,number){
var decider = String(input.value);
updateAllFields(decider,number);
}
function update(label,convert,decider,number){
var updater = document.getElementById(label);
updater.value = parseInt(decider, number).toString(convert);
updater.style.width = ((updater.value.length + 1) * 12.5) + 'px';
}
function updateAllFields(decider,number){
update('binary',2,decider,number);
update('octal',8,decider,number);
update('decimal',10,decider,number);
update('hexadecimal',16,decider,number);
}
Now, that all runs just fine. I ran into an issue that, when an entire field is deleted, I get NaN, and can no longer edit the text fields unless I outsmart the NaN value.
How it happens is that that if a user hits "Ctrl+home", then backspace (wiping the entire field), NaN appears.
What I want, instead, is that when NaN would have appeared, all of the text inputs are reset to the same size and appearance that they were when their placeholders were showing.
I had looked this up, and found the following:
var input = document.getElementById('display');
input.onkeydown = function() {
var key = event.keyCode || event.charCode;
if( key !== 8 && key !== 46 )
return true;
};
It doesn't work. I even tried replacing the return false to instead read my replacement code:
function refresh(label,number){
var refresher = document.getElementById(label);
refresher.value = '';
refresher.size = number;
}
function refreshAllFields(){
refresh('binary','3');
refresh('octal','2');
refresh('decimal','4');
refresh('hexadecimal','8');
}
And that doesn't work.
What am I doing wrong? How can I get my fields to just reset to their original states if the entire text-field of one is wiped out?
You don't need to decrease the possibility of error. You need to prevent errors at all. Just validate the input data and you won't get NaN.
Simply add a check in your compute if the input is an integer:
function compute(input,number){
var decider = String(input.value);
if (isNumeric(decider))
{
// do something else
decider = "0"; // for example
}
updateAllFields(decider, number);
}
where isNumeric is a function which determines if a string represents number. There are many ways to do this, for example this:
function isNumeric(value)
{
if (isNaN(value)) {
return false;
}
var x = parseFloat(value);
return (x | 0) === x;
}
Also, you can stop passing your decider and number to every function as a string:
function compute(input, number){
if (isNumeric(input.value))
{
updateAllFields(parseInt(input.value, number)); // val is a Number now
} else {
updateAllFields(0); // for example
}
}
function update(label,convert,val){
var updater = document.getElementById(label);
updater.value = val.toString(convert);
updater.style.width = ((updater.value.length + 1) * 12.5) + 'px';
}
function updateAllFields(val) {
update('binary',2,val);
update('octal',8,val);
update('decimal',10,val);
update('hexadecimal',16,val);
}

test for null not working

I have a an onclick function, inside this function I want to create a condition for the way some elements are shown in the textarea. added this in the function:
bPlace = bookForm.txtPlace.value;
if (bPlace="null") {
bPlace="!."
}
bookForm.myText.value = bPlace
according to this condition when the value in txtPlace in myForm is not null it should show anything the user puts in. But when I test it, when I type something, instead of showing that, it still shows the (( !. )) in the textarea.
I should say I used "Undefined" instead of Null and still the same thing happened
Can you please tell me what am I doing wrong?
The problem is you are using assignment operator instead of comparision operator
The statement bPlace="null" will assign the string null to bPlace and will return it, which is a truthy value so the if block will always get executed.
bPlace = bookForm.txtPlace.value;
if (bPlace == "null") {
bPlace = "!."
}
bookForm.myText.value = bPlace
But since bPlace is a input value, I think what you are trying to do is if the input is left blank you want to put a default value in that case you can check
bPlace = bookForm.txtPlace.value;
if (!bPlace) {
bPlace = "!."
}
bookForm.myText.value = bPlace
Demo: Fiddle
Which can be further shorten to
bookForm.myText.value = bookForm.txtPlace.value || '!.';
Demo: Fiddle

JavaScript not recognizing variable

I'm new to Javascript and struggling to figure out why this piece of code isn't working for me.
Essentially I'm defining a variable, yet when I go to use that variable in an IF or Switch statement, it doesn't seem to be able to match the contents of the variable. No errors, the IF statement just doesn't get satisfied. While with the Switch, it always falls through to the default setting, as it can't match the contents.
I have a Print statement in place after the variable is defined, and it does display the contents of the variable correctly.
I'm really at a loss as to why the print can return the value of the variable, yet the IF and Switch can't find it.
Below is the snippet I'm working from. The variable is "strWilma", which doesn't get reflected properly in the Print second value statement, but not in the IF.
for (var i=0; i < Flinstones.length; i++)
{
if (Flinstones[i].startsWith("?"))
{
// Convert the Secondary field map to a Properties item, for easier navigation
var objSecondaryFieldMap = PropertiesFromString(strSecondaryFieldMap);
// Map all of the Secondary values
var arraySecondaryFields = objSecondaryFieldMap.keys();
while (arraySecondaryFields.hasMoreElements())
{
strFred = arraySecondaryFields.nextElement();
strWilma = objSecondaryFieldMap.get(strFred);
print("TargetType:" + Object.prototype.toString.call(strFred));
print("SourceType:" + Object.prototype.toString.call(strWilma));
print("Text Type:" + Object.prototype.toString.call("hardcoded value"));
print("First Value:" + objItem.getNewFieldValue(Flinstones[i].substring(1)) );
print("Second Value:" + strWilma );
if (objItem.getNewFieldValue(Flinstones[i].substring(1)) == strWilma)
//if (objItem.getNewFieldValue(Flinstones[i].substring(1)) == "hardcoded value") // WORKS
{
print("It Worked!!!");
}
}
}
}
}
Thanks

keep add the value without overwrite the function

function checkData() {
var temp = 0;
var totalMarks = countMark(temp);
if (totalMarks != 100)
window.alert("Marks must total 100");
}
function countMark(mark) {
var totalMark = 0;
totalMark += parseInt(mark)
return totalMark;
}
function doAdd() {
var taskid = document.getElementById("taskid").value;
var taskname = document.getElementById("taskname").value;
var taskmark = document.getElementById("taskmark").value;
if (taskid.length === 0)
window.alert("Task Id cannot be empty!");
if (taskname.length === 0)
window.alert("Task name cannot be empty!");
if (taskmark.length === 0)
window.alert("Task Mark cannot be empty!");
else if (!markpattern.test(taskmark))
window.alert("Invalid data in mark field");
var marks = parseInt(document.getElementById("taskmark"));
if (marks < 0 || marks > 100)
window.alert("Marks out of range. Please re-enter");
countMark(marks);
}
My question is when i keep call the doAdd() function. my marks will keep adding . want to do like passing reference like in C++ . my function countMark(...) will keep adding .
after that, when my form submitted, my form will call the function checkData()
If my totalmark is not 100 . will prompt out the alert and error.
but my code is not working . I guess that my countMark function wrong somewhere
If I understand you correctly, you're looking for the equivalent of a static variable - something that gets initialized the first time the function is called, and keeps it's value for subsequent calls.
Take a look at this related question: https://stackoverflow.com/a/1535650/2444111
The top answer (by CMS) is talking about class-based static variables, which are not quite the same thing.
The second answer (by Pascal MARTIN) is what you're looking for. It takes advantage of the fact that JS functions are also objects, and stores the variable as a property of the function object. This is a better solution than using a global variable (or a property of window, which is what a global actually is)
There are several issues in your code and it's really hard to say what your intention was. But I will address what I found.
In the following piece of code you are requesting a DOM Element and try to parse it as an Integer. The result of that type convertion is always NaN. Maybe wanted to get the value attribute of your element, like you did before. (Also, don't request the same element multiple times. Request it once, save the result in a variable and use that variable from that on).
var marks = parseInt(document.getElementById("taskmark"));
if (marks < 0 || marks > 100)
window.alert("Marks out of range. Please re-enter");
countMark(marks);
Your function countMark is pretty useless, because it will always return whatever Number you pass to it (see comments in your code).
function countMark(mark) {
var totalMark = 0; //create a new variable with value 0
totalMark += parseInt(mark) //add "mark" to that variable
return totalMark; //return that variable => 0 + mark = mark (and if mark = NaN => 0 + mark = NaN)
}
Maybe you wanted to make totalMark a global variable, than you would need to define it outside of your function:
var totalMark = 0;
function countMark(mark) {
totalMark += parseInt(mark);
return totalMark;
}
Last but not least, lets analyse your function checkData:
function checkData() {
var temp = 0; //create a local variable with value 0
var totalMarks = countMark(temp); //pass 0 to countMark => return 0 => totalMarks = 0
if (totalMarks != 100) //always true since totalMarks is always 0
window.alert("Marks must total 100"); //will always alert
}

What is the most efficient way of toggling a DOM elements value based on the state of another element?

Imagine we have a text field that executes the code below on each keydown event:
if( $('#my_input').val() == '' )
$('#my_span').html('my input is blank');
else
$('#my_span').html('My input is not blank');
Obviously we are executing code that possibly sets the state of something (#my_span element) to what it already is and this seems inefficient. But I am curious as to what the alternative is? Adding more checks like:
if ( $('#my_input').val() == '' ){
if ( $('#my_span').html() != 'my input is blank' )
$('#my_span').html('my input is blank');
}
else if ( $('#my_span').html() != 'My input is not blank' )
$('#myspan').html('My input is not blank');
Is the latter more efficient? It would seem to me more 'correct', but obviously it's more code and I'm not sure how much more efficient it is than the first example.
I know that the former always involves a DOM manipulation, which will factor in computing the relative efficiency, but I've encountered situations like this before in non-DOM related code, so wondering what is the best approach in all cases. Should you always do the extra check on the value of something before setting it to a new value?
EDIT:
My final version actually uses a combination of the answers here so thanks to all for the great replies. So to sum, I now:
Cache the jquery objects in a closure
Uses state to determine the assignment to a new state
Also as an aside, the setTimeout on the keydown is a very nice way to get a input fields value immediately. Thanks again.
I would cache the jQuery objects and use a boolean to store the state and not call html when you don't have to :
(function(){
var i = $('#my_input'), s=$('#my_span'), blank, check = function() {
if (i.val()=='') {
if (blank!==true) s.html('my input is blank');
blank = true;
} else {
if (blank!==false) s.html('my input is not blank');
blank = false;
}
};
i.keyup(check);
check(); // so that the span is initially filled
})();
Note that what you need isn't keydown but keyup, so that the value of the input is changed before you get the event.
This method even works if you keep pressing the key ;)
Performance? Go Pure JS. Fiddle
//before event binding
var my_input = document.getElementById('my_input'),
my_span = document.getElementById('my_span');
$(my_input).on('keydown', function () {
//inside event handler
var value = my_input.value
, prevVal = my_input.prevVal
;
if (value && prevVal && prevVal !== value) {
return;
}
//timeout to return event handler execution early
//(ie: differ DOM manipulation from the event handler.
//So, UX will extra smooth ;) )
setTimeout(function () {
fieldStatusUpdater(my_input.value);
}, 1);
});
function fieldStatusUpdater(value) {
if (my_input.value === '') {
my_span.innerHTML = 'my input is blank';
} else {
my_span.innerHTML = 'My input is not blank';
}
my_input.prevVal = value;
}
This is the fastest and nicest I can come up with:
function keyUpEvent(){
var state = null,
input = $('#my_input'),
span = $('#my_span');
return function(){
var test = input.val() === '';
if( test === state) return;
if(test)
span.html('my input is blank');
else
span.html('My input is not blank');
state = test;
}
}
$('#my_input').keyup(keyUpEvent());
http://jsfiddle.net/TMb8T/
This uses closures to store the input and span elements after initialization. And you can use it (almost) as if its a normal function, so u can bind it do multiple events and it still works.
Note that you have to execute keyUpEvent when you bind the event.
Addition:
You can now also do something like this:
function keyUpEvent(input, span){
var state = null;
return function(){
var test = input.val() === '';
if( test === state) return;
if(test)
span.html('My input is blank');
else
span.html('My input is not blank');
state = test;
}
}
$('#my_input').keyup( keyUpEvent($('#my_input'), $('#my_span')) );
$('#my_input2').keyup( keyUpEvent($('#my_input2'), $('#my_span2')) );
http://jsfiddle.net/TMb8T/2/
Like this you can easily check every input of a whole form with one single event handler.
Addition 2: If you want to make version 2 work even when the key is kept down ;)
Replace this:
$('#my_input').keyup( keyUpEvent($('#my_input'), $('#my_span')) );
With this:
$('#my_input').keydown(function(){
setTimeout(keyUpEvent($('#my_input'), $('#my_span')),1);
});
http://jsfiddle.net/TMb8T/4/
It really depends on how often you are executing the code. If it executes only when the user presses a button or something like that it would be fine to use the first one, it it runs on a quick timer then it might not.
Do like this:
var text;
if ( $('#my_input').val() == '' )
text = 'my input is blank';
else
text = 'My input is not blank';
if ( $(#my_span).html() != text )
$('#my_span').html(text);
Init:
var isBlank = true;
$('#my_span').html('my input is blank');
keyup:
if(!isBlank){
if( $('#my_input').val().length == 0){
isBlank = true;
$('#my_span').html('my input is blank');
}
} else {
if($('#my_input').val().length){
isBlank = false;
$('#my_span').html('my input is not blank');
}
}
This way you are only manipulating the DOM if the state changes.
Also testing the length property may actually be faster than testing the string against "", because the interpreter won't have to create a String object from the string literal.
You can simplify it with a ternary
$('#my_span').html( $('#my_input').val() == '' ? 'my input is blank' : 'My input is not blank' );
More readable
var text = $('#my_input').val() == '' ? 'my input is blank' : 'My input is not blank';
$('#my_span').html(text);
And it you care about speed, it comes up is a DOM redraw faster that reading content. That really will depend on the page strucutre/size,browser. JSPerf is your friend if you want to see how many milliseconds you will save with 1000's of iterations. You really should be looking for the fastest if you see a performance problem.
No Check, Writing content
You have the penalty of updating the DOM if data changed or did not change
Check, Writing content
You have the penalty of reading the HTML
You have penalty of updating DOM
Check, no write needed
You have the penalty of reading the HTML
Now Is the HTML most likely going to be different, the same, etc?
The solution depends on what you want to do. Caching the jQuery element will speed up the lookup/write. It will be slower than just a write.
How about saving the current value to a variable and just testing the variable to see if you have to change it. No messing with the DOM until you need to change it. (You could also use a boolean named isBlank to get good effect here):
var currValue;
if ( $('#my_input').val() == '' ) {
if ( currValue != 'my input is blank' ) {
currValue = 'my input is blank';
$('#my_span').html(currValue);
}
} else if ( currValue != 'My input is not blank' ) {
currValue = 'My input is not blank';
$('#my_span').html(currValue);
}
You also mentioned this is in the keydown event handler.
Don't forget to run this code one time at the start so it sets the display field to show the input field is blank to start with.
Don't forget that the user can select the text and right click to choose 'cut' and empty the field or choose 'paste' to add text to the field. Similarly, a drag and drop action can conceivably add or remove text.
Alternate Train of Thought
You might be better off with periodic, timed event that checks. Some people can type bursts of keys around 3 or 4 a second. If you timed it to look at the field every 1 second, you could cut down the short term slowdown due to this code running and replace it with a long term constant use of CPU cycles. But remember that there is no reason to not use CPU cycles if the computer isn't doing anything interesting.

Categories

Resources