Reduce the number of if query in jQuery - javascript

In my website user can enter two input . Input1 and Input2 .
So i have to calculate difference with these two number .
difference =input1-input2
so if the difference is greater than 700 i have to apply color red Please see the follow.
dIFFERENCE > 700 = red
dIFFERENCE > 800 = blue
dIFFERENCE > 900 = green
dIFFERENCE > 1000 = white
dIFFERENCE > 1100 = yellow
dIFFERENCE > 1200 = orange
dIFFERENCE > 1300 = purple
etc.. UP TO dIFFERENCE > 5000 = other color
So here i am writing the following jquery ,
var difference= $(".input1")-$(".input2");
if(difference>700){
$(".result").css("color","red");
}
if(difference>800){
$(".result").css("color","blue");
}
etc
is there any easy way to reduce this query ? Like i can store the color in an array and based on the difference i can fetch the result etc .
Please help
EDIT
What i tried is
var difference= $(".input1")-$(".input2");
if(difference >700 && difference<=800){
difference=700;
}else if(difference>=800 && difference<=900 ){
difference=800;
}else if(difference>=900 && difference<=1000 ){
difference=900;
}else if(difference>=1000 && difference<=1100 ){
difference=1000;
}
...
else if(difference>=4900 && difference<=5000 ){
difference=4900;
}
var differnce_array =[];
difference_array[700]="red";
difference_array[800]="blue";
difference_array[900]="green";
difference_array[1000]="white";
etc...
Still it is too much query . So please help to optimize this code

In this case i would create a dictionary, where the keys represent the thresholds and round the difference down to hundreds and look that key up in the dictionary:
var diff = 789; // your value
var diffs = {700: 'red', 800: 'blue', 900: 'green'}; //etc
var diffcol = Math.floor(diff/100)*100; //Floor down to hundreds
if(diffcol in diffs) console.log(diffs[diffcol]); //Validation

