If I do this in the console:
document.querySelectorAll('.error')
An object of length 3 is returned.
If any of the property values are empty, then I do not want my if statement to run:
After getting frustrated with this (I was using != '') the internet told me to use !== ""
Here is the output for property in the object:
document.querySelectorAll('.error')[0]
""
document.querySelectorAll('.error')[1]
"some string"
document.querySelectorAll('.error')[2]
""
My newness to JS is probably apparent by my question so far. Is the "best" way to check for empty string to use what I have done !==?
<script>
var errorElems = document.querySelectorAll('.error');
for(i=0; i<errorElems.length; i++) {
if(errorElems[i].textContent !== ""){
dataLayer.push({
"event": "errors",
"eventCategory": "error messages",
"eventAction": errorElems[i].id,
"eventLabel": errorElems[i].textContent
})
};
};
This appears to be working. But I'm one person checking in one browser (Chrome) on a desktop machine, if that matters.
What would be the most full proof (yet reasonably straightforwards) means to doing this? Is !== best test?
If its an empty string, !== "" is the way to go. If it can be undefined too (as it very much can happen when selecting DOM elements), then you should make a check like this:
if (typeof string !== 'undefined' && string !== "")
empty values are parsed as false, if you just try
if (!errorElems[i].textContent) {
... // error handling code here
}
The Node.textContent property, as per its specification can return a null value, so it would be better to test it with something like this:
var errorElems = document.querySelectorAll('.error'),
errorElem;
for (i=0; i < errorElems.length; i++) {
errorElemText = errorElems[i].textContent;
if (typeof errorElemText === "string" && errorElemText !== "") {
dataLayer.push({
"event": "errors",
"eventCategory": "error messages",
"eventAction": errorElems[i].id,
"eventLabel": errorElemText
});
}
}
Related
I'm really trying to avoid nesting in this code snippet...
deal_trade_in_model_1 = document.getElementById('deal_trade_in_model_1').value;
deal_trade_in_amount_1 = document.getElementById('deal_trade_in_amount_1').value;
if (typeof deal_trade_in_model_1 !== 'undefined' && deal_trade_in_model_1 !== null) {
console.log(deal_trade_in_amount_1);
console.log(deal_trade_in_model_1);
if (deal_trade_in_model_1 !== null || deal_trade_in_model_1 !== "") {
if (deal_trade_in_amount_1 == null || deal_trade_in_amount_1 == "") {
console.log('entered into function');
document.getElementById("deal_trade_in_model_1").value = "";
document.getElementById("deal_trade_in_amount_1").value = "";
}
}
}
Basically, what this function does is take the value of two fields... things to know about them and what I want to do to them:
1) They're NOT required
2) If one of them is filled out, the other must be
3) If ONLY one of them is filled out, the user clicks submit, and this part of the function is called upon, I want to delete the value of both of them.
I've tried doing a compound of
&& (and)
and
|| (or)
buttttt it odiously it didn't work.
Primary question: What's the best way to get rid of the nesting (I planned on doing this twice and just swapping the code) that will be the most efficient? This, I want, to be done preferably in the smallest amount of IF statements possible.
Please note: If you change the code a lot, I might not know what you're talking about.. please be prepared to teach me or help me learn!
It sounds like you only want to do something if either of the fields are empty, but not both. Assuming both of the elements are text fields, .value will always return a string. Converting a string to boolean results in false if the string is empty, otherwise true.
So
Boolean(deal_trade_in_model_1) === Boolean(deal_trade_in_amount_1)
will be true if either both fields have a value (both will convert to true) or both fields are empty (both convert to false).
Thus your code can be reduced to
var model_1 = document.getElementById('deal_trade_in_model_1');
var amount_1 = document.getElementById('deal_trade_in_amount_1');
if (Boolean(model_1.value) !== Boolean(amount_1.value)) {
model_1.value = "";
amount_1.value = "";
}
Whats wrong with the below lines of code ...
Its keep complaing that systax error..at the like
if( (radioval === "undefined") || (radioval === null) || (radioval === "null") ) {
complete condition in action
if($('#digitallogin').is(":checked")){
var radioval = $("input[name=certificateradio]:checked").val();//its giving the string "user"
if( (radioval === "undefined") || (radioval === null) || (radioval === "null") ) { //this line
$("#login_error").text("please select the signin certificate");
return false;
}
}
Thanks for any Assistance.
There's no syntax error in your code. If the code had a syntax error, there would be an error message in the Firebug console (not the Watch panel), and the code would not run at all. You'd never get to your breakpoint.
The syntax errors in your screenshot are in your watch expressions. Delete the watch expressions and those error messages will go away.
In your updated screenshot I can see what the syntax error is. Take a close look at your watch expression (reformatted here to avoid scrolling):
if(
(radioval === "undefined") ||
(radioval === null) ||
(radioval === "null")
)
That's not an expression, it's an if statement. If you want to use it as a watch expression, you need just the expression inside the if statement. That is, remove the if( and the final ).
Regarding the specific tests you're making, jQuery's .val() method does return undefined if there are no elements selected. Note that there is an error in the jQuery documentation: it says that .val() returns null when there are no matching elements. This is incorrect; it returns undefined in this case. Here is the line of code in the jQuery source that returns undefined (because it is a simple return; with no value).
But that is the undefined value, not the string "undefined". You would test for this with radioval === undefined. Or you could use radioval == null. Note the == instead of ===; this test matches both null and undefined values. That may be the safest bet, in case the jQuery team ever decides to change the code to match the documentation and start returning null instead of undefined. (An unlikely possibility, but you never know.) By testing radioval == null it would test against either value.
Try
if( (typeof radioval === "undefined") || (radioval === null) || (radioval == "null") ) {
in the third comparison of radioval
radioval == "null" and not === null
$("input[name=certificateradio]:checked").val(); returns undefined (typeof undefined === undefined) if it's unchecked or "on" (typeof "on" === string) if it's checked.
a small example:
<input name="certificateradio" type="checkbox" />
<button>run</button>
$("button").click(function(){
console.log($("input[name=certificateradio]:checked").val());
console.log(typeof $("input[name=certificateradio]:checked").val());
});
http://jsfiddle.net/x2uw4/1/
try to use:
if($("input[name=certificateradio]:checked").val() ==="on"){
...
}
.val() returns a string value, null or an Array in case of a multiselect value, so you could try:
if (/null|undefined/i.test(radioval) || !radioval.length){ /*...*/ }
Since you seem to check for [one of] $("input[name=certificateradio]") being checked, it may also be sufficient to do
if( ( !$("input[name=certificateradio]:checked").length ) {
$("#login_error").text("please select the signin certificate");
return false;
}
Or even shorter
if( $('#digitallogin').is(":checked") &&
!$("input[name=certificateradio]:checked").length ) {
$("#login_error").text("please select the signin certificate");
return false;
}
I am getting a javascript error on a page with this code.The error is "parentNode is null or not and object"
The error is in this line: theParent.parentNode.removeChild(theParent);
Is there some other code I can use to replace this or jquery that
will work instead?
var path = location.pathname;
if( path == "/SearchResults.asp"
|| path == "/ProductDetails.asp"
|| path.indexOf("-s/") != -1
|| path.indexOf("_s/") != -1
|| path.indexOf("_p/") != -1
|| path.indexOf("-p/") != -1 ) {
var links = document.getElementById("content_area")
.getElementsByTagName("a");
var homeLink;
for (var i = 0; i < links.length; i++) {
if (links[i].innerHTML.match("Home")) {
homeLink = links[i];
break;
}
}
var theParent = homeLink.parentNode;
theParent.parentNode.removeChild(theParent);
}
It seems strange that you'd get "parentNode is null or not and object" with:
var theParent = homeLink.parentNode;
If anything, it would simply set theParent to null and continue on. Or, homeLink would need to be the cause of the error, which is not what IE is complaining about.
However, the next line...
theParent.parentNode.removeChild(theParent);
...I could see throwing the error mentioned if parentNode was null, since null cannot have methods, such as removeChild.
You can try revising the line to something like the following to get an idea of success rate:
if (theParent.parentNode == null) // == for null or undefined by coercion
theParent.parentNode.removeChild(theParent);
else
throw new Error('Node could not be removed as parentNode is unknown.');
Or, leave out the else and throw to let it fail silently.
Try
if (theParent) { theParent.parentNode.removeChild(theParent); }
Since, it looks like you may not be finding the innerHTML, "Home" or not creating theParent for some other reason.
The HTML would help, just to make sure Home exists and that it has a grand parent.
It seems your loop may not be finding a link with the text Home. Have you tried checking if homeLink is null?
Looks like either homeLink is null or the parentNode is null. Can you run it in firefox + firebug and set breakpoints?
I am trying to make an if statement in javascript that will do something if the variable does not equal one of a few different things. I have been trying many different variations of the OR operator, but I cant get it to work.
if(var != "One" || "Two" || "Three"){
// Do Something
}
Any ideas? Thanks!
Update:
I have tried this before:
if(var != "One" || var != "Two" || var != "Three"){
// Do Something
}
For some reason it does not work. My variable is pulling information from the DOM i dont know if that would effect this.
Actual Code
// Gets Value of the Field (Drop Down box)
var itemtype = document.forms[0].elements['itemtype' + i];
if(itemtype.value != "Silverware" || itemtype.value != "Gold Coins" || itemtype.value != "Silver Coins"){
// Do Something
}
Your expression is always true, you need:
if(!(myVar == "One" || myVar == "Two" || myVar == "Three")) {
// myVar is not One, Two or Three
}
Or:
if ((myVar != "One") && (myVar != "Two") && (myVar != "Three")) {
// myVar is not One, Two or Three
}
And, for shortness:
if (!/One|Two|Three/.test(myVar)) {
// myVar is not One, Two or Three
}
// Or:
if (!myVar.match("One|Two|Three")) {
// ...
}
More info:
De Morgan's Laws
Edit: If you go for the last approaches, since the code you posted seems to be part of a loop, I would recommend you to create the regular expression outside the loop, and use the RegExp.prototype.test method rather than String.prototype.match, also you might want to care about word boundaries, i.e. "noOne" will match "One" without them...
Assuming you mean "val does not equal One or Two or Three" then De Morgan's Theorem applies:
if ((val != "One") && (val != "Two") && (val != "Three")) {
// Do something...
}
For a shorter way to do it, try this format (copied from http://snook.ca/archives/javascript/testing_for_a_v):
if(name in {'bobby':'', 'sue':'','smith':''}) { ... }
or
function oc(a)
{
var o = {};
for(var i=0;i<a.length;i++)
{
o[a[i]]='';
}
return o;
}
if( name in oc(['bobby', 'sue','smith']) ) { ... }
The method mentioned by Mike will work fine for just 3 values, but if you want to extend it to n values, your if blocks will rapidly get ugly. Firefox 1.5+ and IE 8 have an Array.indexOf method you can use like so:
if(["One","Two","Test"].indexOf(myVar)!=-1)
{
//do stuff
}
To support this method on IE<=7, you could define a method called Array.hasElement() like so:
Array.prototype.hasElement = function hasElement(someElement)
{
for(var i=0;i<this.length;i++)
{
if(this[i]==someElement)
return true;
}
return false;
}
And then call it like so:
if(!["One","Two","Three"].hasElement(myVar))
{
//do stuff
}
Note: only tested in Firefox, where this works perfectly.
In addition to expanding the expression into three clauses, I think you'd better name your variable something other than var. In JavaScript, var is a keyword. Most browsers aren't going to alert you to this error.
Alternate way using an array:
var selected = ['Silverware', 'Gold Coins', 'Silver Coins'];
if ( selected.indexOf( el.value ) != -1 ) {
// do something if it *was* found in the array of strings.
}
Note: indexOf isnt a native method, grab the snippet here for IE:
https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array/IndexOf
In JavaScript is it wrong to use a try-catch block and ignore the error rather than test many attributes in the block for null?
try{
if(myInfo.person.name == newInfo.person.name
&& myInfo.person.address.street == newInfo.person.address.street
&& myInfo.person.address.zip == newInfo.person.address.zip) {
this.setAddress(newInfo);
}
} catch(e) {} // ignore missing args
If you expect a particular condition, your code will be easier to maintain if you explicitly test for it. I would write the above as something like
if( myInfo && newInfo
&& myInfo.person && newInfo.person
&& myInfo.person.address && newInfo.person.address
&& ( myInfo.person.name == newInfo.person.name
&& myInfo.person.address.street == newInfo.person.address.street
&& myInfo.person.address.zip == newInfo.person.address.zip
)
)
{
this.setAddress(newInfo);
}
This makes the effect much clearer - for instance, suppose newInfo is all filled out, but parts of myInfo are missing? Perhaps you actually want setAddress() to be called in that case? If so, you'll need to change that logic!
Yes. For one, an exception could be thrown for any number of reasons besides missing arguments. The catch-all would hide those cases which probably isn't desired.
I would think that if you're going to catch the exception then do something with it. Otherwise, let it bubble up so a higher level can handle it in some way (even if it's just the browser reporting the error to you).
On a related note, in IE, even though the specs say you can, you can not use a try/finally combination. In order for your "finally" to execute, you must have a catch block defined, even if it is empty.
//this will [NOT] do the reset in Internet Explorer
try{
doErrorProneAction();
} finally {
//clean up
this.reset();
}
//this [WILL] do the reset in Internet Explorer
try{
doErrorProneAction();
} catch(ex){
//do nothing
} finally {
//clean up
this.reset();
}
You could always write a helper function to do the checking for you:
function pathEquals(obj1, obj2, path)
{
var properties = path.split(".");
for (var i = 0, l = properties.length; i < l; i++)
{
var property = properties[i];
if (obj1 === null || typeof obj1[property] == "undefined" ||
obj2 === null || typeof obj2[property] == "undefined")
{
return false;
}
obj1 = obj1[property];
obj2 = obj2[property];
}
return (obj1 === obj2);
}
if (pathEquals(myInfo, newInfo, "person.name") &&
pathEquals(myInfo, newInfo, "person.address.street") &&
pathEquals(myInfo, newInfo, "person.address.zip"))
{
this.setAddress(newInfo);
}
For the example given I would say it was bad practice. There are instances however where it may be more efficient to simply trap for an expected error. Validating the format of a string before casting it as a GUID would be a good example.