Javascript/Ajax/Jquery Dynamically calculation form on change - javascript

I have a small form which is going to be populated from Mysql database and human input. What I want to do is calculate 2 other fields based on the other ones.
Example Form:
Indicator (MySQL) (a dropdown)
Hour Equivalent (MySQL)
SKS Equivalent (MySQL)
Amount (User)
Hour Total (Amount*Hour Equivalent)
SKS Total (Amount*SKS Equivalent)
Submit (Button to save into table)
This is an example for the calculation operation that I try to solve
Indicator = A
Hour Equivalent = 20
SKS Equivalent = 15
Amount = 2
Hour Total (Amount*Hour Equivalent) = 40
SKS Total (Amount*SKS Equivalent) = 30
I have searched around and try some of solutions but I can’t quite find what I am looking for, and my skills are not really good in Javascript/Ajax/Jquery so I haven't able to do anything to work, although I have tried miserably.
How to do it?
This is the HTML Form
<form>
<fieldset>
<legend>PSC Achievement</legend>
<!-- Button Drop Down -->
<div class="form-group">
<label for="buttondropdown">Indicator</label>
<button type="button" data-toggle="dropdown">
Choose
<span class="caret"></span>
</button>
<ul class="dropdown-menu pull-right">
</ul>
</div>
<label for="txtsks">SKS Equivalent</label>
<input id="txtsks" name="txtSks" type="text">
<label for="txtjam">Hour Equivalent </label>
<input id="txtjam" name="txtHour"type="text">
<label for="textjml">Amount</label>
<input id="textjml" name="txtAmount" type="text">
<label for="Totalhour">Hour Total</label>
<input id="Totalhour" name="Totalhour" type="text">
<label for="Totalsks">SKS Total</label>
<input id="Totalsks" name="Totalsks" type="text">
<label for="btn_submit"></label>
<button id="btn_submit" name="btn_submit">Submit</button>
</fieldset>
</form>

Your solution here : https://jsfiddle.net/tv94prmu/ . Calc function is a result of change event. Result will be displayed after one of fields will be filled
$(function(){
$('#txtsks,#txtjam,#textjml').change(function(){
calc();
})
function calc(){
$('#Totalhour').val(parseInt($('#txtjam').val())*parseInt($('#textjml').val()))
$('#Totalsks').val(parseInt($('#txtsks').val())*parseInt($('#textjml').val()))
}
})
Also, you need to include jquery library to page.

If i got your answer correctly.
Your need to provide more info about your code, but, as far as i understood.. u need to add event handlers for your form (as shown below).
Please note that you have set some of the id's of your elements with an uppercase and some with camelCase. which is bad practice, for better practie, decide on a pattern that you are working at.
It will be easier to handle when you are getting back to your code in the future.
txtsks.addEventListener("blur", function( event ) {
/* call SKS Equivalent function */
}, true);
txtjam.addEventListener("blur", function( event ) {
/* call Hour Equivalent function */
}, true);
textjml.addEventListener("blur", function( event ) {
/* call Amount (User) function */
}, true);
Totalhour.addEventListener("blur", function( event ) {
/* call Hour Total (Amount*Hour Equivalent) function */
}, true);
Totalsks.addEventListener("blur", function( event ) {
/* call SKS Total (Amount*SKS Equivalent) function */
}, true);
btn_submit.addEventListener("click", function ( event ) {
/* call Submit(Button to save into table) function */
});
<form>
<fieldset>
<legend>PSC Achievement</legend>
<!-- Button Drop Down -->
<div class="form-group">
<label for="buttondropdown">Indicator</label>
<button type="button" data-toggle="dropdown">
Choose
<span class="caret"></span>
</button>
<ul class="dropdown-menu pull-right">
</ul>
</div>
<label for="txtsks">SKS Equivalent</label>
<input id="txtsks" name="txtSks" type="text">
<label for="txtjam">Hour Equivalent </label>
<input id="txtjam" name="txtHour"type="text">
<label for="textjml">Amount</label>
<input id="textjml" name="txtAmount" type="text">
<label for="Totalhour">Hour Total</label>
<input id="Totalhour" name="Totalhour" type="text">
<label for="Totalsks">SKS Total</label>
<input id="Totalsks" name="Totalsks" type="text">
<label for="btn_submit"></label>
<button id="btn_submit" name="btn_submit">Submit</button>
</fieldset>
</form>

