Simplifying/Combining if statement logic (When using Numbers) - javascript

I have been looking around, googling here and there, how to properly code a very simplistic calculator. More specifically a Boolean calculator with set values. If I've lost you, bear with me I'll try to explain.
I have the need to use checkboxes to set a input.value. This value will be picked up elsewhere in a Web-Java applet; hence the need for input.value.
To save time and confusion I have built a small snippet using JS Fiddle, and realised I have no real idea how to work with Numbers in JS. Everything I have learned so far has been self taught using the web and various other sources.
I struggle in understanding efficient ways of writing logic, but can scrape by, by writing really simplistic logic. The more I write and ask questons the more I learn. So I've come here seeking some advice on how to minimize my given code snippet.
It's not robust, It's not elegant; but it's my route in.
function calculate() {
// set the variables
var a = document.getElementById('checkboxopt');
var b = document.getElementById('checkboxopt1');
var c = document.getElementById('pnvar');
var d = document.getElementById('adjvar');
var e = document.getElementById('adjvar2');
var i = 0;
var i2 = 0;
if (a.checked) {
console.log('Arg True')
i = i + 80;
d.value = i;
} else {
console.log('Arg False')
d.value = i;
}
if (b.checked) {
console.log('Arg True')
i2 = i2 + 30;
e.value = i2
} else {
console.log('Arg False')
e.value = i2;
}
console.log(i, i2);
c.value = i + i2;
};
var cbs = document.querySelectorAll('[type="checkbox"]');
[].forEach.call(cbs, function(cb) {
cb.addEventListener("click", function() {
console.log(this.id);
calculate();
});
});
calculate();
.editoropt {
font-family: Calibri, sans-serif;
width: 160px;
background: #f8f8ff;
padding: .5em;
border: solid 1px #ddd;
}
#checkboxopt {
float: left;
margin-right: 1em;
margin-top: 4px;
}
#checkboxopt1 {
float: left;
margin-right: 1em;
margin-top: 4px;
}
.pnvar {
width: 95%;
}
input:-moz-read-only {
/* For Firefox */
background-color: transparent;
border: none;
border-width: 0px;
}
input:read-only {
background-color: transparent;
border: none;
border-width: 0px;
}
<div class="seq-box-form-field editoropt ">
<label for="opt1"><span style="padding-right: 10px; vertical-align: 1px;">Default 80mm </span>
<input type="checkbox" name="checkboxopt" id="checkboxopt" value="true" checked />
<input type="hidden" name="opt1" id="opt1" value="true" />
</label>
</div>
<div class="seq-box-form-field editoropt ">
<label for="opt1"><span style="padding-right: 10px; vertical-align: 1px;">Add 30mm </span>
<input type="checkbox" name="checkboxopt1" id="checkboxopt1" value="true" />
<input type="hidden" name="opt2" id="opt2" value="true" />
</label>
</div>
<div class="editoropt">
<input class="pnvar" id="pnvar" name="pnvar" placeholder="Null" onkeydown="if (event.keyCode == 13) { event.preventDefault(); return false; }" value="" class="required" type="text">
<input name="adjvar" class="pnvar" id="adjvar" readonly value="0">
<input name="adjvar" class="pnvar" id="adjvar2" readonly value="0">
</div>
</div>
My Question
What would be the best way to simplify my given code, and improve it's performance. More Specifically, is there a more simplistic way of working with numbers within JS? Or am I on the right track with my current snippet?
If you are an experienced JS developer how would you tackle the desired result above?
A little detailed guidance is what I'm hoping for.

