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>
Related
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.
I have been trying this for hours(I am new to web development). I need to access a table which contains many columns one of which contains rows of people's names, and put them in a data structure. In each row the id for the text which holds the person's name is setup like this:
<span class="myClass" id = "first"> JOHN DOE </span> == $0
<span class="myClass" id = "second"> BOB DAVID </span> == $0
These rows are very, very deep inside of a table of tables of tables, etc...
I tried
var n = document.getElementsByClassName(".myClass");
and
var n = document.querySelectorAll(".myClass");
and
n = $(".myClass");
but have not had any luck.
Is there a different way to access certain classes/ids deep inside this structure?
EDIT: There were multiple close answers, but I accepted the one by the user most willing to help, and tailored mostly for my particular circumstance.
Update
There's a possibility that .PSLONGEDITBOX is created dynamically and that it doesn't exist in the DOM when script is invoked. The updated demo will invoke the script onDOMReady and then a second time at onload which is the latest load event possible.
Details are commented in demo
Demo
// This loads dataArray() when DOM is ready
$(function() {
var onDOM = dataArray();
console.log('onDOMReady: ' + onDOM);
});
function dataArray() {
// Declare empty array
var boxArray = [];
/* .each() .PSLONGEDITBOX extract it's text
|| with .text() method then
|| .push() extracted text into the empty array
*/
$('.PSLONGEDITBOX').each(function(idx, box) {
let content = $(this).text();
boxArray.push(content);
});
return boxArray;
}
function onLoadEvent(fnc) {
// assign any functions on 'window.onload' to a var
var onLoad = window.onload;
// if there isn't any function on 'window.onload'...
if (typeof window.onload != 'function') {
// Assign fnc to it...
window.onload = fnc;
let F = fnc();
console.log('onLoad: ' + F);
// Otherwise...
} else {
window.onload = function() {
// Call the function that's there already...
onLoad();
console.log('Original function loaded...');
// ...then call fnc
fnc();
let F = fnc();
console.log('onLoad: ' + F);
}
}
}
/* Both expressions will run dataArray after everything
|| else has loaded. This is the onload event, which is
|| the most thorough of loading events and the slowest.
|| Besides being the last event, it's other major con
|| is that only one function can be called, any others
|| called before the last function called is overridden.
|| The function onLoadEvent() is designed to find any
|| previously assigned function or method to the onload
|| event and then invoke it first, then invoke any
|| given function afterwards.
*/
/* add a '/' to enable expression below.
var onLoad = dataArray();
window.onload = console.log('onLoad Event: ' + onLoad);
/*/
//* Remove a '/' to disable function below
onLoadEvent(dataArray);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id='A'>
<tr>
<tr>
<td>
<td>
<td>
<td>
<td>
<td>
<td>
<td>
<tr>
<td>
<tr>
<td>
<tr>
<td>
<table id='B'>
<table id='C'>
<tr>
<td><span class='PSLONGEDITBOX'>ABC</span>
<tr>
<td><span class='PSLONGEDITBOX'>DEF</span>
<tr>
<td><span class='PSLONGEDITBOX'>GHI</span>
<tr>
<td><span class='PSLONGEDITBOX'>JKL</span>
<tr>
<td><span class='PSLONGEDITBOX'>MNO</span>
</td>
</td>
</td>
</tr>
</td>
</td>
</tr>
</table>
</table>
</td>
</tr>
Old
Try .each() jQuery method on the .PSLONGEDITBOX class and extract the text with the .text() method.
This
n = $(".PSLONGEDITBOX");
should work. but it won't return the text, it returns the SPAN element as an object. to get the text you need
n = $(".PSLONGEDITBOX").text();
I don't think it depends on the structure of your HTML. Do you use $(document).ready? Or maybe you should include your js file near closing body on your page.
I'm writing some JavaScript to clone a table row containing form elements.
It's working well so far but there's one piece I can't quite figure out.
The element names have a number which increases with every row.
E.g:
<table>
<tbody>
<tr>
<td><input type="text" name="name[0][abc]" /></td>
<td><button class="add-row-button">+</button></td>
</tr>
<tr>
<td><input type="text" name="name[1][abc]" /></td>
<td><button class="add-row-button">+</button></td>
</tr>
</tbody>
</table>
I need the cloned row to update the number. There are multiple fields in each row which need this updated number so I can't just include the new name in the jQuery code. What I think has to happen is I need get the name, use a regex replace, then update the attribute.
Here's my current (simplified for the example) jQuery:
// Current num of elements. Names are 0 based so this will be the number used
// for the new name.
var formRowCount = $('table tr').length;
$('.add-row-button').click(function() {
// Clone the last row.
$(this).closest('tr').last().clone().insertAfter($(this).closest('tr'));
// Set the new field selector.
var $newRow = $(this).closest('tr').next();
$newRow.find('input[type="text"]').val('');
formRowCount++;
});
Can someone point me in the right direction. Before formRowCount++; I need to get the current element name and update the number with formRowCount.
Yeah, you can use regex if you want.
var formRowCount = $('table tr').length;
$('.add-row-button').click(function() {
// Clone the last row and insert it.
$(this).closest('tr').last().clone().insertAfter($(this).closest('tr'));
// Select the input field
var $newInput = $(this).closest('tr').next().find('input[type="text"]');
// Update the input value and name attribute
var newName = $newInput.attr('name').replace(/^(name\[)\d+(\].+)$/, '$1' + formRowCount + '$2');
$newInput.val('').attr('name', newName);
// Update the number
formRowCount++;
});
I have this table in my HTML:
<table class="dataTable" id="repaymentShedule">
<thead>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
<th>5</th>
<th>6</th>
<th>7</th>
<th>8</th>
</tr>
</thead>
<tbody data-bind="foreach: creditDetails">
<tr>
<td class="paymentDate" data-bind="text: dateOfPayment"></td>
<td class="startBalance" data-bind="text: beginingBalance"></td>
<td class="monthlyInt" data-bind="text: monthlyInterest"></td>
<td class="principal"><input data-bind="value: princpalPayment"></input></td>
<td class="monthlyInst" data-bind="text: monthlyInstallment"></td>
<td class="remainingBalance" data-bind="text: endingBalance"></td>
<td class="paid"><input type="checkbox" data-bind="checked: isPaid, disable: isPaid, click: testFunc, value: true"></td> <!-- value: true moje da ne e nujno -->
<td class="currentDate" data-bind="text: currentDate"></td>
</tr>
</tbody>
</table>
The values are comming from knockout js bindings.
and I'm trying to get all the values of the principal class with the function below:
updateValues = function(){
$("tbody").find("tr").each(function() {
var principal = $(this).find('td.principal').val();
console.log(principal);
});
};
Bu the console returns: (an empty string)
EDIT:
The above function works without any problems on the paymentDate class only by changing the .val() to .text()
I'm pretty sure that I'm not getting the value the right way, or that the binding is not allowing me to get the current value, but I'm really not able to spot the issue
You need to do this:
var principal = $(this).find('td.principal :input').val();
to get the value of the input element inside the table cell with class principal.
Also, as per the .val() API Documentation :-
The .val() method is primarily used to get the values of form elements
such as input, select and textarea. In the case of elements, the .val() method returns an array
containing each selected option; if no option is selected, it returns
null.
Hence, you are getting empty string in console while using your code.
The above function works without any problems on the paymentDate class
only by changing the .val() to .text()
This also explains why you got the correct value after changing the .val() to .text() for the paymentDate table cell, as it does not have any input element inside it.
<td class="principal"><input data-bind="value: princpalPayment"></input></td>
You don't need a closing </input> tag, as input elements are self-closing.
And you just need to target better.
var principal = $(this).find('td.principal input').val();
If you're using KnockoutJS you probably don't need to use jQuery at all. Get the correct value from your ViewModel, something like this:
updateValues = function() {
var details = MyMainViewModel.creditDetails();
for (var i = 0; i < details.length; i++) {
var principal = details[i].princpalPayment();
console.log(principal);
}
};
No dependency on your view, and thus unit testable. In addition, if you put this function in the correct bit of scope (e.g. the observable bound to the data table) you'll have access to all the relevant other observables when you want to use the result.
your not looking for the input value your looking at the td value which clearly doesnt exist
here is a jsfiddle with the fixed jquery
http://jsfiddle.net/krxva/
updateValues = function(){
$("tbody").find("tr").each(function() {
var principal = $(this).find('td.principal').find('input').val();
console.log(principal);
});
};
var principal = $(this).find('td.principal').val();
console.log(principal);
Above willn't work because td has an input element also.
Since you want value of input element inside that td, so use like this :
var principal = $(this).find('td.principal input').val();
// Or use this
var principal = $(this).find('td.principal > input').val();
console.log(principal);
Refer this for understanding
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();