Related

Get value of input field by class name, wherer class name is varible

I have many pair of text fields and submit button, with id to submit button and class to text field as same but different for each pair. So I want to pass the value entered in text field after button click to ajax function.
function update_rate(id){
// var price = document.getElementsByClassName(id)[0].innerHTML;
var price = document.getElementsByClassName(id);
console.log(price);
$.ajax({
type: "POST",
url: "update_rate.php", // Name of the php files
data: {subcategory : id , price: price},
success: function(res)
{
// console.log(html);
alert(res);
}
});
}
first pair:
<div class="form-group">
<input type="text" class="form-control" name="a" placeholder="Your task rate excl. taxes">
</div>
<button type="submit" id="a" onclick="update_rate(this.id)" class="btn btn-primary">Update</button>
<div class="form-group">
<input type="text" class="form-control" name="b" placeholder="Your task rate excl. taxes">
</div>
<button type="submit" id="b" onclick="update_rate(this.id)" class="btn btn-primary">Update</button>
But I can't get the value of text field into variable.
This can and should be done in a different and more simple manner. Connecting the buttons with their text fields by id and class is not a scalable solution and requires constant updating of the code to keep all the naming in sync. Just get the value of the text field that comes just prior to the button. This will be easier if you modify your HTML structure so that the text field and the button are in the same div together.
Don't use inline event handlers, instead separate your event handling
code into JavaScript.
Set up just a single event handler at a higher DOM element and handle
it when it bubbles up to that element. This is called Event
Delegation.
Use data-* attributes to store custom data in elements.
Also, don't use .getElementsByClassName() in 2020. Instead,
use .querySelector.
See comments below.
// Do your event handling in JavaScript, not with inline HTML event handling attributes
// Also, set up just one handler at a parent level of the items that might trigger
// the event (event delegation).
$(".wrapper").on("click", update_rate);
function update_rate(event){
// See if it was a submit button that got clicked
if(event.target.classList.contains("btn")){
// A submit button was pressed.
// Locate the nearest ancestor element that has the form-group class
// (event.target references the actual element that triggered the event).
let formGroup = event.target.closest(".form-group");
// and then, from there, find the first input (which is the one you want).
var input = formGroup.querySelector("input");
// The following code is already added to the success handler below and
// that's where it should be. It's only added here to be able to see the
// effect since the AJAX call won't run in Stack Overflow. The next 3 lines
// should be removed when used for real.
input.classList.add("hidden");
formGroup.querySelector("button").classList.add("hidden");
formGroup.querySelector("span").classList.remove("hidden");
console.log(input.value);
$.ajax({
type: "POST",
url: "update_rate.php", // Name of the php files
// Use the dataset API to extract the custom attribute on the input
data: {subcategory : input.dataset.category , price: input.value},
success: function(res){
alert(res);
// Hide the input and the button and show the updated message
input.classList.add("hidden");
formGroup.querySelector("button").classList.add("hidden");
formGroup.querySelector("span").classList.remove("hidden");
}
});
}
}
.hidden { display:none; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<div class="form-group">
<input type="text" class="form-control" data-category="a" placeholder="Your task rate excl. taxes">
<button type="submit" class="btn btn-primary">Update</button>
<span class="hidden">Updated</span>
</div>
<div class="form-group">
<input type="text" class="form-control" data-category="b" placeholder="Your task rate excl. taxes">
<button type="submit" class="btn btn-primary">Update</button>
<span class="hidden">Updated</span>
</div>
</div>
In the end, you have no id or unique class names to have to match up against each other, your HTML is more simplified, and you only have one event handler to set up.
Several things
var price = document.getElementsByClassName(id);
is plural and you need the value, so
var price = document.getElementsByClassName(id)[0].value; if you must
BUT it is not a class. It is a name
var price = document.getElementsName(id)[0].value; if you must
but if you have jQuery, why not use it?
Here I take the button ID and find the input by name
I also change to type="button" - you do not want to submit when you use Ajax
$(function() { // on page load
$("#container").on("click","[type=button]",function() { // click on type="button" you can use a Class here too
const id = $(this).attr("id");
const price = $("[name="+id+"]").val(); // get the input by name
console.log(id, price)
if (price) {
$.ajax({
type: "POST",
url: "update_rate.php", // Name of the php files
data: {
subcategory: id,
price: price
},
success: function(res) {
// console.log(html);
alert(res);
}
});
}
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
first pair:
<div class="form-group">
<input type="text" class="form-control" name="a" placeholder="Your task rate excl. taxes">
</div>
<button type="button" id="a" class="btn btn-primary">Update</button>
<div class="form-group">
<input type="text" class="form-control" name="b" placeholder="Your task rate excl. taxes">
</div>
<button type="button" id="b" class="btn btn-primary">Update</button>
</div>
As you're already passing the id in the function, using jQuery, you can do something like:
var selector = 'input[name="' + id + '"]' // Compose the selector string for jQuery
var value = $(selector).val() // Get input value

Simulate multiple form clicks with javascript

I have a product page on my website with product options, two with sub options. For those options with sub options they are using type="radio"
I've created javascript buttons which emulate clicking those sub options. I'd like to set up clearing the form and emulating the clicks all on one button. Currently I have a separate clear button, which still doesn't work.
Picture Example: http://i.imgur.com/uAlLBAK.jpg
Code examples below
Sub option code:
<li class="option">
<label for="09f0c74f3d92847ecfcf5837eb6b2f8b">
<input type="radio" class="validation" name="attribute[249]" value="127" id="09f0c74f3d92847ecfcf5837eb6b2f8b"/>
<span class="name">65cc</span>
</label>
</li>
<li class="option">
<label for="06fc48a0a3949a17c28162ea0eb1f406">
<input type="radio" class="validation" name="attribute[249]" value="128" id="06fc48a0a3949a17c28162ea0eb1f406"/>
<span class="name">75cc</span>
</label>
</li>
First button:
<input onclick="document.getElementById('06fc48a0a3949a17c28162ea0eb1f406').click(); document.getElementById('a596a2e871da26ba9b1cf7fffe325848').click();" type="button" value="0911" />
Second button:
<input onclick="document.getElementById('09f0c74f3d92847ecfcf5837eb6b2f8b').click(); document.getElementById('a596a2e871da26ba9b1cf7fffe325848').click();" type="button" value="0916" />
Clear options:
<input onclick="Clear();" type="button" value="Clear" />
<script type="text/javascript">// <![CDATA[
function Clear()
{
clearRadioGroup("09f0c74f3d92847ecfcf5837eb6b2f8b");
clearRadioGroup("a596a2e871da26ba9b1cf7fffe325848");
}
function clearRadioGroup(GroupName)
{
var ele = document.getElementsById(GroupName);
for(var i=0;i<ele.length;i++)
ele[i].checked = false;
}
// ]]></script>
In the above example the second button click would un-select the second element if the buttons were clicked in succession. Thoughts on at the very least being able to clear the form?
There is a typo in function clearRadioGroup. It should be
"var ele = document.getElementById(GroupName);" and not
"var ele = document.getElementsById(GroupName);".
The Clear function will work then.

How to show a blue colored progress bar exactly like gmail's horizontal blue colored progress bar which is displayed when user submits the form?

I'm using Bootstrap v3.3.5 in my website.
In one scenario I'm displaying a form in Bootstrap modal dialog. User fills in the data and submits the form. After submitting the form the form looks as it is until the response is received from the server.
So, what I want to do is display a blue colored horizontal progress bar exactly resembling the blue colored horizontal progress bar which gmail uses when it loads the inbox mail list after login. This progress bar should be dynamic like gmail's progress bar(i.e. progressive in nature and not like revolving circle loader image).
It should be displayed at the top of form with the message "Please wait...your event is being generated." I've added a comment in my code telling where it should be displayed exactly.
Following is my Bootstrap modal's HTML code:
<form method="post" action="{$site_url}add_event.php" id="formAddEvent" >
<!-- The gmail look alike loader should display here only upon successfull submission of a form. -->
<div class="form-group" id="addEventErrorMsg" style="display:none; color:#FF0000;">
</div>
<div class="form-group">
<input type="text" name="txt_event_title" id="txt_event_title" autocomplete="off" class="form-control custom-height" placeholder="Event Title" style="height:30px;" />
</div>
<div class="form-group">
<textarea type="text" name="txt_event_description" id="txt_event_description" autocomplete="off" class="form-control custom-height" placeholder="Description (optional)" style="height:60px;" ></textarea>
</div>
<table border="0" cellspacing="10">
<tr>
<th><span class="event-title1" style="margin-bottom:5px;">Start Date:</span></th>
<th><span class="event-title1" style="margin-bottom:5px;">End Date:</span></th>
</tr>
<tr>
<td>
<div style="margin-right:15px;" class="form-inline form-group event-selection">
<div class="form-group has-feedback">
<div class='input-append date form_datetime' data-date="2013-02-21T15:25:00Z">
<input type='text' id='event_start_date' name="event_start_date" style="width:225px; display:inline; height:30px;" class="form-control" autocomplete="off" />
<span aria-hidden="true" class="glyphicon glyphicon-calendar form-control-feedback"></span>
</div>
</div>
</div>
</td>
<td>
<div class="form-inline form-group event-selection">
<div class="form-group has-feedback">
<div class='input-append date form_datetime' data-date="2013-02-21T15:25:00Z">
<input type='text' id='event_end_date' name="event_end_date" style="width:225px; display:inline;height:30px;" class="form-control" autocomplete="off" />
<span aria-hidden="true" class="glyphicon glyphicon-calendar form-control-feedback"></span>
</div>
</div>
</div>
</td>
</tr>
</table>
<div class="form-group has-feedback">
<input type="text" name="txt_event_location" id="txt_event_location" autocomplete="off" class="controls form-control custom-height" placeholder="Event Location" style="height:30px;" />
<span class="glyphicon glyphicon-map-marker form-control-feedback" aria-hidden="true"></span>
</div>
<div style="clear:both;"> </div>
<div id="map"></div>
<div class="form-group">
<input type="text" name="txt_event_room" id="txt_event_room" autocomplete="off" class="form-control custom-height" placeholder="Room No." style="height:30px;" />
</div>
<div class="form-group">
<div id="custom-templates">
<input class="typeahead form-control custom-height" id="selected_groupname" name="selected_groupname" type="text" placeholder="Invite Group" value="{foreach from=$user_group_list1 item=grouplist key=key} {if $groupId==$grouplist.page_id} {$grouplist.title} {/if} {/foreach}">
<input type="hidden" name="selected_groupid" id="selected_groupid" value="" />
</div>
</div>
<div class="modal-footer text-center">
<button class="btn btn-primary" id="btn_add_event" type="button">Add Event</button>
<button data-dismiss="modal" class="btn btn-default" type="button">Cancel</button>
</div>
</form>
The function which gets called for form submission upon clicking on button with id btn_add_event is as follows:
$(document).ready(function() {
$("#btn_add_event").click(function() {
var strSeriaze = $( "#formAddEvent" ).serialize();
url = $( "#formAddEvent" ).attr('action');
$("#btn_add_event").attr('disabled', 'disabled');
$("#addEventErrorMsg").html('');
$.ajax({
url : url,
type : "POST",
data : {postData:strSeriaze},
beforeSend: function() {
$('#loader-icon').show();
},
complete : function() {
$('#loader-icon').hide();
},
success : function(data) {
// $("#events-result").append(data);
$('#loader-icon').hide();
if(data == true) {
$("#myModal-add-event").modal('hide');
$("#myModal-add-event").hide();
//window.location = site_url + "event_index.php";
window.location.href = site_url + "event_index.php";
return false;
} else {
$("#btn_add_event").attr('disabled', false);
$("#addEventErrorMsg").show();
$("#addEventErrorMsg").html(data);
}
},
error: function() {}
});
})
});
Please help me. Thanks.
My question is different than any other question. I don't know how to work the progress bar percentage or progress with the response time. I'm not getting solution for it from anywhere. Please remove the tag of duplicate from my question.
My question is different than any other question. I don't know how to
work the progress bar percentage or progress with the response time.
I'm not getting solution for it from anywhere. Please remove the tag
of duplicate from my question.
No it's not different, and therefore it is duplicate of
show progressbar while loading pages using jquery ajax in single page website
The only difference is that in your bounty notice you said
This question had a bounty worth +50 reputation from user2839497.
The question is widely applicable to a large audience. A detailed
canonical answer is required to address all the concerns.
I want a canonical answer for this question. I want a working demo of
a code which must be integrated with the code I posted in the
question. I need the entire working code demo(jsfiddle) for the same.
I don't want any reference links for tutorials or anything else. I
just want to work the exactly same google styled blue colored progress
bar working in my website's ajax function call. Anyhow you make my
code working with the necessary other code. Thanks. Waiting keenly for
the perfect answer folks. Have a nice day.
and as SO is not a code factory to its users disposal, the dupe is an excellent way to solve your question.
This community answer is intended to be deleted when the question is closed as a duplicate.
Edit after post review
This code snippet shows the essential part for a progress bar.
HTML
<div class="progress-bar"></div>
Script
function set_pbar(p) {
$('.progress-bar').css({ width:(p * 100)+'%'});
}
$.ajax({
xhr: function() {
var xhr = new window.XMLHttpRequest();
xhr.upload.addEventListener("progress", function(evt){
if (evt.lengthComputable) {
//Sending in progress, divided with 2 make bar 50% wide after sending
set_pbar(evt.loaded / evt.total / 2);
}
}, false);
xhr.addEventListener("progress", function(evt){
if (evt.lengthComputable) {
//Receiving in progress, dividing with 2 and adding 0.5 make bar start at 50%
set_pbar(0.5 + (evt.loaded / evt.total / 2));
}
}, false);
return xhr;
},
url: "/echo/json/",
type: 'POST',
data: {json: JSON.stringify(new Array(100000))},
success: function(data){
//Loaded...
}
});

Trouble with binding events to Bootstrap 3 (button.js) button radios

I'm having trouble getting the correct value from a segmented control I made with the radio button component of button.js in Twitter Bootstrap 3. When I bind a click event to the segmented control that runs $.serialize() on the parent form, it return the unchecked value of the radio button along with all the other correct values from the other inputs.
I suspect it might be related to the fact that I can't bind this event directly to the segmented control's input. When I tried to bind the event directly to the input I didn't get a response back, so I bound it to the label.
Here's an example of the problem in a fiddle: https://jsfiddle.net/stevekas/9w94pL4o/
<form id="form">
<div id="radios">
<div class="radio">
<label class="major-category">
<input facet="exclusive" type="radio" name="hipsum" value="hashtag" />hashtag</label>
</div>
<div class="radio">
<label class="major-category">
<input facet="exclusive" type="radio" name="hipsum" value="farm-to-table" />farm-to-table</label>
</div>
<div class="radio">
<label class="major-category">
<input facet="exclusive" type="radio" name="hipsum" value="gastropub" />gastropub</label>
</div>
</div>
<!--/ #radios -->
<div id="segmented-control" class="btn-group btn-group-justified" data-toggle="buttons">
<label class="btn btn-default active">
<input type="radio" name="segmented-control" id="roof" value="roof" autocomplete="off" checked />roof</label>
<label class="btn btn-default">
<input type="radio" name="segmented-control" id="party" value="party" autocomplete="off" />party</label>
</div>
<!--/ #segmented-control -->
</form>
<script>
$('.radio input').on('click', function () {
var data = $('#form').serialize();
});
$('#segmented-control label').on('click', function () {
var data = $('#form').serialize();
});
</script>
It probably happens because the click for the label is processed before the click for the input (the label is higher in the DOM tree).
You can force debug to be called after all the events have been processed using setTimeout() without any delay, like this:
$('#segmented-control label').on('click', function () {
setTimeout(function() {
debug();
}, 0);
});
This works because setTimeout() enqueues a new event, which will be run after all the current pending ones.

jquery function input radio onchange

Im trying to implement a self-written query function. A brief description about the function: It should recalculate two values when changing the radio button. It is working in JSFiddle. (http://jsfiddle.net/VL465/34/)
However now i'm trying to implement it in a real webpage. But actually i'm not able to get it working. I've tried to debug it but didn't grinder to a hold.
Currently the console is only showing the "Function loaded" message. When changing the radio buttons it doesn't display days recognized.
Let me clarify the current HTML file:
in the head i have:
<script type='text/javascript' src='http://code.jquery.com/jquery-1.8.3.js'></script>
<script type="text/javascript" src="/js/functions.js"></script>
The form is exactly the same:
<form action="/b/" method="POST" id="choseLessor">
<fieldset>
<input type="hidden" name="userLocale" value="en">
<ul>
<li><span class="rate"> € 21,29</span> <span class="note">starting at </span><span class="radio"></span><input type="radio" class="styled" name="days" value="30" data-price="21.29"><b>30 days </b></li>
<li><span class="rate"> € 23,65</span> <span class="note">starting at </span><span class="radio" style="background-position: 0px -50px;"></span><input type="radio" class="styled" name="days" value="60" data-price="23.65" checked=""><b>60 days </b></li>
<li><span class="rate"> € 26,02</span> <span class="note">starting at </span><span class="radio"></span><input type="radio" class="styled" name="days" value="90" data-price="26.02"><b>90 days </b></li>
<li><span class="rate"> € 27,20</span> <span class="note">starting at </span><span class="radio"></span><input type="radio" class="styled" name="days" value="120" data-price="27.2"><b>120 days </b></li>
</ul>
<div class="priceCalculation">
<div class="list">
<span class="type">List Price:</span>
<span class="retailPriceActual">
<div class="strikethrough">€ 49,93</div>
</span>
</div>
<div class="savings">
<span class="type">Your Savings:</span>
<span class="bookSavings" id="CalculateSavings">€ 26,28</span>
</div>
<div class="total">
<span class="type bigger">Your Price:</span>
<span class="totalPrice" id="CalculatePrice">€ 23,65</span>
</div>
</div>
<input type="submit" value="Cho" class="btn">
</fieldset>
</form>
And the contents of functions.js
$( document ).ready(function() {
console.log ( 'Function loaded' );
$("input[name=days]:radio").change(function () {
console.log ( 'Days recognized' );
// get values
var savingPrice = 0;
var msrp = $('input[name="msrp"]').val();
var periodPrice = $('input[name="days"]:checked').data('price');
var userLocale = $('input[name="userLocale"]').val();
console.log ( 'UserLocale' + userLocale);
// calculate bac
savingPrice = (msrp-periodPrice).toFixed(2);
if(userLocale === 'nl')
{
savingPrice = savingPrice.replace(/\./g, ',');
periodPrice = periodPrice.replace(/\./g, ',');
}
$('#CalculateSavings').text('€ ' + savingPrice);
$('#CalculatePrice').text('€ ' + periodPrice);
});
});
The console is showing:
Function loaded
And not more than this, even not when the radio button is changed.
What am i doing wrong?
I believe the problem is not with your code per se, but how it interacts with the code contained with custom-form-elements.js
It seems that your radio buttons are hidden behind styled span elements, to improve the look and feel of the form. However, from a DOM perspective, the actual element that the user clicks on is not the radio button, but the span element.
The custom-form-elements script does some funky stuff behind the scenes to make it look like the radio button has been selected, but a change event is never fired on the radio button.
In order to get around this, you'll need to add something like the following to your $(document).ready():
$("span.radio").click(function () {
$(this.nextSibling).trigger('change');
});
This will add a click event handler to the span masks that will fire the change event on their corresponding radio buttons. Looking at your HTML, this.nextSibling always refers to the radio button next to the span.

Categories