how to get work with dynamically inserted fields - javascript

i have the below div class 'labouritems' which gets a new instance of it inserted into the dom each time the user clicks on a button.
I need to be able to calculate the '.rate' and '.hours' fields and set the answer to the '.total' field.
Now this is for only the instance of 'labouritems' that the user is working on, ie: should not update the field total on another instance' so basically just work within that row.
Below is the html that i'm working with and below that is the code i have which only works for the first instance of 'labouritems' but when i insert a new one it does not do anything.
<div class="labouritems">
<label for="quote_labouritems_attributes_0_description">Description</label>
<input class="input-medium" id="quote_labouritems_attributes_0_description" name="quote[labouritems_attributes][0][description]" size="30" type="text" value="concrete the house">
<label for="quote_labouritems_attributes_0_hours">Hours</label>
<input class="input-mini hours" id="quote_labouritems_attributes_0_hours" name="quote[labouritems_attributes][0][hours]" size="30" type="text" value="33">
<label for="quote_labouritems_attributes_0_total">Total</label>
<input class="input-mini total" id="quote_labouritems_attributes_0_total" name="quote[labouritems_attributes][0][total]" size="30" type="text" value="1089">
<label for="quote_labouritems_attributes_0_Mup/Hr">Mup/hr</label>
<input class="input-mini" id="quote_labouritems_attributes_0_muphourrate" name="quote[labouritems_attributes][0][muphourrate]" size="30" type="text" value="0">
<label for="quote_labouritems_attributes_0_Mup/Total">Mup/total</label>
<input class="input-mini" id="quote_labouritems_attributes_0_muptotal" name="quote[labouritems_attributes][0][muptotal]" size="30" type="text" value="0">
<label for="quote_labouritems_attributes_0_Mup/%">Mup/%</label>
<input class="input-mini" id="quote_labouritems_attributes_0_muppercent" name="quote[labouritems_attributes][0][muppercent]" size="30" type="text">
<label for="quote_labouritems_attributes_0_Contractor">Contractor</label>
<input class="input-small" data-autocomplete="/contractors/autocomplete_contractor_firstname" data-update-elements="{"id":"#quote_labouritems_attributes_0_contractor_id","hourly_rate":"#quote_labouritems_attributes_0_contractor_rate"}" id="quote_labouritems_attributes_0_contractor_name" name="quote[labouritems_attributes][0][contractor_name]" placeholder="Seach" size="30" type="text" value="bing lee">
<input id="quote_labouritems_attributes_0_contractor_id" name="quote[labouritems_attributes][0][contractor_id]" type="hidden" value="1">
<label for="quote_labouritems_attributes_0_Rate/hr">Rate/hr</label>
<input class="input-mini rate" id="quote_labouritems_attributes_0_contractor_rate" name="quote[labouritems_attributes][0][contractor_rate]" size="30" type="text" value="33">
<label for="quote_labouritems_attributes_0_Work %">Work %</label>
<input class="input-mini" id="quote_labouritems_attributes_0_progress_percent" name="quote[labouritems_attributes][0][progress_percent]" size="30" type="text" value="55">
<label for="quote_labouritems_attributes_0_Work $">Work $</label>
<input class="input-mini" id="quote_labouritems_attributes_0_progress_payment" name="quote[labouritems_attributes][0][progress_payment]" size="30" type="text">
<input id="quote_labouritems_attributes_0__destroy" name="quote[labouritems_attributes][0][_destroy]" type="hidden" value="false">Delete
</div>​
var LabourItems = {
rate: null,
hours: null,
total: null,
init: function(object) {
this.rate = parseInt($(object).children('.rate').first().val(), 10);
// var rate = $(object).children('.rate').first();
this.hours =parseInt($(object).children('.hours').first().val(), 10);
this.total = this.rate * this.hours;
this.updateTotal(object);
},
updateTotal: function(object) {
$(object).children('.total').first().val(this.total || 0);
}
}
//reactTochange for those inputs that you want to observe
$('.hours').on("keyup", function() {
$('.labouritems').each( function(key,value){
LabourItems.init(this);
});
});

