How to refactor long if statment? - javascript

I have a long if statement that I'm wanting to refactor. The statement listens for a click and then updates one of five text boxes depending on if those text boxes have anything in them or not. How could I change my code to be more efficient.
$('#img1').click(function() {
if ($('#card1').val().length === 0) {
$('#card1').val('A feeling of warmth');
} else if ($('#card2').val().length === 0) {
$('#card2').val('A feeling of warmth');
} else if ($('#card3').val().length === 0){
$('#card3').val('A feeling of warmth');
} else if ($('#card4').val().length === 0){
$('#card4').val('A feeling of warmth');
} else if ($('#card5').val().length === 0){
$('#card5').val('A feeling of warmth');
}
});

you could use a loop
$('#img1').click(function() {
var items = ["#card1", "#card2", "etc"];
for(var i=0;i<items.length;i++){
if ($(items[i]).val().length === 0) {
$(items[i]).val('A feeling of warmth');
}
}
});
it's at least easier to read. Also if your buttons are always card + a number you could make it even simplier (not easier to read, just less lines & maintenance)
$('#img1').click(function() {
for(var i=0;i<=5;i++){
if ($("#card" + i).val().length === 0) {
$("#card" + i).val('A feeling of warmth');
}
}
});

It seems like you're using JQuery. You can use a selector and a filter to isolate the first empty item:
$('#img1').click(function() {
$('input:text[id^=card]')
.filter(function() { return $(this).val() == ""; })
.first()
.val('A feeling of warmth');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="img1">CLICK ME</button><br>
<input id="card1"><br>
<input id="card2"><br>
<input id="card3"><br>
<input id="card4"><br>
<input id="card5">
$('input:text[id^=card]') selects all text inputs whose IDs begin with 'card'. But the same principle would apply to other element types.

$('#img1').click(function() {
// num can be total count of the element like $(.card).children.count
var num = 5, // preferably dont make it hardcoded.
str = 'A feeling of warmth',
preIdStr = '#card',
id;
for (var i = 1; i <= num; i += 1) {
id = preIdStr + i;
if ($(id).val().length === 0) {
$(id).val(str);
}
}
});

Give all cards the same class.
Then use the selector $('.yourclass')
Now use the jQuery for-each (.each) function to iterate all elements. Within the loop you check the value, set it to whatever you want and return false when the value was set, since this exit's the loop.
$('.yourclass').each(
function () {
if (this.val().length === 0) {
this.val('your value');
return false; // exit loop
}
});

Related

Display Based on innerHtml number

I want to create a system that displays certain content based on the number for this innerhtml content...
Here's the actual element itself, 17 is just the number for mine it is different for each user:
<span id="your_div_id_diamonds"><dd><div class="field_uneditable">17</div></dd></span>
I want it to display if their number is say between 10 and 20... Here's a code I've been trying to work with, but it only does one number at a time and currently isn't working...
$(function() {
if(document.getElementById('your_div_id_diamonds').innerHTML = "17") {
document.getElementById('elitecontent').className="gotelite";
}
else {
document.getElementById('elitecontent').style.display="none";
}
}
});
Here's a version that works, but again only works for one number at a time... It'd be a huge pain if I had it go up to say 150 or 200, I'd have to make like 200 else if statements.
$( "#lev1" ).load('/u' + _userdata.user_id + ' #field_id-14 dd', function() {
var divs= document.getElementsByClassName('field_uneditable');
for (var i = 0, len = divs.length; i < len; ++i) {
if(divs[i].innerHTML.indexOf("7") != 1) {
document.getElementById('elitecontent').innerHTML="Elite";
}
else if(divs[i].innerHTML.indexOf("16") != -1) {
document.getElementById('elitecontent').innerHTML="Elite";
}
else if(divs[i].innerHTML.indexOf("17") != -1) {
document.getElementById('elitecontent').innerHTML="Elite";
}
else {
document.getElementById('elitecontent').innerHTML="Starter";
}
}
});
I basically want a code that works similar to with values, where I can just put something like >=10 and =<20
The problem you are facing with your current code is that you aren't using the correct comparison statements = is declarative, not used for comparison. In its place you should be using ==(matches regardless of data type) or === (must match data type as well) for instance
$(function() {
if(document.getElementById('your_div_id_diamonds').innerHTML = "17") {
document.getElementById('elitecontent').className="gotelite";
}else {
document.getElementById('elitecontent').style.display="none";
}
}
});
should be
$(function() {
if(document.getElementById('your_div_id_diamonds').innerHTML == "17") {
document.getElementById('elitecontent').className="gotelite";
}else {
document.getElementById('elitecontent').style.display="none";
}
}
});
However, for your needs something along the lines of:
$(function() {
if(document.getElementById('your_div_id_diamonds').innerHTML <=20 && document.getElementById('your_div_id_diamonds').innerHTML >=10) {
document.getElementById('elitecontent').className="gotelite";
}else {
document.getElementById('elitecontent').style.display="none";
}
}
});
should work.