First, try to make code as reusable as possible. So,
if (a.checked) {
console.log('Arg True')
i = i + 80;
d.value = i;
} else {
console.log('Arg False')
d.value = i;
}
if (b.checked) {
console.log('Arg True')
i2 = i2 + 30;
e.value = i2
} else {
console.log('Arg False')
e.value = i2;
}
can be replaced as
function dummy(el, val) {
i2 += el.checked ? val : 0;
}
Second, do not have inline functions in HTML. It will dirty your HTML and make debug difficult. You should wrap all listeners in a wrapper function. This will enable you to even export all of them to separate file and you will know where to look.
Third, instead of hard coding value 80 or 30 in your code, make a map or bind it to element using data-attribute
Fourth and more Important one, use better variable names. a-e or i, i1, i2 are bad names. Only you will understand your code (till you are in context). Always use precise meaningful name. This will help in long run. I have even kept function names as long as 30+ chars just to define its purpose.
Also try to break your code in smaller functions. This will increase scope for reusing them.
You can refer updated code and ask any queries, if you have.
Hope it helps!

Related

How to assign labels on a range slider

<div class="range-wrap">
<input id="range" type="range" name="range" min="3" max="20" value="10" step="1">
<label id="rangevalue">10</label>
</div>
I to need to create range slider, where the values below 7 are labelled modest, 7 to 15 as moderate and anything above labelled as extensive. How I do add these labels to my range slide?
The idea will to be just simply get the value of existing slider and based on the value, do an if statement.
And to get the value when someone moves the slider, you can use oninput.
Try this:
First Answer Without The Partition
var slider = document.getElementById("range");
var display = document.getElementById("display");
var getVal = slider.value;
numVal.innerHTML = getVal; // If you don't want the number to be displayed, delete this. This is to show at which number the label will change
if(getVal<7) {
display.innerHTML = "Modest";
}
if(getVal>=7 && getVal<=15) {
display.innerHTML = "Moderate";
}
if(getVal>15){
display.innerHTML = "Extensive";
}
slider.oninput = function() {
numVal.innerHTML = this.value;// If you don't want the number to be displayed, delete this. This is to show at which number the label will change
var getVal = this.value;
if(getVal<7) {
display.innerHTML = "Modest";
}
if(getVal>=7 && getVal<=15) {
display.innerHTML = "Moderate";
}
if(getVal>15){
display.innerHTML = "Extensive";
}
}
<div class="range-wrap">
<input id="range" type="range" name="range" min="3" max="20" value="10" step="1">
<label id="display"></label>
<p id="numVal"></p> <!-- If you don't want the number to be displayed, delete this. This is to show at which number the label will change -->
</div>
ps: I've added comments in the code to hide the number if you don't want it. The numbers are there so you can see the change is happening at the right number. Delete the commented code accordingly to hide number values from displaying.
Updated Answer: (with partition)
You can use child elements to create a bar and push it on top of the slider using absolute and relative position. Its just a simple CSS trick.
The idea is to set a width for your range. Then, create 2 divs that looks like bars using border-right and then absolutely position it to your parent (which would be the range input)
Try this:
var slider = document.getElementById("range");
var display = document.getElementById("display");
var getVal = slider.value;
numVal.innerHTML = getVal; // If you don't want the number to be displayed, delete this. This is to show at which number the label will change
if(getVal<7) {
display.innerHTML = "Modest";
}
if(getVal>=7 && getVal<=15) {
display.innerHTML = "Moderate";
}
if(getVal>15){
display.innerHTML = "Extensive";
}
slider.oninput = function() {
numVal.innerHTML = this.value;// If you don't want the number to be displayed, delete this. This is to show at which number the label will change
var getVal = this.value;
if(getVal<7) {
display.innerHTML = "Modest";
}
if(getVal>=7 && getVal<=15) {
display.innerHTML = "Moderate";
}
if(getVal>15){
display.innerHTML = "Extensive";
}
}
#range-wrap {
position: relative;
}
input[type=range] {
width: 200px;
}
#range-bars {
width: 1px;
height: 10px;
border-right: 2px solid black;
position: absolute;
top: 13px;
left: 47px;
}
#range-bars-two {
width: 1px;
height: 10px;
border-right: 2px solid black;
position: absolute;
top: 13px;
left: 157px;
}
<div class="range-wrap">
<input id="range" type="range" name="range" min="3" max="20" value="10" step="1">
<label id="display"></label>
<p id="numVal"></p> <!-- If you don't want the number to be displayed, delete this. This is to show at which number the label will change -->
<div id="range-bars"></div>
<div id="range-bars-two"></div>
</div>
ps: there was a slight error in the if statement and I have made the changes to this answer plus the snippet 1 answer.