try
$(documents).on("keyup", '.hours', function() {
LabourItems.init(this.closest('.labouritems'));
});
this will
1. attach hours.keyup event on document, instead of every hours element
2. update total for only changed element

Related

Creating multiple HTML elements with JavaScript. Dynamic forms?

I'd like to insert a block of HTML into the DOM when a checkbox or radio button or button is pressed.
For example, when a button is pressed, then another set of the labels and inputs below are added to the form.
<form class="details">
<div>
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname">
<label for="job">Job:</label><br>
<input type="text" id="job" name="job"><br>
<label for="id">ID:</label><br>
<input type="text" id="id" name="id">
<label for="shoesize">Shoe size:</label><br>
<input type="text" id="shoesize" name="shoesize"><br>
<label for="helmetsize">Helmet size:</label><br>
<input type="text" id="helmetsize" name="helmetsize">
</div>
</form>
Every time a button is pressed I'd like another set of fields where someone else can add their details to the form.
I am aware of document.createElement(), but it seems like I can only create 1 element at a time using that. This form will probably grow and so would like something less verbose.
I've experimented with appendChild() e.g.
var details = document.getElementsByClassName('details')[0]
var newDetailsSection = '<div>
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname">
<label for="job">Job:</label><br>
<input type="text" id="job" name="job"><br>
<label for="id">ID:</label><br>
<input type="text" id="id" name="id">
<label for="shoesize">Shoe size:</label><br>
<input type="text" id="shoesize" name="shoesize"><br>
<label for="helmetsize">Helmet size:</label><br>
<input type="text" id="helmetsize" name="helmetsize">
</div>'
details.appendChild(newDetailsSection)
But I am getting an error because newDetailsSection is not of type Node - it is a string and I understand that.
I am new to web development.
Is this a use case for a JS framework that handles components? Is this what a component is?
if u want to add html string; innerHTML is your friend.
to append use details.innerHtML = details.innerHtML + newSectionHTML;
ofcourse i would recommend using document.createElement and create a function that returns element that contain label:
example:
function creatInput(name, label){
const labelElm = document.createElement('label');
const inputElm = document.createElement('input');
labelElm.setAttribute('for', name);
labelElm.innerText = label+':';
inputElm.setAttribute('name', name);
inputElm.setAttribute('id', name);
inputElm.setAttribute('placeholder', label);
labelElm.appendChild(input);
return labelElm;
}
this way you can reuse it for all your input simply call:
var details = document.querySelector(".details");
details.appendChild( createInput('fname','First name') );
details.appendChild( createInput('lname','Last name') );
/// .. etc

the function i set for my html button isn't working

