JavaScript variable doesn't increment in function after getElementById of div - javascript

I try to create a JavaScript function that will have one of the variables (var c) which will get the inner text of div tag (the text should be numbers, so somehow it should make variables of numbers) and increment by one when users click button.
Problem: The value of variable c is not incrementing. It increments once, but if user clicks again the button it still stays the same.
//variable $j is in for loop, and the size depends on the other part of the code.
<input type="button" value="Add more" onClick="addmore('.$j.');">
$kxx .= '<div id="K'.$j.'">'.$kx[$j].'</div>';
$kx is for example 1,4,5,2,33,33. And when the index is for example 1, instead of incrementing c (2,3,4,5...) if users click button twice, it gives them 2,2 - instead of 2,3.
<script type="text/javascript">
function addmore(index) {
var c = document.getElementById("K"+index).innerHTML;
c++;
var textarea = document.createElement("textarea");
textarea.name = "odg" + index + c;
var div = document.createElement("div");
div.innerHTML = textarea.outerHTML;
document.getElementById("inner"+index).appendChild(div);
}
</script>

You're pulling that value out as a string. JS doesn't know what to do with c++ because it sees it as string++. Convert it to an int first with -
+c++
or
parseInt(c, 10)
updated to include parseInt() along with +c as suggested below.

Related

Replacing a string value using the click event

I'm building a donate modal.
When I click on the donate button, the progress bar gets incremented based on the input value.
I want to replace the money string from h1 when I click on donate.
So if the input value is 10, when I click on the donate button the h1 should read:
$140 is still needed for this project
This runs only once, because it replaces the text only when it finds '$150'.
.modal
.modal-header-box
h1 $150 is still needed for this project
.modal-content
progress#myProgress(value='50', max='200')
h1 Only days left to fund this project. Join the other 42 other donors who have already suppoorted this project. Every dollar helps.
input(type='number', placeholder='$' id='value', max='100')
button#btn Give Now
.button.save-later Save for later
.button.social Tell your friends
JavaScript
document.getElementById('btn').addEventListener('click', function() {
var x = document.getElementById('myProgress');
console.log(x.value, document.getElementById('value').value)
x.value = +x.value + +document.getElementById('value').value;
let difference = x.max - x.value;
console.log(difference);
document.body.innerHTML = document.body.innerHTML.replace('$150', `${difference}`);
});
Is there any way to make this more dynamic, so the string will update If click on the donate button multiple times?
CodePen link
https://codepen.io/make96/pen/XWZdbPZ
Your problem resides in replacing everything on the page. You should restrict the transformation to the elements that you are changing.
Instead of replacing document.body, then target the modal header box instead.
document.body.innerHTML = document.body.innerHTML.replace('$150', `${difference}`);
Replace the modal-header-box content instead.
document.getElementsByClassName("modal-header-box")[0].innerHTML = `<h1>$${difference} is still needed for this project</h1>`;
Just put the number in a span and only change the span input on every click.
You take the value of the span and the value of the input box and substract it everytime you click on it.
Function:
document.getElementById("btn").onclick = function(){
var value = parseInt(document.getElementById("test").innerHTML);
var donate = parseInt(document.getElementById("value").value);
document.getElementById("myProgress").value += donate;
document.getElementById("test").innerHTML = value-donate;
}
modal-header-box
.modal-header-box
h1 $<span id="test">150</span> is still needed for this project
Don't replace the document body, Not good practice to update the body every time, update only the required field.
Javascript
document.getElementById("btn").addEventListener("click", function() {
const title = document.getElementById("title");
const x = document.getElementById("myProgress");
const prev = +x.value
x.value = prev + +document.getElementById("value").value;
let difference = x.max - x.value;
title.innerHTML = title.innerText.replace(x.max - prev, `${difference}`);
});
Template
h1#title $150 is still needed for this project

How to call a function multiple times in Jquery to add an event listener without just listening the last one?