Javascript push() function is not adding objects to an array [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I have a for-loop that cycles thru some html elements collected with jquery selectors and extracts some text or values from them. Each loop creates a new object. The object is simple, it is just text and a value. Console.log confirms that the object is created successfully each loop.
Outside the for-loop, I have a variable (kvObjs) that is initialized as an array. At the end of the for-loop, I push the new object into the array. But console.log confirms that the array stays empty.
This is part of a larger piece of code. This appears to be the part that isn't working. The specific function that isn't working is getKVs(), well, it works except for the part that tries to push the object on the array.
I promise you I looked thru all or almost all the "similar questions" and nothing clicked with me. I might have missed something in them, though. I feel like I'm overlooking something obvious.
I have tried to creating an array manually (var x = ["bob", "steve", "frank"]) and then setting another variable equal to that (var y = x) and that seems to work. I even created an array of objects, as in var x = [{"Key":"Bob","Value":10}, {"Key":"Steve","Value":5}], and I think that worked to. But my for-loop doesn't.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<style>
.Jobs {
width: 300px;
margin: 0 auto;
}
.Jobs li {
display: grid;
grid-template-columns: 1fr 50px;
padding: 2px 5px 2px 7px;
align-items: center;
}
.Jobs .value {
text-align: right;
}
.Jobs p.value {
padding-right: 7px;
}
.even {
background-color: rgba(0,0,0,0.2);
}
</style>
<div class="Jobs">
<ul>
<li class="kvp">
<p class="key">Bob</p>
<input class="value" type="number" value="3"/>
</li>
<li class="kvp even">
<p class="key">Frank</p>
<input class="value" type="number" value="2"/>
</li>
<li class="kvp">
<p class="key">Tom</p>
<input class="value" type="number" value="8"/>
</li>
<li class="kvp total even">
<p class="key">Total</p>
<p class="value">13</p>
</li>
</ul>
</div>
<script>
class KV {
constructor(key, value) {
this.Key = key;
this.Value = value;
}
}
function getKVs(type) {
type = "." + type + " .kvp";
var elmts = $(type);
var kvObjs = [];
for (var i = 0; i < elmts.length; i++) {
var elmt = $(elmts[i]);
if(elmt.hasClass("total")) {
// do nothing
} else {
var k = elmt.find(".key").text();
var v = elmt.find("input").val();
var kv = new KV(k, v);
console.log(kv); // the kv object is successfully created
kvObjs.push[kv];
console.log(kvObjs.length); // but it is not being added to the array (length stays 0)
}
}
return kvObjs;
}
var x = getKVs("Jobs");
console.log(x); // so I'm transferring an empty array to x
</script>
I keep getting an empty array.
Problem in push() , replace kvObjs.push[kv] by kvObjs.push(kv);
read syntax of push() => array.push(element1, ..., elementN);
class KV {
constructor(key, value) {
this.Key = key;
this.Value = value;
}
}
function getKVs(type) {
type = "." + type + " .kvp";
var elmts = $(type);
var kvObjs = [];
for (var i = 0; i < elmts.length; i++) {
var elmt = $(elmts[i]);
if(elmt.hasClass("total")) {
// do nothing
} else {
var k = elmt.find(".key").text();
var v = elmt.find("input").val();
var kv = new KV(k, v);
console.log(kv); // the kv object is successfully created
kvObjs.push(kv);
console.log(kvObjs.length); // but it is not being added to the array (length stays 0)
}
}
return kvObjs;
}
var x = getKVs("Jobs");
console.log(x); // so I'm transferring an empty arr
.Jobs {
width: 300px;
margin: 0 auto;
}
.Jobs li {
display: grid;
grid-template-columns: 1fr 50px;
padding: 2px 5px 2px 7px;
align-items: center;
}
.Jobs .value {
text-align: right;
}
.Jobs p.value {
padding-right: 7px;
}
.even {
background-color: rgba(0,0,0,0.2);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="Jobs">
<ul>
<li class="kvp">
<p class="key">Bob</p>
<input class="value" type="number" value="3"/>
</li>
<li class="kvp even">
<p class="key">Frank</p>
<input class="value" type="number" value="2"/>
</li>
<li class="kvp">
<p class="key">Tom</p>
<input class="value" type="number" value="8"/>
</li>
<li class="kvp total even">
<p class="key">Total</p>
<p class="value">13</p>
</li>
</ul>
</div>
It looks like you have a small error in your code. See the line where you push the object into the array:
kvObjs.push[kv];
You need to use parentheses instead on the .push() method.
kvObjs.push(kv);
It seems that you have a syntax error:
use kvObjs.push(kv);
instead of
kvObjs.push[kv];

How to change style of each character of input text

Here I want to randomly change the CSS of each character of text.
Like if I input Stack I will get S in red, t in blue, a in green... etc on the bottom of the input field.
var myModel = {
name: "Mayur",
};
var myViewModel = new Vue({
el: '#my_view',
data: myModel
});
span{
color:green;
font-weight:600;
font-size:20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<div id="my_view">
<label for="name">Enter name:</label>
<input type="text" v-model="name" id="name" name="name" />
<p>Welcome, <span>{{ name | uppercase }}</span></p>
</div>
I haven't worked with Vue and I'm not familiar with its internal events and processes, but here's a tiny prototype i made in plain JavaScript:
document.querySelector('button').onclick = function (){
let span = document.querySelector('span.letters'),
text = span.textContent;
span.innerHTML = '';
Array.from(text).map(function(l){
let color = document.createElement('span');
color.innerHTML = l;
color.style.color = 'rgb(' +
randInterval(0, 255) + ',' +
randInterval(0, 255) + ',' +
randInterval(0, 255) + ')';
span.appendChild(color);
});
}
function randInterval(min,max)
{
return Math.floor(Math.random()*(max-min+1)+min);
}
<div><span class="letters">STACK</span></div>
<button>Random colors</button>
I've purposefully placed the function that randomizes each value of rgb() in a function, so you can alter it easily (now the colors are trully random). If you want to make the darker, you need to lower the max values. If you want the colors lighter, you need to increase the mins.
Html:
<div>Type something here, then click on the white space beneave.</div>
<input type="hidden" id="hidden">
Javascript:
$("div").prop("contentEditable", true).blur(function(){
var chars = $(this).text().split("");
$("#hidden").val($(this).text());
this.innerHTML = "";
$.each(chars, function(){
$("<span>").text(this).css({
color: "#"+(Math.random()*16777215|0).toString(16)
}).appendTo("div");
});
});
Css:
div{
border: 1px solid black;
width: 400px;
height: 20px;
padding: 2px 3px;
overflow: hidden;
}
You can visit http://jsfiddle.net/DerekL/Y8ySy/ for the implementation!
Both html and css codes are given in the link.
It gives the colour to the characters randomly but it can be manipulated easily or if you want them to run randomly, you can use it directly.

How to make UI more responsive for other screen sizes?

I have an html page in which I have a textbox (Type your text) and TextArea list. I need to type into the textbox and then click Add button so that whatever is there in textbox goes to my TextArea list. I need to type in this below format in the textbox.
Name=Value
This textbox will be used by the user to quickly add Name Value pairs to the list which is just below that textbox. let's say if we type Hello=World in the above textbox and click add, then in the below list, it should show as
Hello=World
And if we again type ABC=PQR in the same textbox, then in the below list, it should show like this so that means it should keep adding new Name Value pair just below its original entry.
Hello=World
ABC=PQR
But if the syntax is incorrect like if it is not in Name=Value pair then it should not add anything to the list and instead show a pop up that wrong input format. Names and Values can contain only alpha-numeric characters. I also have three more buttons Sort by name, Sort by value and Delete button. Once I click either of these buttons, then it should sort entries in TextArea list using either name or value and delete entries as well. Now I have all above things working fine without any issues.
Here is my jsfiddle. I need to use plain HTML, CSS and Javascript, I don't want to use any library yet as I want to keep it simple as I am still learning. Now I am trying to see whether we can make UI more responsive like the UI should adjust based on what screen size is viewing it. For example, if viewed on a mobile phone (i.e. Android or iPhone), the page should automatically adjust to present the layout in a better way. This also applies to re-sizing the browser on desktop, and viewing the page on a tablet.
What are the changes I need to make in my CSS or HTML to make it more responsive? Any improvements I can make here? Since my UI is very simple so there should be some easy way or some improvements I can make here.
Below is my code:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Test</title>
<style type="text/css">
.main{
background:white;
padding: 35px;
border-radius: 5px;
}
#my-text-box {
font-size: 18px;
height: 1.5em;
width: 585px;
}
#list{
width:585px;
height:300px;
font-size: 18px;
}
.form-section{
overflow:hidden;
width:700px;
}
.fleft{float:left}
.fright{float:left; padding-left:15px;}
.fright button{display:block; margin-bottom:10px;}
html, body {
height: 100%;
font-family: "Calibri";
font-size: 20px;
}
html {
display: table;
margin: auto;
}
body {
display: table-cell;
vertical-align: middle;
background-color: #5C87B2;
}
</style>
<script language="javascript" type="text/javascript">
document.getElementById('add').onclick = addtext;
function addtext() {
var nameValue = document.getElementById('my-text-box').value;
if (/^([a-zA-Z0-9]+=[a-zA-Z0-9]+)$/.test(nameValue)){
var x = document.getElementById("list");
var option = document.createElement("option");
option.text = nameValue;
x.add(option);
}
else
alert('Incorrect Name Value pair format.');
}
document.getElementById('btnDelete').onclick = deleteText;
function deleteText(){
var myList = document.getElementById('list');
var i;
for (i = myList.length - 1; i>=0; i--) {
if (myList.options[i].selected) {
myList.remove(i);
}
}
}
document.getElementById('sortByValue').onclick = sortByValue;
function sortByValue(){
var myList = document.getElementById('list');
var values = new Array();
for (var i=0;i<myList.options.length;i++) {
values[i] = myList.options[i].text;
}
values.sort(function(a, b){
if(a != "" && b != ""){
return a.split('=')[1].localeCompare(b.split('=')[1])
} else {
return 0
}
});
clearList(myList);
fillList(myList, values);
}
document.getElementById('sortByName').onclick = sortByName;
function sortByName(){
var myList = document.getElementById('list');
var values = new Array();
for (var i=0;i<myList.options.length;i++) {
values[i] = myList.options[i].text;
}
values.sort(function (a, b){
if(a != "" && b != ""){
return a.split('=')[0].localeCompare(b.split('=')[0])
} else {
return 0
}
});
clearList(myList);
fillList(myList, values);
}
function clearList(list) {
while (list.options.length > 0) {
list.options[0] = null;
}
}
function fillList(myList, values){
for (var i=0;i<values.length;i++) {
var option = document.createElement("option");
option.text = values[i];
myList.options[i] = option;
}
}
</script>
</head>
<body>
<div class = 'main'>
<h3>Test</h3>
<label for="pair">Type your text</label></br>
<div class="form-section">
<div class="fleft">
<input type='text' id='my-text-box' value="Name=Value" />
</div>
<div class="fright">
<button type="button" id='add' onclick='addtext()'>Add</button>
</div>
</div>
<label for="pairs">Name/Value Pair List</label></br>
<div class="form-section">
<div class="fleft">
<select id="list" multiple></select>
</div>
<div class="fright">
<button type="button" id='sortByName' onclick='sortByName()'>Sort by name</button>
<button type="button" id='sortByValue' onclick='sortByValue()'>Sort by value</button>
<button type="button" id='btnDelete' onclick='deleteText()'>Delete</button>
<button type="button">Show XML</button>
</div>
</div>
</div>
</body>
</html>
W3 have a number of resources on responsive web design:
http://www.w3schools.com/html/html_responsive.asp
http://www.w3schools.com/css/css_responsive_intro.asp
Without using PHP to detect the browser/user agent, your responsive design will typically involve ensuring the site is more fluid and flowing, allowing for changing browser widths (as in the first example above) and/or by delivering differing stylesheets depending on the viewport size and media type in CSS (second example).

Mask input for number - percent

How can create a mask input for number that have percent by jQuery? Do I make input just accept until three numbers and put percent sign after numbers while user finished typing(keyup)?
I don't use plugins.
Example:
1% Or 30% Or 99% Or 100% Or 200%
<input name="number" class="num_percent">
You're better off not using JavaScript for this. Besides the problems that come with using onkeyup for detecting text input, you also have the hassle of parsing the resulting string back to a number in your client/server scripts. If you want the percent sign to look integrated, you could do something like this:
<div class="percentInput">
<input type="text" name="number" class="num_percent">
<span>%</span>
</div>
.percentInput { position:relative; }
.percentInput span { position: absolute; right: 4px; top:2px; }
.num_percent { text-align: right; padding-right: 12px; }
http://jsfiddle.net/BvVq4/
I'm rushing slightly, so you may have to tweak the styles to get it to look right cross-browser. At least it gives you the general idea.
I've stayed with input number, moved the percentage char and then modified its position according to the length of the input (the amount of digits).
HTML
<input type="number" min="0" max="100" value="100"> //chose 100 only for the sake of the example
<span class="percentage-char">%</span>
CSS
input {
width: 55px;
height: 20px;
font-size:18px;
}
.percentage-char {
position: absolute;
left: 32px; // default position - in this case 100
top: 1px;
font-size: 18px;
}
.one-digit { //position of the '%' when input is 0-9
left: 13px;
}
.two-digits{ //position of the '%' when input is 10-99
left: 24px;
}
JS
$(":input").change(function() { //listening to changes on input
if ($(this).val() < 10) { //adding and removing the classes
$('.percentage-char').removeClass('two-digits');
$('.percentage-char').addClass('one-digit');
} else if ($(this).val() > 9 && $(this).val() < 100) {
$('.percentage-char').addClass('two-digits');
} else {
$('.percentage-char').removeClass('one-digit two-digits');
}
});
Check out this fiddle
function setPercentageMask() {
let input = $('.percent');
input.mask('##0,00', {reverse: true});
input.bind("change keyup", function() {
isBetweenPercentage($(this));
});
}
function isBetweenPercentage(input) {
let myNumber = (input.val()) ? parseFloat(input.val()) : 0;
(myNumber.isBetween(0, 100.00)) ? myNumber : input.val('100,00');
}
if (typeof(Number.prototype.isBetween) === "undefined") {
Number.prototype.isBetween = function(min, max, notBoundaries) {
var between = false;
if (notBoundaries) {
if ((this < max) && (this > min)) between = true;
} else {
if ((this <= max) && (this >= min)) between = true;
}
return between;
}
}
setPercentageMask();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.mask/1.14.16/jquery.mask.min.js" integrity="sha512-pHVGpX7F/27yZ0ISY+VVjyULApbDlD0/X0rgGbTqCE7WFW5MezNTWG/dnhtbBuICzsd0WQPgpE4REBLv+UqChw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<input name="text" class="percent">

Categories

Resources