Why doesn't my simple if-statement render false in javascript? - javascript

I call a function like this:
call_facebook(103138046395999, "samåkning.se", "http://www.facebook.com/samakning", "page");
call_facebook(16089699074, "Jag ska köra bil, vem vill åka med", "http://www.facebook.com/groups/16089699074/", "grupp")
The function looks like this:
function call_facebook(id, name, link, type){
//snip
console.log(type)
if (type = "grupp"){
var postid=fbposts[fbpost].id.split("_");
return "https://www.facebook.com/groups/"+postid[0]+"/permalink/"+postid[1]+'/'
}
else {
return fbposts[fbpost].actions[0].link;
}
}
//snip
};
I have confirmed that they have different type arguments, but still the first case if (type = "grupp") always ends up true. Why?

A single equals character (=) does not compare. It assigns! Therefore, your if statement always assigns "grupp" into type and returns true.
Use == or === to compare.

I guess you meant
if (type == "grupp"){
You have to use == to compare values. Just a single = is used to assign values.

Related

javascript if statement checking for true/false

I wrote, what I thought, was a straight forward if statement in JS but it is running incorrectly.
function printLetter(LetterId) {
var studentflag = $("#IsStudent").val();
if (studentflag)
{
//do option 1
} else {
//do option 2
}
}
Everytime it runs, the studentflag var value is correct, but regardless of whether it is true or false, it goes into option 1. I am pretty sure I have done true/false checks like this before in JS, but do I need to spell it out (studentflag == true) instead?
This is known as truthy and falsy Values
The following values are always falsy:
false
0 (zero)
"" (empty string)
null
undefined
NaN (a special Number value meaning Not-a-Number!)
All other values are truthy:
including "0" (zero in quotes),
"false" (false in quotes) like if (studentflag) //being studentflag "false",
empty functions,
empty arrays, and
empty objects.
If #StudentFlag is either "true" or "false", then if(studentFlag) will always follow the true route because both are non-empty strings (truthy). You need to do something along these lines:
var studentflag = $("#IsStudent").val();
if (studentflag === "true") {
//do option 1
} else {
//do option 2
}
.val () doesn't return a boolean.
Try this instead;
function printLetter(LetterId) {
var studentflag = $("#IsStudent").is (':checked');
if (studentflag)
{
//do option 1
} else {
//do option 2
}
}
This is assuming #IsStudent is a checkbox. If it's not, try this (assuming the value is true (as a string, not a boolean));
function printLetter(LetterId) {
var studentflag = ($("#IsStudent").val () == 'true')
if (studentflag)
{
//do option 1
} else {
//do option 2
}
}
IMO there should be more context in the question. If submitted solution works for OP that is great, but for others using this as a resource, the accepted solution might not work in all cases.
The value retrieved from an element via JS actually depends on the input itself and its HTML structure. Here's a demo explaining the difference between using .val(), .attr('val'), and .is(':checked') with checkboxes and radios. All of those variants can pull different values from an element depending on its HTML structure and current UI state.
Fiddle : http://jsfiddle.net/h6csLaun/2/
var studentflag = $("#IsStudent").val();//This is a string .. not a boolean
if (studentflag === "true") //therefore this has to be string comparison
Or you can make studentflag boolean as follows:
var studentflag = $("#IsStudent").val() === "true";
if (studentflag) { ....

Variable not updating its value

var canAssignMultiple="true";
var canWithdrawMultiple="true";
function onCheckUncheck()
{
if($(':checkbox[name^="checkedRecords"]:checked').length>0)
{
$("input[name='checkedRecords']:checked").each(function()
{
debugger;
var canAssign = $(this).attr("canAssign").toLowerCase();
var canWithdraw = $(this).attr("canWithdraw").toLowerCase();
canAssignMultiple= canAssignMultiple && canAssign;
canWithdrawMultiple= canWithdrawMultiple && canWithdraw;
if (canAssignMultiple == "false")
$("#assaignbutton").attr("disabled", "disabled");
else
$("#assaignbutton").removeAttr("disabled");
if (canWithdrawMultiple == "false")
$("#withdrawbutton").attr("disabled", "disabled");
else
$("#withdrawbutton").removeAttr("disabled");
});
}
else
{
$("#assaignbutton").attr("disabled", "disabled");
$("#withdrawbutton").attr("disabled", "disabled");
}
}
The variable canAssignMultiple is becoming true when each() function is called the second time though its value has changed to false in the first iteration.It should retain its value evrytime the loop runs.How to do this?
boolean (false, true) values are different than strings ("false", "true")
try
var canAssignMultiple = true;
var canWithdrawMultiple = true;
function onCheckUncheck() {
if ($(':checkbox[name^="checkedRecords"]:checked').length > 0) {
$("input[name='checkedRecords']:checked").each(function() {
debugger;
var canAssign = $(this).attr("canAssign").toLowerCase() == "true"; // make this a boolean expression
var canWithdraw = $(this).attr("canWithdraw").toLowerCase() == "true"; // make this a boolean expression
canAssignMultiple = canAssignMultiple && canAssign;
canWithdrawMultiple = canWithdrawMultiple && canWithdraw;
if (canAssignMultiple === false) $("#assaignbutton").attr("disabled", "disabled"); // use false (instead of "false")
else $("#assaignbutton").removeAttr("disabled");
if (canWithdrawMultiple === false) $("#withdrawbutton").attr("disabled", "disabled"); // use false (instead of "false")
else $("#withdrawbutton").removeAttr("disabled");
});
}
else {
$("#assaignbutton").attr("disabled", "disabled");
$("#withdrawbutton").attr("disabled", "disabled");
}
}​
left comments where changes were made
As others have noted, the strings "true" and "false" do not function the same as the boolean values true and false. If you try to use a string in an if statement or with a logical operator such as &&, the string is converted to a boolean; and all non-empty strings are converted to true (i.e. they are "truthy"). That means the string "false" will work the opposite of how you expect, e.g. in ("false" && x) or in if ("false") {...}.
One way to fix your code is to change this line
canAssignMultiple = canAssignMultiple && canAssign;
to convert canAssign to a boolean in an explicit and correct way:
canAssignMultiple = canAssignMultiple && (canAssign == "true");
Then the && operator will work correctly, and canAssignMultiple will hold an actual boolean value.
And (as #mdmullinax noted, but I would do it differently) once canAssignMultiple is actually a boolean, you can change your if statements to treat them as such:
if (canAssignMultiple == "false")
should become
if (!canAssignMultiple)
And similarly with the corresponding withdraw stuff.
Does your HTML look like this?
<input canAssign="false" ...>
<input canAssign="true" ...>
If so, and you can't change the HTML, I suggest changing this:
canAssign = $(this).attr("canAssign").toLowerCase()
to this (to work with booleans from then on):
canAssign = $(this).attr("canAssign") == "true"
and this:
if(canAssignMultiple == "false")
to this (since it is a real boolean now):
if(canAssignMultiple)
If you can change HTML, I suggest you do it the HTML5-compliant way. First, all of your made up attributes should be prefixed data-. You can also change camelCase to hyphen-case. JQuery, when loading your data-attributes, will then perform the conversion from string if possible:
<input data-can-assign="false" ...>
<input data-can-assign="true" ...>
then jQuery will give you the boolean you want from this call:
canAssign = $(this).data("canAssign")
Of course, the same fix should be applied to all other string pseudo-booleans (that don't quite work with the boolean operators) as well.
The reason is: "false" is not exactly false. "false" && x will evaluate to x (not to "false" as you expect). On the other hand, false && x will evaluate to false.

If block of conditional logs a message, but a variable is still being set in the else block

So I have this javascript function, reOrderJSON, and it orders an array, and, if the argument, order equates to "reverse", it reverse the array right after it has been sorted.
I also have a function bound to the click event of an associated link.
function reOrderJSON(subj,att,order,limit){
subj.sort(function (a, b,order) {
a = a[att],
b = b[att];
return a.localeCompare(b);
});
if(order === "reverse"){
subj.reverse();
console.log("Reverse passed a parameter to reOrderJSON")
}
layoutDate(subj,limit)
return depos = subj;
}
function clickReorder(e){
var orderingLink = e.target;
var reverseOrder = "";
var order = $(orderingLink).attr('data-order');
if(order === "desc" || order === "undefined"){
$(orderingLink).attr('data-order','asc');
console.log("Order detected as "+order)
reverseOrder = false;
}else{
$(orderingLink).attr('data-order','desc');
console.log("Order detected as "+order)
reverseOrder = "reverse";
}
var limit = $('.entries-per-page').val();
reOrderJSON(e.data.orderedObject,$(e.target).data('assoc'),reverseOrder,limit);
$('.result th').css('background','transparent');
$(orderingLink).closest('th').css({'background':'pink'});
return false;
}
$('.result').on("click", "th a", { orderedObject: depos }, clickReorder);
The link looks like this at the start:
<th>County</th>
As you can tell, I'm logging some debug text to tell what's going on. The first time I click a link, I always get these two lines returned in the log:
Order detected as undefined
Reverse passed a parameter to reOrderJSON
I don't understand how this is happening, order should not be passed as "reverse" the first time. What am I missing here?
depos is an array object, if that makes any difference.
Your comparison
order === "undefined"
is currently checking for the string "undefined", but you actually want to be checking for an undefined value in a variable.
You really want:
order == undefined // no quotes -- it's not a string
Or, even better:
typeof order == "undefined"
since undefined can be overwritten in non-strict mode.

check if html attribute exist and has right value with jquery

Is there a better way for checking an attribute for:
it exist. so value must be false if attribute doesn't exist
Value is correct (boolean)
var isOwner = false;
if ($(selectedItem).is('[data-isOwner="True"]') || $(selectedItem).is('[data-isOwner="true"]')) {
isOwner = true;
} else {
isOwner = false;
}
Now I need to check for 'True' and 'true'...
Thanks
You can convert the value stored in data-isOwner to lower case and only compare the value to 'true'.
if (($(selectedItem).attr ('data-isOwner') || '').toLowerCase () == 'true')
The above use of <wanted-value> || '' will make it so that if the selectedItem doesn't have the attribute data-isOwner the expression will result in an empty string, on which you can call toLowerCase without errors.
Without this little hack you'd have to manually check so that the attribute is indeed present, otherwise you'd run into a runtime-error when trying to call toLowerCase on an undefined object.
If you find the previously mentioned solution confusing you could use something as
var attr_value = $(selectedItem).attr ('data-isOwner');
if (typeof(attr_value) == 'string' && attr_value.toLowerCase () == 'true') {
...
}

Javascript switch statement- very simple, what am I doing wrong?

I'm sure there must be a really simple answer to this, but at the risk of sounding stupid- I can't get this switch statement to work. The input var, 'status' can be either 'public' or 'draft', and I can assure you it is only holding one of those two values as I have alerted it out at various stages, and anyway, the if statement here works. Take a look:
function switch_status(status){
if (status == 'public'){
return false;
} if (status == 'draft') {
return true;
}
^This works, but replacing the 'if' with this 'switch' statement below doesn't work.
switch(status){
case 'public':
return false;
case 'draft':
return true;
}
}
The first one to provide me with the inevitable embarrassingly simple answer wins my accolade!
EDIT: Here is my full code-
$('.status').live('click',
function(){
fullClass = $(this).attr('class');
id = fullClass.split(' ').slice(-1);
status = fullClass.split(' ').slice(-2,-1);
var newStatus = switch_status(status);
alert(newStatus);
});
function switch_status(status){
// if (status == 'public'){
// return false;
// } if (status == 'draft') {
// return true;
// }
switch(status){
case 'public':
return false;
case 'draft':
return true;
}
}
You're passing status as an array of one string (the result of slice) rather than as just a string.
When you check equality between your array and your string, it appears that coercion is causing the equality check to work. But coercion doesn't happen in a switch statement.
If I change
status = fullClass.split(' ').slice(-2,-1);
to
status = fullClass.split(' ').slice(-2,-1)[0];
then it works fine.
I suspect this problem is occuring due to type conversion.
Javascipt is generally a loosely typed language. The if statement you used earlier used a loose == comparison. This worked just fine.
However, switch statements are a different matter. For the case to be a match, the data types must match. In other words, the status must be converted to a string before it is passed to the switch statement.
I used a .each in a jquery loop and compared value to 'this'; I could clearly see that 'this' had the correct value if I used console.log. It worked in the if/else logic but failed in the switch/case logic.
The solution is:
var obj = this.toString();
switch(obj){
case 'one': ...
case 'two': ...
}
By forcing the 'this' to a string type, the logic in the switch now works.

Categories