I have multiple inputs on my website.
The inputs created with createElement.
I can give every input class, id and etc.
My goal: every time the user inserts new input (amount of products) it will calculate the overall price without any click, just automatic calculation(object price * amount in the input).
I would post the code, but I think image will explain it better:
How can I do the onchagne with getElementByTagName.
Example will be grate. Thank you !
You can use event delegation. Several events -- like "change" -- on your input elements will bubble up to container elements, up to the root of the DOM. So identify which is the common ancestor element, and listen there for the event you are interested in. I will choose the "input" event, as it triggers on any change the user makes, via any way of input:
document.addEventListener("input", function() {
// make calculation here:
});
This way you only need to attach one listener.
You can do something like this
function changeHandler() {
// on change handler
}
const inputs = [...document.getElementsByTagName('input')];
inputs.forEach(input => input.addEventListener('click', changeHandler));
You can do this with classes, which is better than applying your job to all your inputs.
I hope is something like this do you need :
function addInputListener(input) {
//#todo Replace this by your data
let row = input.parentElement.parentElement;
let overallPriceElement = row.querySelector('.overall-price');
let price = parseInt(row.querySelector('.price').innerText);
let calcEvent = function() {
//#todo Put your calc function here
if (this.value > 0) {
overallPriceElement.innerText = (price * this.value).toString();
} else {
overallPriceElement.innerText = "No products yet";
}
};
input.addEventListener('input', calcEvent);
calcEvent.call(input); // call() is here to add input context
}
// It's better to use class instead tag to do your job
let inputs = document.querySelectorAll('.amount');
// But you can also use tag do this
//let inputs = document.querySelectorAll('input');
for (let i = 0; i < inputs.length; i++) {
let input = inputs[i];
addInputListener(input);
}
<table>
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Price</th>
<th>Amount</th>
<th>Overall Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Bread</td>
<td class="price">3</td>
<td><input type="number" class="amount"></td>
<td class="overall-price"></td>
</tr>
<tr>
<td>2</td>
<td>Bread</td>
<td class="price">10</td>
<td><input type="number" class="amount"></td>
<td class="overall-price"></td>
</tr>
<tr>
<td>3</td>
<td>Bread</td>
<td class="price">30</td>
<td><input type="number" class="amount"></td>
<td class="overall-price"></td>
</tr>
</tbody>
</table>
You can call function addInputListener(input) each time you create new row pass directly your new input created by createElement to add these listeners.
Related
With the code below, I don't seem to be able to just set the textbox to the value of an TD element. What I need to achieve is to populate Enter Refund Amount box with the already present value of Grand Total field above. Nothing else is needed except copying the content from one element to the other.
window.onload = function() {
var src = document.getElementById("grand_total").innerHTML;
dst = document.getElementById("refund_amount").innerHTML;
src.addEventListener('#refund_amount', function() {
dst = src;
});
};
Firstly, #refund_amount isn't a valid event name. Given the context of the code and your goal I would assume that should be click instead. You also need to bind the event handler on the Element reference, not the a string variable containing its innerHTML value. In addition, to set the value of an input element you need to use the value property of the Element directly. Try this:
var src = document.getElementById("grand_total");
var dst = document.getElementById("refund_amount");
src.addEventListener('click', function() {
dst.value = src.textContent;
});
<table>
<tbody>
<tr>
<td>Grand total:</td>
<td id="grand_total">26.58</td>
</tr>
<tr>
<td>Refund amount:</td>
<td><input type="text" id="refund_amount" /></td>
</tr>
</tbody>
</table>
How can I get the value of an specific input field with Javascript?
Lets take this shopify shop for example: https://geekymate.com/products/magic-doormat-1?variant=18941211607138
I am trying to create a script which is automatically applying an discount code based on the quantity filled in the quantity field.
But to do that I need to be able to get the latest value of the field.
How would the code look like to get the latest/current value?
EDIT: Thank you for the hint with the question. I do know that I need to use getElementById ( For the linked page above it would be this: var x = document.getElementById("Quanity").value; ) but how do I always get the latest input automatically if the enduser is changing the value?
The other answers are also correct (using jQuery .keyup), but you can also use this solution below (which is better). This solution uses pure javascript.
The code selects the element by using .getElementById() and uses .addEventListener() to do something when input changes.
var text = document.getElementById("text");
window.onload = function() {
text.addEventListener("input", function() {
console.log(text.value);
});
}
<input id="text" />
Or you can use the following if you want a jQuery solution. This uses jQuery .bind().
$("#text").bind("input", function() {
console.log($("#text").val());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="text" />
keyup() function ;)
It runs each time, when user types new text.
Also, you can use input() or change() functions.
In jQuery it works like this:
$(document).on('keyup', '#InputID', function(){
//...code...
var discount = Number( document.getElementById('InputID').value )*10/100;
});
It's a Jquery function that runs on keypress. I've included a snippet below to see how it would tie in with an input field.
$('#code').keyup(function() {
var discountcode = this.value;
console.log(discountcode);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="code" type="test" />
Keyup runs every time a specific element is lifted. Imagine someone enters 'Hello'
You will see the following logged:
'H' 'He' 'Hel' 'Hell' 'Hello'
look at the code snippet. using JavaScript to get the values. and can use addEventListener to detect the change and use detectChange function to get the latest values.
var discount = [];
function detectChange() {
var table = document.getElementsByClassName("shappify_qb_grid")[0];
for (var i = 0; i < table.rows.length; i++) {
var row = "";
for (var j = 0; j < table.rows[i].cells.length; j++) {
if (j == 1) {
row = table.rows[i].cells[j].innerHTML;
rate = parseFloat(row);
if (rate && discount.indexOf(rate) < 0) {
discount.push(parseFloat(row));
console.log('---', parseFloat(row));
}
}
// console.log('discount : ', discount);
}
}
}
detectChange();
console.log('discount : ', discount);
<table class="shappify_qb_grid" border=1>
<thead>
<tr>
<th>Qty</th>
<th>Discount</th>
</tr>
</thead>
<tbody>
<tr>
<td>Buy 1</td>
<td>0% Off</td>
</tr>
<tr>
<td>Buy 2</td>
<td>10% Off</td>
</tr>
<tr>
<td>Buy 4</td>
<td>12% Off</td>
</tr>
<tr>
<td>Buy 5</td>
<td>14% Off</td>
</tr>
<tr>
<td>Buy 6</td>
<td>17% Off</td>
</tr>
</tbody>
</table>
This work for me!
document.getElementById("text").value;
<input id="text" />
Use the document.getElementById(); -command to get the existence of the referenced element in your HTML page. Then use the same technique of assigning attributes in the original HTML coding rules.
Use document.getElementById('able').value = 'whatever';.
I have a page that has a table and a small form. The table has some data on questionnaires. I am trying to use jquery to loop through the table, checking if a condition is met, then adding it to the correct field of the form. The problem I have is that the forms are not created by me so I cant match them to set id's. So i need to get the field_id from relate, and the answer inserting into that location. Im new to Jquery and js. This is what I came up with.
html
<div align="left">
<table class="table table-striped">
<thead>
<td>Question</td>
<td>Answer</td>
<td>Relates to</td>
</thead>
<tbody>
<tr>
<td>Random question 1</td>
<td>Random answer 1</td>
<td>add to variable form field</td>
</tr>
<tr>
<td>Random question 2</td>
<td>Random answer 2</td>
<td>add to a different form field</td>
</tr>
</tbody>
</table>
</div>
<input type="text" id="variable id that could be matched with element of table">
main.js
table.find('tr').each(function (i, el) {
var $mylists = $('#' + relate)
$mylists.html('');
var $tds = $(this).find('td'),
label = $tds.eq(0).text(),
relate = $tds.eq(1).text(),
answer = $tds.eq(2).text();
$('<span></span>').text(answer).appendTo($mylists);
});
Since you have a single input that you want to append values you, you need to set the val of the input. And since you want to create that single input value from multiple other values (answers), you need to loop through, get all your answers, then combine them into a single value. Something like this:
var $mylists = $('#' + relate);
$mylists.val('');
var answers = [];
table.find('tr').each(function (i, el) {
var $tds = $(this).find('td'),
label = $tds.eq(0).text(),
relate = $tds.eq(1).text(),
answer = $tds.eq(2).text();
answers.push(answer);
});
// at this point, answers contains an array of all your individual answer values.
// decision time: what do you want to do with them?
// in this example, I join them together in a comma-delimited list.
$mylists.val( answers.join(', ') );
I am trying to develop a plugin for jQuery. This is my first plugin, and I am stuck in the initial phase.
I need to do following things: I need to find the "add row" link from the table and bind to the click event. When the link is clicked, it should add a new row by cloning the existing template row. Initially the template row is hidden.
Following is the HTML.
<table id='grid1'>
<tr>
<td><a href='#' id='add_row'>Add New Row</a></td>
</tr>
<tr>
<td>
<table id='data_table'>
<tr><th>Col1</th><th>Col2</th><th>Col3</th></tr>
<tr><td>Data1</td><td>Data2</td><td>Col3</td></tr>
<tr id='template_row'>
<td><input type='text' /></td>
<td><input type='text' /></td>
<td><input type='text' /></td>
</tr>
</table>
</td>
</tr>
</table>
And my jQuery so far:
(function($) {
$.extend($.fn, {
editableGrid: function() {
function addRow() {
//code to clone here but i need the instance of main table here ie grid1
}
this.find('#add_row').bind("click",addRow);
}
});
})(jQuery);
You need to .detach() the template from the table and put it on a factory variable, like:
var factory = $('#template_row').detach();
factory.removeAttr('id'); // Suggestion for Tomalak
It will hidden (not really) from the table. Next step is bind click on your link and specify here will go the new factory.clone item. Like:
$('button.new-link').click(function(){
$('#data_table').append(factory.clone(true));
});
Take a look too in .clone() and plugin authoring
Going on from your current code:
(function($) {
$.extend($.fn, {
editableGrid: function() {
this.find("a.add_row").click(function () {
var $table = $(this).parent("table").find("table.data_table");
var $newRow = $table.find("tr.template_row").clone();
$newRow.removeClass("template_row"); // !!!
$table.append($newRow);
return false;
});
}
});
})(jQuery);
Notes
work with CSS classes instead of IDs - only that way you can have multiple "editable grids" on one page
there is no benefit of using bind() over using click() here
you can pass functions directly as arguments - no need to define them separately
it can improve readability/clarity to use verbose selectors ("a.add_row" is better than just ".add_row")
in the outer function, this refers to a jQuery object containing all matched elements, so click() binds all of them in one step.
in the inner function, this refers to an individual DOM element (i.e. the clicked link) - it is not a jQuery object here!
don't forget to return false from the click function to prevent the browser default behavior
it's useful to prepend variables with a $ to denote that they contain a jQuery object
No need for a plugin just do this:
$('#add_row').click(function(){
var clone = $('#template_row').clone();
clone.removeAttr('id');
clone.appendTo('#data_table');
})
Here is a demo: http://jsfiddle.net/Jw5TF/
$.fn.myTableTingPlugin = function() {
var self = this;
$(self).find(".template_row").hide(); // or use css class
$(this).find(".add_row").click(function() {
// shuld probebly not use ids if its a plugin
// so i use a class here
var newRow = $(self).find(".template_row").clone();
$(self).find(".data_table").append(newRow);
});
};
First, don't use ids, classes are better. And double quotes are better too.
<table class="extendableTable">
<tr>
<td>Add New Row</td>
</tr>
<tr>
<td>
<table id="data_table">
<tr><th>Col1</th><th>Col2</th><th>Col3</th></tr>
<tr><td>Data1</td><td>Data2</td><td>Col3</td></tr>
<tr id='template_row'>
<td><input type="text" /></td>
<td><input type="text" /></td>
<td><input type="text" /></td>
</tr>
</table>
</td>
</tr>
</table>
Source code of the plugin:
(function($) {
$.fn.extendableTable = function(options){
var table = this;
this.find('.extendLink').click(function(){
table.find('.dataTable .templateRow:first').clone().appendTo(table.find('.dataTable'));
return false;
});
}
})(jQuery);
And then you can use plugin in such a way:
$('.extendableTable').extendableTable();
I've been messing around with different forms and tables, now I need something that takes data from table tr and td field, runs a if statement on each fetched item, and outputs text inside the form, depending what was found in td fields.
So right now I have something like this, which doesn't do anything useful at all, for now, just outputs td-01 class values into the form:
var test;
$('tbody tr').each(function(index) {
test = $(this+'.td.td-0');
$('fieldset.csc-mailform').after($('td.td-0'));
});
and my table structure looks something like this:
<table class="contenttable contenttable-3 tabel">
<tr class="tr-even tr-0">
<td class="td-0">01</td>
<td class="td-1">Valik 1</td>
<td class="td-last td-2">150€</td>
</tr>
<tr class="tr-odd tr-1">
<td class="td-0">01</td>
<td class="td-1">Valik 2</td>
<td class="td-last td-2">50€</td>
</tr>
<tr class="tr-even tr-2">
<td class="td-0">01</td>
<td class="td-1">Valik 3</td>
<td class="td-last td-2">170€</td>
</tr>
<tr class="tr-odd tr-3">
<td class="td-0">01</td>
<td class="td-1">Valik 4</td>
<td class="td-last td-2">88€</td>
</tr>
</table>
Right now it only find tr tags and outputs all of them. I need it to split the tr tag up, run if condition on td-0 to determine if it needs to be radio button/text input/checkbox etc, then see what td-1 contains and make that field name, then td-2 is for example a price. all of this should end up in a form.
So as you can see, I am stuck with jQuery, but I think it should be doable.
edit:
I got something like this after messing around a little, but my if statements don't seem to work on jQuery objects, any way to get around this?
var check1;
$('tbody tr').each(function(index) {
//test = $(this+'.td.td-0');
check1 = $('td.td-0');
alert(check1);
if(check1=='01'){
content_type="checkbox";
}else if(check1=='02'){
content_type="text";
}else{
content_type="none";
}
$('fieldset.csc-mailform').after(content_type);
//$('fieldset.csc-mailform').after($('td.td-0'));
});
//edit2
Ugh, I was running if statement against jQuery object, of course it didn't work.
I got it working with this, looks quite nasty, but it seems to work:
$('tr').each(function () { var val = $(this).children('td:first').text();
//$check1 = $('td.td-0');
if(val=='01'){
content_type="checkbox";
}else if(val=='02'){
content_type="text";
}else{
content_type="none";
}
$('fieldset.csc-mailform').after(content_type + '<br/>');
}
);
Now, I need to figure out how to create input fields from these.
You could possibly make it a bit cleaner by using the jQuery selector context, e.g.:
$('tr').each(function () {
var val = $('td:first', this).text();
..
}
Something like this will do:
$('table tr').each(function() {
$tds = $(this).children();
for(var i=0;i<$tds.length;i++){
$td = $tds[i];
if($td.hasClass('td-0'){
//do your thing by getting next TD or something else
break;
}
}
});