Adding rows to a table with jQuery - javascript

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();

Related

Copy content from <td> into a text box using jQuery

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>

Onchange on a lot of inputs JS vanilla

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.

Pass php variable through JavaScript to another php page

I want to pass the id to the next page on clicking the entire row.
I tried to do it myself but I wasn't able to do so .
my code is below :
$( "#tablerow" ).click(function() {
var jobvalue=$("#jobid").val();
alert(jobvalue);
window.location.href = "jobsview.php?id=" + jobvalue;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tbody>
<tr id="tablerow">
<td><?=$srno?></td>
<td id="jobid"><?=$row['ID']?></td>
</tr>
</tbody>
</table>
val() method works for form elements like input, select etc.
Use text() method,
var jobvalue = $("#jobid").text();
Update
An HTML can have only one ID throughout the document. To enable click event for multiple elements and pass the one that is clicked onto another page, change ID attribute to class.
<table>
<tbody>
<tr class="tablerow" >
<td><?=$srno?></td>
<td class="jobid"><?=$row['ID']?></td>
</tr>
</tbody>
</table>
Then you can get the once clicked in JS as follows,
$( ".tablerow" ).click(function() {
/** $(this) will refer to current tablerow clicked
* .find(".jobid") will find element with class `jobid`
* inside currently clicked tablerow
*/
var jobvalue = $(this).find(".jobid").text();
alert(jobvalue);
window.location.href = "jobsview.php?id=" + jobvalue;
});

How to get innerText of each element deep inside multiple tables?(chrome extension)

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.

How to select value/innerHTML of a certain <td> within a certain <tr>? Using Javascript only. No jQuery

<table>
<tr>
<td>foo1</td>
<td>bar1</td>
<td><input type="button" id="button1" onClick="get(this);"></td>
</tr>
<tr>
<td>foo2</td>
<td>bar2</td>
<td><input type="button" id="button2" onClick="get(this);"></td>
</tr>
</table>
Goal: To get buttons button1 and button2 to trigger the same function get() which should get the value of the first <td> in the same <tr> the button resides in. Which is, in this case: foo1 and foo2 respectively.
This is a rough outline of the function which should help understand what I'm trying to achieve-
function get(element){
alert(element.tr.first_td.innerHTML);
}
I realize there was a jQuery solution to a similar problem. But I do not understand jQuery well enough to translate it back to JavaScript. If it is possible at all using JavaScript, please show me how.
Crawl up the parentNode twice to get to the tableRow element. From there, access the first td from the HTMLCollection of cells, and get the innerHTML value:
function find( element ) {
alert( element.parentNode.parentNode.cells[0].innerHTML );
}​
Fiddle: http://jsfiddle.net/jonathansampson/WuWnw/
Try this, since you have many tr and td tags right, so, you can do DOM Parsing. But you need to specify one ID for the table to get that table. For now lets call it foo-table.
var table = document.getElementById("foo-table");
var cells = table.getElementsByTagName("td");
for (var i = 0; i < cells.length; i++) {
alert(cells[i].innerHTML);
}
If you don't wanna give an ID and you are sure that there is only one table, then use this:
var table = document.getElementsByTagName("table");
var cells = table[0].getElementsByTagName("td");
for (var i = 0; i < cells.length; i++) {
alert(cells[i].innerHTML);
}
Enjoy! Hope this helps! :) No jQuery or any other plugin. Pure JavaScript. :)
<table>
<tr>
<td id="button1_value">foo1</td>
<td>bar1</td>
<td><input type="button" id="button1" onClick="get('button1_value');"></td>
</tr>
<tr>
<td id="button2_value">foo2</td>
<td>bar2</td>
<td><input type="button" id="button2" onClick="get('button2_value');"></td>
</tr>
</table>
You shoul identify what you want to get using an ID so that you can easily retrieve it. This also helps prevent the chance of getting erroneous data. If you give the component an id you should be able to use document.getElementById() to get that component.
function get(element){
var obj = document.getElementById(element)
alert(obj.innerHTML);
}

Categories

Resources