Checking to find out if an element contains more than 1 classname

I need your help.
Using pure javascript and not jQuery, how do you find out if an element contains more than 1 classname.
ie.
if (#test has the classname = "classA and classB" then { alert(true) }
else { alert(false) }
HTML:
<input type="text" id="test" "class="classA classB">
You question (or rather your title) is a little unclear. I'm guessing what you are asking is not if an element has more than one class, but whether or not an element has 2 specific classes assigned to it (ClassA and ClassB):
var classNames = document.getElementById("test").className.split(" ");
if (classNames.indexOf("ClassA") >= 0 && classNames.indexOf("ClassB") >= 0) {
// test has both class A and class B
alert(true);
} else {
alert(false);
}
<div id="test" class="ClassA ClassB"></div>
You could use just split:
var classes = document.getElementById("test").className.split(' ');
Please check the following:
var classes = document.getElementById("test").className.split(' ');
alert(classes);
<input type="text" id="test" class="classA classB">
<input type="text" id="test" class="classA classB" />
var classArray = document.getElementById('test').classList;
Try with this, here a example fiddlejs
Array.prototype.contains = function(obj) {
var i = this.length;
while (i--) {
if (this[i] == obj) {
return true;
}
}
return false;
}
var test = document.getElementById("test").classList
if (test.contains("classA") && test.contains("classC")){
alert(true)
}
else {
alert(false)
}
Pure JavaScript:
// Consecutive spaces in the class attribute will cause this to return the wrong number
document.getElementById("test").className.split(" ").length
In the above code you'd want to loop through the result of the split method and remove empty array entries before getting the length of the array.
DOM API (http://caniuse.com/#feat=classlist)
document.querySelector("#test").classList.length
or
document.getElementById("test").classList.length
For the psuedo code
var classList = document.querySelector("#test").classList;
if (classList.contains("classA") && classList.contains("classB")) {
alert(true);
} else {
alert(false);
}
First, get the class attribute:
var classAttr = document.getElementById("test").className;
Split it into an array:
var classes = classAttr.split(" +");
Finally, check that both classes are in the array. With ECMAScript 7:
if (classes.includes("classA") && classes.includes("classB") {
alert(true);
} else {
alert(false);
}
Or with older JS:
if ((classes.indexOf("classA") > -1) && (classes.indexOf("classB") > -1)) {
alert(true);
} else {
alert(false);
}

How to add different classes to template element?

In my JSON file I have 7 objects, where first 3 of them have "is_read" attribute == 1, and last 4 have "is_read" == 0.
I add rows, using a template and want to give tr different classes according to their "is_read" value (".news_read" for "is_read" == 1 and ".news_unread" for "is_read" == 0).
However, I end up with 7 rows that all have "news_unread" class. Though, console.log shows that I have 3 "newsData.get('is_read') == 1" and 4 "newsData.get('is_read') == 0" objects.
I wonder how to create rows with different classes. I tried to do newsRow.addClass, but the error message says that an object <tr><td>...</td></tr> (newsRow template) can't have a method addClass.
render: function() {
news.fetchMyNews();
for (var i = 1; i <= news.length; i++) {
var newsData = news.get(i);
var newsRow = JST["news/row"](newsData.attributes);
$("#news_tbody").append(newsRow).first('tr').attr("class",function(){
if (newsData.get('is_read') == 1)
return "news_read";
else if (newsData.get('is_read') == 0)
return "news_unread";
});
}
}
You wrote:
I tried to do newsRow.addClass, but the error message says that an object ... (newsRow template) can't have a method addClass.
But I can't find addClass in your example code:
$("#news_tbody").append(newsRow).first('tr').attr("class",function(){
if (newsData.get('is_read') == 1)
return "news_read";
else if (newsData.get('is_read') == 0)
return "news_unread";
});
I just can advice you to try this code(use addClass, instead of attr and add blocks in if statement):
$("#news_tbody").append(newsRow).first('tr').addClass(function(){
if (newsData.get('is_read') === 1){
return "news_read";
} else if (newsData.get('is_read') === 0) {
return "news_unread";
}
});
As #Pinal suggested, I used addClass instead.
However, after append(newsRow) I used .children('tr') and it worked fine.
$("#news_tbody").append(newsRow).children('tr').addClass(function(){
if (newsData.get('is_read') === 1){
return "news_read";
} else if (newsData.get('is_read') === 0) {
return "news_unread";
}
});

Simple If statement for Javascript(jQuery)

I am trying to wrap my head around if statements. I am new to this.
I have a pretty simple script pulling data(text) from a html5 data attribute.
var $datatext = $(this).data('explain');
Now I want an if statement when html5 attribute data-explain is missing or empty.
var $success = if ($datatext < 0) {
// show some other text, maybe? =
$(this).text('Fail');
} else {
// show original, maybe? =
$(this).text($datatext);
}
Again, hard time wrapping my head around it. Ohhh these ifs.
That should work:
if (typeof $datatext !== 'undefined' && $datatext.length > 0) {
$(this).text($datatext);
} else {
$(this).text('Fail');
}
check for the length not for the data in $datatext rewrite your code like this
if ($datatext.length > 0) {
// show original, maybe? =
$(this).text($datatext);
} else {
// show some other text, maybe? =
$(this).text('Fail');
}
You can do it this way,
Live Demo
$('.someclass').each(function() {
if(typeof this.attributes['data-explain'] != 'undefined')
{
alert(this.id + ": explain exists");
explain = $.trim(this.getAttribute('data-explain'))
if(explain.length > 0)
alert(explain);
else
alert("no value for explain");
}
else
alert(this.id + ": explain does not exists");
});​

Filtering inputs by value

I have HTML construction like this
<div class="qn-block">
<input type="text" class="quantity-number" name="quantity-number" value="2" />
Refresh
</div>
For inputs with value > 1 i have to disable ".refresh-q". For inputs with value = 1 disable ".refresh-q" and ".remove".
How can I achieve this?
In order to disable an anchor you could define a click handler which returns false:
function disableAnchor() {
return false;
}
But you could also hide it or whatever.
and then:
$('.quantity-number').each(function() {
var value = parseInt($(this).val(), 10);
if (isNaN(value)) {
return;
}
if (value > 1) {
$(this).siblings('.refresh-q').addClass('disabled').click(disableAnchor);
} else if (value === 1) {
$(this).siblings('.refresh-q, .remove').addClass('disabled').click(disableAnchor);
}
});
Try this. You cannot disable a link, so I have simply hidden them. There are alternatives to simply hiding the element, such as removing the A element completely, or returning false when clicked, if you'd prefer to use those instead.
$(".quantity-number").change(function() {
var val = $(this).val()
if (val = 1) {
$(this).siblings(".refresh-q, .remove").hide();
}
else if (val > 1) {
$(this).siblings(".refresh-q").hide();
}
});

Categories