1ST APPROACH
You use a hashtable, it's a little bit like a hashset in c# or java, you just pair the keys to the values:
var hash = {
700:"red",
800:"blue",
900:"green",
//etc...
};
And this is how you can get your color:
var difference= $(".input1")-$(".input2");
roundedDifference = Math.floor(difference/100)*100
var color = hash[roundedDifference];
//This will be your color
2ND APPROACH:
You can round the number so you only get the hundereds i.e. 100,200,300,400,etc.
then you can use a switch statement:
var difference= $(".input1")-$(".input2");
roundedDifference = Math.floor(difference/100)*100
switch(roundedDifference) {
case 700:
$(".result").css("color","red");
break;
case 800:
$(".result").css("color","blue");
break;
case 900:
$(".result").css("color","green");
break;
case 1000:
$(".result").css("color","white");
break;
case 1100:
$(".result").css("color","yellow");
break;
case 1200:
$(".result").css("color","orange");
break;
case 1300:
$(".result").css("color","purple");
break;
case ... until 5000
break;
default:
console.log("difference not within range of 700-5000"
}
You can do this up to 5000.

Here is a working code for you:
function submit() {
var difference = $(".input1").val() - $(".input2").val();
console.log(difference)
function getColor() {
var color;
switch (difference) {
case 700:
color = "red";
break;
case 800:
color = "blue";
break;
case 900:
color = "green";
break;
case 1000:
color = "white";
break;
case 1100:
color = "yellow";
break;
case 1200:
color = "orange";
break;
case 1300:
color = "purple";
break;
default:
color = "magenta"
}
return color
}
$(".result").css("color", getColor(difference));
$(".result").html("The color is: "+ getColor(difference));
}
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<input type="text" class="input1" placeholder="input1">
<input type="text" class="input2" placeholder="input2">
<button onclick="submit()">Difference</button>
<div class="result"> This changes color</div>
</body>
</html>
Please run the above snippet
Here is a working DEMO

Related

Javascript switch statement only triggering first case

a[2] is a random integer variable from 1 - 100. When it is less than than 33 it changes to red but when it is above 33 it stays black. Anyone got an idea why it ignores the last 2 cases?
<script type="text/javascript">
switch (a[2]) {
case < 33:
document.getElementByID('speechstat').style.color = "red";
break;
case >= 33 && <= 66:
document.getElementByID('speechstat').style.color = "blue";
break;
case > 66:
document.getElementByID('speechstat').style.color = "green";
break;
}
</script>
In JavaScript, switch statements look differently than what you've posted. For example, here's some documentation on switch statements on MDN.
If you want to check for ranges, you should check with regular if/else statements.
<script type="text/javascript">
var color;
// Check the possible value ranges.
if (a[2] < 33) { color = 'red'; }
else if (a[2] >= 33 && a[2] <= 66) { color = 'blue'; }
else if (a[2] > 66) { color = 'green'; }
document.getElementByID('speechstat').style.color = color;
</script>
In Javascript, you can't compare a variable with switch but you can do so indirectly as this post's answer shows: switch statement to compare values greater or less than a number
With a few edits and adding some html to check if everything works this is how you would do this in your case:
<!DOCTYPE html>
<html>
<body>
<p id="speechstat1"></p>
<p id="speechstat2"></p>
<p id="speechstat3"></p>
<script type="text/javascript">
var a = 34; //You can set this to whatever you want or a user's input
switch (true) {
case (a<33):
document.getElementById("speechstat1").innerHTML = "red works";
break;
case a>= 33 && a<= 66:
document.getElementById('speechstat2').innerHTML = "blue works";
break;
case a> 66:
document.getElementById("speechstat3").innerHTML = "green works";
break;
}
</script>
</body>
</html>
I put in .innerHTML just to show it works, in your case you can replace those
lines with whatever you want to make happen.
I changed Switch to switch
I changed .getElementByID to .getElementById Spelling matters!
If you are testing a variable for two conditions: case >= 33 <= 66: you
need to add the "and" operator case >= 33 **&&** <= 66:
I changed a[2] to a so it doesn't error out because it's not named
correctly
Overall it's easier to use if and else statements for something like this as Morgan Wilde mentioned.

Word search game : grid generating takes too long

I'm working on a Word Search puzzle game, and I'm struggling with generating the grid with letters. At the moment, I'm able to generate the grid, but the performance is very slow (way too slow for a decent usage, it can take up to 30-40 seconds before generating the grid).
To fit words into the grid, I'm using a recursive function that tries to fit the last word from a given list, then the one before it, etc, and if it doesn't fit, backtracks to the previous word and changes its place, then tries again. I guess I'm not doing this right, because it keeps going back and forth.
I tried to use weighed probabilities for directions, so that the generating is made in a "smarter" way, but I'm not getting any results yet.
My question :
How can I optimize this code to make it more performant and reliable? I accept any suggestions, even if it makes me do a lot of changes (if there is an iterative solution for example instead of a recursive one, or if I'm not reasoning correctly in the function...).
Here is the function:
function tryWord(grid, wordList, index, gridLength){
var valid = false;
var clear = false;
if(index==(wordList.length-1)){
/* Clear grid for current index */
for(var j=0; j<gridLength.x; j++){
grid[index][j] = [];
for (var k=0; k<gridLength.y; k++){
grid[index][j][k] = '';
}
}
var nbIterations = 0;
// Try current word
while(valid == false){
// Impossible to resolve this grid
if(nbIterations>500){
return false;
}
nbIterations++;
var initX = Math.floor(Math.random() * gridLength.x); // x coord of first letter of the word
var initY = Math.floor(Math.random() * gridLength.y); // y coord of first letter of the word
var direction = Math.floor(Math.random() * 8); // direction of the word (0=top-left; 1=top; 2=top-right; 3=right; 4=bottom-right; 5=bottom; 6=bottom-left; 7=left)
valid = checkValidWord(wordList[index].length, initX, initY, direction, gridLength);
}
clear = checkClearWord(wordList[index], initX, initY, direction, grid[index]);
if(!clear){
return false;
}
var x = initX;
var y = initY;
for(var j=0; j<wordList[index].length; j++){
grid[index][x][y] = wordList[index].charAt(j);
switch(direction){
case 0:
x--;
y--;
break;
case 1:
y--;
break;
case 2:
x++;
y--;
break;
case 3:
x++;
break;
case 4:
x++;
y++;
break;
case 5:
y++;
break;
case 6:
x--;
y++;
break;
case 7:
x--;
break;
default:
break;
}
}
return grid;
}
else if(index!=(wordList.length-1)){
var emptyGrid = true;
for(var p=0; p<grid[index].length; p++){
for(var q=0; q<grid[index][p].length; q++){
if(grid[index][p][q]!=''){
emptyGrid = false;
}
}
}
if(emptyGrid || $scope.nbIterations>50){
$scope.nbIterations=0;
grid = tryWord(grid, wordList, index+1, gridLength);
}
/* Prepare grid for current index */
grid[index] = grid[index+1];
if(grid!=false){
// Try current word
while(valid == false){
var initX = Math.floor(Math.random() * gridLength.x); // x coord of first letter of the word
var initY = Math.floor(Math.random() * gridLength.y); // y coord of first letter of the word
var direction = Math.floor(Math.random() * 8); // direction of the word (0=top-left; 1=top; 2=top-right; 3=right; 4=bottom-right; 5=bottom; 6=bottom-left; 7=left)
valid = checkValidWord(wordList[index].length, initX, initY, direction, gridLength); // Check that word fits in the grid
}
clear = checkClearWord(wordList[index], initX, initY, direction, grid[index]);
// If word is obstructed by other words
if(!clear){
$scope.nbIterations++;
return tryWord(grid, wordList, index, gridLength); // Try again
}
else{
var x = initX;
var y = initY;
for(var j=0; j<wordList[index].length; j++){
grid[index][x][y] = wordList[index].charAt(j);
switch(direction){
case 0:
x--;
y--;
break;
case 1:
y--;
break;
case 2:
x++;
y--;
break;
case 3:
x++;
break;
case 4:
x++;
y++;
break;
case 5:
y++;
break;
case 6:
x--;
y++;
break;
case 7:
x--;
break;
default:
break;
}
}
return grid;
}
}
else{
return false;
}
}
}
Parameters of the function :
grid : at the beginning, just a 10x11x11 array filled with '' string.
wordList : an array of words to put in the grid
index : 0 when calling the function for the first time, then it's used to check how deep we are in the wordList
gridLength : an array : {x:11, y:11}, giving the grid length
Some more precisions about the function :
The function checkValidWord checks if a given word going to a given direction fits in a grid with a given size. Returns true or false.
The function checkClearWord checks if a given word going to a given direction fits in the grid with other words already in it (no obstruction etc). Returns true or false.
The function tryWord is supposed to output a 3-dimensional array of size [wordList.length;11;11]. I then use the grid[0] as my 2 dimensional grid for the game.

how to take information from custom method and apply it to another method inside my constructor function javascript?

Okay so I was trying to think of a good example, and so I created a constructor function about precious metals. The constructor takes in type of metal and weight. I have two methods. One method determines if the precious metal (gold or silver) is real and the other calculates the value based on spot price. (I know the spot price is wrong, this is just an example anyway).
Suppose a customer brought in a silver piece that is 80% silver. Because its 80% silver I want to apply that to my metalValue method. How would I do that.
Here is the code. (JSFiddle provided for your convience http://jsfiddle.net/bwj3fv12/).
This will help me understand constructors better.
HTML
<div id="testDiv">test Div</div>
<div id="testDiv2">test Div2</div> <br /><br />
JavaScript
var PreciousMetals = function(metal, weight){
this.metal = metal;
this.weight = weight; //weight in ounces
this.authentic = function(colorTest){
var metalPurity;
var zero = "";
if (this.metal == "silver"){
switch(colorTest){
case "brightred":
metalPurity = 1;
break;
case "darkred":
metalPurity = 0.925;
break;
case "brown":
metalPurity = 0.80;
break;
case "green":
metalPurity = 0.50;
break;
default:
metalPurity = 0;
}
}else if(this.metal == "gold"){
switch(colorTest){
case "green":
metalPurity = "base metal or gold plated";
break;
case "milk colored":
metalPurity = "gold plated sterling silver";
break;
case "no color":
metalPurity = "real gold";
break;
default:
metalPurity = "Could be a fake, try different test";
}
}
return metalPurity;
}
this.metalValue = function(metal){
var sum = 0;
var spotPrice;
if (this.metal == "gold"){
spotPrice = 1000;
}else if(this.metal == "silver"){
spotPrice = 15;
}
sum = spotPrice * this.weight;
return sum;
}
}
var customerCindy = new PreciousMetals("silver", 2);
document.getElementById('testDiv').innerHTML = customerCindy.authentic("brown");
document.getElementById('testDiv2').innerHTML = customerCindy.metalValue(); //The result I would like would be 24 of course.
Now I realize I could do it this way:
document.getElementById('testDiv2').innerHTML = customerCindy.metalValue() * customerCindy.authentic("brown");
However the goal here is to take in the information from the authentic method and use that to help me calculate the metal Value in the metalValue method.
If you'd like to keep the logic of these two methods separate in your constructor function, you could include a third method that performs the task of multiplying the two results.
var PreciousMetals = function(metal, weight){
this.metal = metal;
this.weight = weight; //weight in ounces
this.authentic = function(colorTest){
var metalPurity;
var zero = "";
if (this.metal == "silver"){
switch(colorTest){
case "brightred":
metalPurity = 1;
break;
case "darkred":
metalPurity = 0.925;
break;
case "brown":
metalPurity = 0.80;
break;
case "green":
metalPurity = 0.50;
break;
default:
metalPurity = 0;
}
}else if(this.metal == "gold"){
switch(colorTest){
case "green":
metalPurity = "base metal or gold plated";
break;
case "milk colored":
metalPurity = "gold plated sterling silver";
break;
case "no color":
metalPurity = "real gold";
break;
default:
metalPurity = "Could be a fake, try different test";
}
}
return metalPurity;
}
this.metalValue = function(){
var sum = 0;
var spotPrice;
if (this.metal == "gold"){
spotPrice = 1000;
}else if(this.metal == "silver"){
spotPrice = 15;
}
sum = spotPrice * this.weight;
return sum;
}
this.netValue = function(colorTest){
return this.authentic(colorTest) * this.metalValue();
}
}
Here's a working JSFiddle - https://jsfiddle.net/bwj3fv12/
If you wanted to update metalValue to include the results from the purity check, you could just update
this.metalValue = function(colorTest){
// ...
sum = spotPrice * this.weight * this.authentic(colorTest);
return sum;
}
and call it with
customerCindy.metalValue('brown');
Since this is just an example, there's no reason to worry about it, but presumably the purity in the real world would be just as much an instance property as the metal and the weight, and wouldn't actually be a transient value for a method like this. But that's neither here nor there.

Angular SVG manipulation does'nt work in IE10

I'm struggling with a simple SVG Image, where I try to update the color of two rectangles.
In Chrome they get updated, In IE(10) the reactangles are just black!
In my controller I'm setting the color via $scope.cvrColor=[random generated color code]
I've made this simple sample to illustrate my problem:
http://jsfiddle.net/mvg123/td7py264/
My Controller:
function testController($scope, $timeout) {
var test = updateSvg();
function updateSvg() {
$scope.startColor = getRandomColor();
$scope.cvrColor = getRandomColor();
$timeout(updateSvg, 1000);
};
function getRandomColor() {
var number = Math.floor(Math.random() * 11);
var color = "";
switch (true) {
case (number < 3):
color = "#808000";
break;
case (number > 3 && number < 8):
color = "#666666";
break;
case (number > 8 && number < 12):
color = "#ff0000";
break;
default: color = "#ffff00";
}
return color;
}
}
Any hints out there?
/Best regards
While your example should work, I have discovered that having expressions inside class or style is somewhat unreliable. It's better to use ng-class and ng-style. So in your case you can write:
<rect ng-style="{fill:startColor, fillOpacity:1}" ... />
http://jsfiddle.net/c5ozbv52/
You must use the angularjs directive "ng-style" :
ng-style="{fill:startColor,fillOpacity:1}"
https://docs.angularjs.org/api/ng/directive/ngStyle

getElementId('divname' + varname) ::: Not Working?

I have a long set of divs where I'd like to change all of their background colors to a random color when someone clicks the "home" button with a cascading delay (which I'll add later). I've been testing this in jfiddle and I can't seem to get it to work.
For example, with a while loop of 1-10 on jsfiddle:
http://jsfiddle.net/PWvaw/17/
Am I having a var scope issue or is there an issue with placing a string/variable combo in a getElementByID method? It seems to show, when I place head tags in the HTML section of jfiddle, the code turns red right after the "getElementById("
switch (randomNumberOne) {
case 1:
document.getElementById(
Any help would be appreciated. I did a search here already and found nothing conclusive, however, I apologize if I missed an answer. Thanks!
Just remove the semicolon in your color codes.
function backgroundColorChange() {
var num = 1;
while (num <= 10) {
var randomNumberMe = Math.floor((Math.random()*10)+1);
console.log(randomNumberMe);
switch (randomNumberMe) {
case 1:
document.getElementById('r' + num).style.backgroundColor = '#db0058';
break;
case 2:
document.getElementById('r' + num).style.backgroundColor = '#80e800';
break;
case 3:
document.getElementById('r' + num).style.backgroundColor = '#ffb700';
break;
case 4:
document.getElementById('r' + num).style.backgroundColor = '#4b5ed7';
break;
default:
document.getElementById('r' + num).style.backgroundColor = '#ffffff';
break;
}
num += 1;
}
}
jsfiddle

Categories

Resources