So I want to create a function that counts the characters in a text box and prints the number below it. The thing is that I want to be able to reutilize the function two times since I have two text boxes.
<textarea id="custom_message" placeholder="sumthin sumthin" maxlength="240"></textarea>
<div id="charsleft1" class="span-8" style="float:right; text-align:right"></div>
<textarea id="restriction_message" placeholder="other sumthing" maxlength="240"></textarea>
<div id="charsleft2" class="span-8" style="float:right; text-align:right"></div>
I want to call this function two times but only the last call to the function works, here's my function.
function char_counter_limit(selector, content){
text_box = "#"+selector.split("#")[1]
counter = "#"+selector.split("#")[2]
var maxlength = $(text_box).attr("maxlength");
$(counter).text(0+" / "+maxlength);
$(text_box).on("input", function(){
var maxlength = $(this).attr("maxlength");
var currentLength = $(this).val().length;
if(currentLength <= maxlength){
$(counter).text(currentLength+" / "+maxlength);
}
})
}
The selector would be the id's of the textbox and the div in one string ej: "#custom_message#charsleft1"
Assuming you're passing distinct selectors in, the problem is that your code is falling prey to what I call the Horror of Implicit Globals: You need to declare text_box and counter so that they're local to the char_counter_limit function, not globals. When they're globals, the second call overwrites the first.
Put var in front of them:
function char_counter_limit(selector, content){
var text_box = "#"+selector.split("#")[1]
var counter = "#"+selector.split("#")[2]

Insert digits into input field with JS keypad without erasing previously entered digits

Looking for some help with a project I am working on, guys and gals.
I have a simple keypad with the digits from 0 to 9, each one is a separate element.
My goal is to bind onclick() events on all of the elements, and make them insert the respective digit into an input field of my choosing.
I know how to set the value of a certain element ( in this case the input field ), but I don't know how to preserve the previously entered digits without rewriting the value of the entire field with the next clicked digit on the keypad.
document.getElementById("field").value = "digit-here"
This is how I set the whole value field. How do I insert a digit without erasing the previously entered ones?
You can do it with the following:
document.getElementById("field").value += "digit-here"
Basically just add + before the equal sign (=).
Get the existing value, add the digit to the end, set that value. += is happy to do that for you with value:
function handler(e) {
document.getElementById("field").value += this.value;
}
for (let n = 1; n < 10; ++n) {
const btn = document.createElement("input");
btn.type = "button";
btn.value = n;
btn.addEventListener("click", handler);
document.body.appendChild(btn);
}
<input type="text" id="field">
<br>
Doing that when the text field had focus might be problematic because the insertion point would get moved, but since clicking the button will make the text field lose focus anyway, that's not an issue in this simple situation.
Try this out as #T.J Crowder said
var text = document.getElementById("field").value = "";
text.value += '';

Assistance with calls to a function and the placement of the result a specific location based on the statement that called it using jquery

I am not a web developer but am enjoying working with jQuery on a timesheet form i am creating for my employer's specific needs.
I am working on part of the timesheet that takes the Start Time and Finish Time along with the Meal Break start and finish time and calculates the total hours worked. This works well using examples found on stack overflow and modifications to meet my needs. Below is the code
jQuery(document).ready(function(jQ){
function calculate() {
var StartTime = jQ(".form-group .StartTime").val().split(':'),
FinishTime = jQ(".form-group .FinishTime").val().split(':'),
MealStart = jQ(".form-group .MealStart").val().split(':'),
MealFinish = jQ(".form-group .MealFinish").val().split(':');
var StartHour = parseInt(StartTime[0], 10) || 0,
FinishHour = parseInt(FinishTime[0], 10) || 0,
StartMin = parseInt(StartTime[1], 10) || 0,
FinishMin = parseInt(FinishTime[1], 10) || 0,
MealStartHour = parseInt(MealStart[0], 10) || 0,
MealFinishHour = parseInt(MealFinish[0], 10)|| 0,
MealStartMins = parseInt(MealStart[1], 10) || 0,
MealFinishMins = parseInt(MealFinish[1], 10) || 0;
var CalcHours = FinishHour - StartHour,
CalcMins = 0,
MealHours = MealFinishHour - MealStartHour,
MealMins = 0;
if(CalcHours < 0) CalcHours = 24 + CalcHours;
if(FinishMin >= StartMin) {
CalcMins = FinishMin - StartMin;
}
else {
CalcMins = (FinishMin + 60) - StartMin;
CalcHours--;
}
CalcMins = CalcMins / 60;
CalcHours += CalcMins;
CalcHours = CalcHours.toFixed(2);
if(MealHours < 0) MealHours = 24 + MealHours;
if(MealFinishMins >= MealStartMins) {
MealMins = MealFinishMins - MealStartMins;
}
else {
MealMins = (MealFinishMins + 60) - MealStartMins;
MealHours--;
}
MealMins = MealMins / 60;
MealHours += MealMins;
MealHours = MealHours.toFixed(2);
GrandTotal = CalcHours - MealHours;
//Convert to fixed decimal again
GrandTotal = GrandTotal.toFixed(2);
//Display the total in the correct location on the page
jQ(".Hours").val(GrandTotal);
}
})
i wrote the code as a function as there are 20 locations on the form that the value of the variable Grand_Total will be placed based on the event that triggers the function.e.g an on change event for Wednesday should only update the total field for Wednesday
My first issue is the value assigned to Grand_Total is not available outside the function even though it is not defined as variable, i was of the opinion that if i omitted the var in front of
GrandTotal = CalcHours - MealHours;
that this would make it global and available anywhere. I am assuming the variable needs to be global so i can call on it from different events
My second issue is i am trying not to duplicate the code for every change in location where the value needs to be stored so my question is what is the best way to run event actions like the following to place the grand total where its needed without affecting the totals in other input boxes
jQuery(document).ready(function(jQ){
jQ('#Wed1_StartTime','#Wed1_FinishTime','#Wed1_MealStart','#Wed1_MealFinish').change(function(){
jQ('.Hours').val("Grand_Total");
// i want to place the value in the input box with a class of .Hours for Wed 1 fieldset only
jQuery(document).ready(function(jQ){
jQ('#Thur1_StartTime','#Thur1_FinishTime','#Thur1_MealStart','#Thur1_MealFinish').change(function(){
jQ('.Hours').val("Grand_Total");
// i want to place the value in the input box with a class of .Hours for Thurq fieldset only
//etc
As you can see this will not work as the same value will be input into all input boxes regardless of the fieldset being modified as all total fields have the same class name. Using ID's i feel is bad coding as i would have write 20 versions of the function and call each one individually based on the elements being changed.
Hope this makes sense
Thanks in advance for any help offered
Pointing out couple of issues from your code and assumptions, Firstly
My first issue is the value assigned to Grand_Total is not available outside the function even though it is not defined as variable, i was of the opinion that if i omitted the var in front of that this would make it global and available anywhere.
NO, this assumption is wrong, The variable will be global only when placed in global scope. Explaining your code.
jQuery(document).ready(function(jQ){ //<-- note this block
function calculate() {
// your other code
GrandTotal = CalcHours - MealHours; // you assume this must be global varialbe only because there is no var in front of it.
}
})
The variable scope is within the block, And as you assume it should be global, Yes it is global But global within in block. Its available to all the functions and code with in the block only.
Now how to create a global variable.
1) Placing the variable declaration under script block and not under any function block. hence available for all the scripts.
<script>
var GrandTotal; //<-- this is global, as its placed directly under script tag and not contained inside any block.
jQuery(document).ready(function(jQ){
function calculate() {
// your other code
GrandTotal = CalcHours - MealHours;
}
})
</script>
2) using window scope while declaring the variable. This will place the variable into the window scope, and is global.
<script>
jQuery(document).ready(function(jQ){
function calculate() {
// your other code
window.GrandTotal = CalcHours - MealHours; // note the window.GrandTotal
}
})
</script>
My second issue is i am trying not to duplicate the code for every change in location where the value needs to be stored so my question is what is the best way to run event actions like the following to place the grand total where its needed without affecting the totals in other input boxes
Since you have not posted any HTML, I will give m best to answer close to your HTML, you can change it to stuff that works for you.
To write a common Jquery you must use class selectors. When ever we write code to work generic way then class is the best choice. So put a class to all your input elements to which you want to bind the change event, Also give a class name to all your div's which holds the input elements of each day. Something like this
<div class="DayTimeWrapper">
<input id="Wed1_StartTime" class="setTime" />
<input id="Wed1_FinishTime" class="setTime" />
<input id="Wed1_MealStart" class="setTime" />
<input id="Wed1_MealFinish" class="setTime" />
<input class="Hours" />
</div>
<div class="DayTimeWrapper">
<input id="Thur1_StartTime" class="setTime" />
<input id="Thur1_FinishTime" class="setTime" />
<input id="Thur1_MealStart" class="setTime" />
<input id="Thur1_MealFinish" class="setTime" />
<input class="Hours" />
</div>
Now your Jquery would be as simple as below.
jQ('.setTime').change(function(){ // set event to all the elements at once with class name setTime
jQ(this).closest('.DayTimeWrapper').find('.Hours').val(Grand_Total);
});
jQ(this).closest('.DayTimeWrapper').find('.Hours').val(Grand_Total); : here jQ(this) means the element which triggered the change event. Now find the closest div with class DayTimeWrapper that would be the div which hold this element. Now trace down to find the input with class Hours within this div and set the value.
So this way we can bind events to all the elements with this simple code, Also the hours will be updated for that particular day itself.
let me know if this helps and if you want further help.
EDIT 1: Adding the working fiddle which is the modified version of yours

Passing variable from function in javascript

I'm trying to take text as input from user and split into array and pass it.
<textarea id="texty">
</textarea>
<input type="button" onclick="funky()" />
<script type="text/javascript">
var str;
var array;
var ACL1;
var ACL2;
function funky() {
str = document.getElementById('texty').value;
array = str.split(' ');
}
for (var i = 0; i < array.length; i++) {
var xi = array[i];
if (xi === "ACL") {
ACL1 = array[i + 1];
ACL2 = array[i + 2];
}
}
I'm again using that variables ACL1 and ACL2 in some other place in the same page using this piece of code
<script type="text/javascript">
document.write(+ ACL1 + "<br>");
</script>
<script type="text/javascript">
document.write(+ ACL2 + "<br>");
</script>
Do anybody know where I'm going wrong?
All your funky() function does is split the string into an array and nothing more - you need to make your for loop part of funky() and see what happens.
You assign a value to array when the button is clicked.
You try to process that data into ACL1 and ACL2 and write them to the page while the document loads.
The button won't be clicked before the document loads.
Move the for loop inside the funky function
Get rid of your document.write scripts.
Replace them with div elements (or some other container that is more semantically appropriate).
Modify the funky function to add the content to the page once it is populated the variables
Find the element you want to put the content in (e.g. with document.getElementById or document.querySelector)
Put the content inside it (e.g. with document.createTextNode and document.appendChild

Categories