i set a function for my button but the button doesn't follow it and it isn't being used anywhere else either
<div id="main2" class="main">
<form>
<label class="Courier" for="EventName"></label><br/>
<input class="Courier" required type="text" id="EventName" placeholder="Event name"><br/>
<input class="Courier" required type="Text" id="location" placeholder="venue"><br/>
<input class="Courier" required type="Text" id="DateAndTime" placeholder="Date and time"><br/>
<input class="Courier" required type="Text" id="Duration" placeholder="Duration"><br/>
<input class="courier" required type="Text" id="Clothing" placeholder="Dress code"><br/>
<input class="courier" required type="Text" id="Food" placeholder="Food"><br/>
<textarea class="courier" id="Notes" name="Notes" rows="4" cols="50">Enter additional notes here</textarea><br/>
<button id="submitEvent">Submit</button>
</form>
<br/>
<div id="newEvent"></div>
</div>
Javascript for the button below
$('#submitEvent').on('click' , function submitEvent(){
var event = $('#EventName');
var location = $('#location');
var DateAndTime = $('#DateAndTime');
var Duration = $('#Duration');
var Clothing = $('#Clothing');
var Food = $('#Food');
var Notes = $('#Notes');
var data ={
event: event,
location:location,
DateAndTime: DateAndTime,
Duration: Duration,
Clothing: Clothing,
Food: Food,
Notes: Notes
};
var eventRef = database.ref('Events');
var newEventRef = eventRef.push(data, function(err) {
if (err) {
console.error('Error Saving Data', err)
}
else{
console.log('success saving data');
$('#EventName').val('');
$('#location').val('');
$('#DateAndTime').val('');
$('#Duration').val('');
$('#Clothing').val('');
$('#Food').val('');
$('#Notes').val('');
}
})
})
i expect it to submit this to at least put on the console that the upload to firebase was successful or not but it doest do either it just refreshes my page to index.html and instead of the usual url it will be http://localhost:63342/Event%20Planner/www/index.html?Notes=1
when its usually
http://localhost:63342/Event%20Planner/www/index.html
Change this:
$('#submitEvent').on('click' , function submitEvent(){
to this:
$(document).on('click', '#submitEvent', function(){
I presume you are using .on() because the #submitEvent button is added dynamically. However, you must attach the .on event to an element that already exists when the DOM is initially rendered -- $(document) is a safe and common choice.
Reference:
Event delegation
I recommend you use the submit method https://api.jquery.com/submit/
<form id="yourFormName">
<label class="Courier" for="EventName"></label><br/>
<input class="Courier" required type="text" id="EventName" placeholder="Event name"><br/>
<input class="Courier" required type="Text" id="location" placeholder="venue"><br/>
<input class="Courier" required type="Text" id="DateAndTime" placeholder="Date and time"><br/>
<input class="Courier" required type="Text" id="Duration" placeholder="Duration"><br/>
<input class="courier" required type="Text" id="Clothing" placeholder="Dress code"><br/>
<input class="courier" required type="Text" id="Food" placeholder="Food"><br/>
<textarea class="courier" id="Notes" name="Notes" rows="4" cols="50">Enter additional notes here</textarea><br/>
<button type="submit">Submit</button>
</form>
And then
$( "#yourFormName").submit(function( event ) {
alert( "Handler for .submit() called." );
event.preventDefault();
});
Cheers!

Javascript, how to get multiple elements of a form and add an attribute to them?

<form name="myform">
<fieldset>
<legend>Delivery Information</legend>
<p>Country: <input pattern="^[A-Za-z]" type="text" name="textInput" size="25" placeholder="input country..."></p>
<p>Street: <input pattern="^[A-Za-z0-9]" type="text" name="street" size="30" placeholder="input street..."></p>
<p>City: <input pattern="^[A-Za-z ]" type="text" name="textInput" size="20" placeholder="input city..."></p>
<p>Zip: <input pattern="(\d{5}([\-]\d{4})?)" type="text" name="zip" size="5" placeholder="#####"></p>
</fieldset>
</form>
So, I have a form and I want to get all input elements by name "textInput"(I have other inputs so it ha) using Javascrip DOM, and add an attribute "oninvalid="please, only use letters".
Only Javascript, so no JQuery.
You can use this function:
function changeAttributes() {
var x = document.getElementsByName("textInput");
for(var i = 0; i < x.length, i++) {
x[i].setAttribute("oninvalid", "please, only use letters");
}
}
Try below:
$('input[name=textInput]').attr("oninvalid", "please, only use letters");

Disable textbox if other textbox is not empty in CSS and JavaScript

I have a search form which contains text-boxes. What I want to ask is if textbox1(Hotel (num_rooms)) is not empty then the textbox2(Packages(num_days)) will be disabled or if textbox2(Packages(num_days)) is not empty then the textbox1(Hotel (num_rooms)) will be disabled. Because this search form will leads to different output based on the inputs of an user. If the user tries to put data in textbox1 and submit it, then it will return a lot of recommendations based on the user preferences about hotel same as in packages.
<form action="Filtered-SearchResult.php" method="post">
<div class="SearchForm">
<label id="Form"><h3 style="color:beige; text-align:left;">Search Form</h3></label><br>
<br>
<input type="text" name="location" class="searchtext" id="locate" placeholder="location" onkeyup="LettersOnly(this)" /><br>
<input type="text" name="from_budget" class="searchtext" placeholder="minimum budget" style="width:150px;" onkeyup="NumbersOnly(this)" />
<input type="text" name="to_budget" class="searchtext" placeholder="maximum budget" style="width:150px;" onkeyup="NumbersOnly(this)" /><br>
<input type="text" name="person" class="searchtext" placeholder="no of person" onkeyup="NumbersOnly(this)" /><br>
<input type="text" name="no_of_rooms" class="searchtext" style="width:150px;" placeholder="hotel(num_rooms)" onkeyup="NumbersOnly(this)" />
<input type="text" name="no_of_days" class="searchtext" style="width:150px;" placeholder="Packages(num_days)" onkeyup="NumbersOnly(this)" />
<script>
function LettersOnly(input) {
var regex = /[^a-zA-Z ]/gi;
input.value = input.value.replace(regex, "");
}
function NumbersOnly(input) {
var regex1 = /[^0-9]/gi;
input.value = input.value.replace(regex1, "");
}
</script>
<input type="submit" name="search1" value="Show Prices" id="Prices2" />
</div>
</form>
You can write a change event for no of rooms and no of days like this.
You can add more condition accordingly
$("#no_of_days").change(function(){
if($(this).val() == ""){
$("#no_of_rooms").attr("disabled", false);
}else{
$("#no_of_rooms").attr("disabled", true);
}
});
$("#no_of_rooms").change(function(){
if($(this).val() == ""){
$("#no_of_days").attr("disabled", false);
}else{
$("#no_of_days").attr("disabled", true);
}
});

How can i make a simple form to calculate quantity x's a fixed rate?

Ok, I have a good understanding of how javascript works, but not how to implement it. I have a simple form that needs to calculate on the fly the price of x number of tickets at 75.00 each. Let's say form id is quantity & total, with 75.00 being a rate. What would be the script to execute this and where should I add it.
The pertinent HTML is this:
<form id="docContainer" enctype="multipart/form-data" method="POST" action=""
novalidate="novalidate" data-form="preview">
<label id="item4_label_0" ># of Tickets</label>
<input type="text" id="quantity" maxlength="254" data-hint="" name="quantity" required/>
<label id="item13_label_0">Price Per Ticket</label>
<input name="item_price" type="text" id="item_price" placeholder="75.00"
maxlength="254" readonly data-hint="75.00"/>
<label id="item14_label_0" >Total</label>
<input name="total_price" type="text" id="total_price" maxlength="254" readonly/>
<input type="submit" class="fb-button-special" id="fb-submit-button" value="Submit" />
</form>
Your inputs don't have ids so I've used their names. This is how you would do it with jQuery. I've forgotten how to write old school javascript, perhaps someone else can add to this.
<script src="jquery.js"></script>
<script>
$(function(){
$('input[name="quantity"]').on('change keyup', function(){
$('input[name="total_price"]').val($(this).val() * $('input[name="item_price"]').val());
});
});
</script>
goes before
</body>
Edit: Added the necessary stuff for jQuery, but this can be done with regular js.
<html>
<head>
<script>
window.onload = function() {
var calculSumToString = function calculSumToString() {
totalField.value = (qtyField.value * itemPriceField.value).toFixed(2) + " $";
};
var totalField = document.getElementById('total_price');
var qtyField = document.getElementById('quantity');
var itemPriceField = document.getElementById('item_price');
qtyField.onkeyup = calculSumToString;
itemPriceField.onkeyup = calculSumToString;
};
</script>
</head>
<body>
<form id="docContainer" enctype="multipart/form-data" method="POST" action=""
novalidate="novalidate" data-form="preview">
<label id="item4_label_0" ># of Tickets</label>
<input type="text" id="quantity" maxlength="254" data-hint="" name="quantity" required/>
<label id="item13_label_0">Price Per Ticket</label>
<input name="item_price" type="text" id="item_price" value="75.00"
maxlength="254" readonly data-hint="75.00"/>
<label id="item14_label_0" >Total</label>
<input name="total_price" type="text" id="total_price" maxlength="254" readonly/>
<input type="submit" class="fb-button-special" id="fb-submit-button" value="Submit" />
</form>
</body>
</html>

Categories

Resources