Sorry, if this is too basic.
I am trying to add rows to a table if current number of rows are
less than a user's demand.
At the same time, I need to delete the
extra rows if current number of rows are more than a user's need.
My code is working, but I think it does not make a lot of sense. So I am wondering if anyone could correct my mistakes and make my code more reasonable. (I was trying to use two indices to control this add or remove activity. One index check the current existed elements and get the difference between user's new input. Then do the add or remove movements. But I failed to do this.)
In addition, is it possible to adjust the width of added <td> without changing the shape of the first table row? Thanks for your help! Here is a demo.
HTML
<form method="post" id="form1" action=index.html>
<table class="tab tab_Application" border="0">
<tr>
<th>
<label for="id_noa">Number of Applications:</label>
</th>
<td>
<select name="noa" id="id_noa">
<option value="">Make a selection</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</td>
</tr>
<tr id='noa_header' style="display:none">
<th>App#</th>
<th>Month</th>
<th>Day</th>
<th>Mass Applied (kg/hA)</th>
<th>Slow Release (1/day)</th>
</tr>
</table>
</form>
JS
$(document).ready(function () {
var i = 1
$('#id_noa').change(function () {
var total = $(this).val()
$('#noa_header').show()
//I was trying to use two indices to control this add or remove activity. One index check the current existed elements and get the difference between user's new input. Then do the add or remove movements. But I failed to do this.
while (i <= total) {
$('.tab_Application').append('<tr class="tab_noa1"><td><input type="text" size="5" value="' + i + '"/></td><td><input type="text" size="5" name="mm' + i + '" id="id_mm' + i + '""/></td><td><input type="text" size="5" name="dd' + i + '" id="id_dd' + i + '""/></td><td><input type="text" size="5" name="ma' + i + '" id="id_ma' + i + '""/></td><td><input type="text" size="5" name="sr' + i + '" id="id_sr' + i + '" value="0""/></td></tr>');
i = i + 1;
}
while (i-1 > total) {
$(".tab_Application tr:last").remove();
i=i-1
}
$('</table>').appendTo('.tab_Application');
})
});
I took the ideas presented by #B3aT, edited, and fleshed out to make this (available at my fork of OP's jsfiddle:
var row_i = 0;
function emptyRow() {
row_i++;
this.obj = $("<tr></tr>");
this.obj.append('<td><input type="text" size="5" value="' + row_i + '"/></td>');
this.obj.append('<td><input type="text" size="5" name="mm' + row_i + '" id="id_mm' + row_i + '""/></td>');
this.obj.append('<td><input type="text" size="5" name="dd' + row_i + '" id="id_dd' + row_i + '""/></td>');
this.obj.append('<td><input type="text" size="5" name="ma' + row_i + '" id="id_ma' + row_i + '""/></td>');
this.obj.append('<td><input type="text" size="5" name="sr' + row_i + '" id="id_sr' + row_i + '" value="0""/></td>');
}
function refresh(new_count) {
if(new_count > 0) {
$("#noa_header").show();
}
else {
$("#noa_header").hide();
}
var old_count = parseInt($('tbody').children().length);
var rows_difference = parseInt(new_count) - old_count;
if (rows_difference > 0)
{
for(var i = 0; i < rows_difference; i++)
$('tbody').append((new emptyRow()).obj);
}
else if (rows_difference < 0)//we need to remove rows ..
{
var index_start = old_count + rows_difference + 1;
$('tr:gt('+index_start+')').remove();
row_i += rows_difference;
}
}
$(document).ready(function () {
$('#id_noa').change(function () {
refresh( $(this).val() );
})
});
The reason the emptyRow function is so long is that I wanted to make the number of columns easy to manipulate. Each column is appended individually, so changing the default pattern is simple.
In the html, I had to add the thead and tbody tags as described in #B3aT's answer. The thead includes the first two rows, because row 1 is the select box and row 2 is the actual header for the table. The tbody is empty to start.
As far as changing styles for individual rows (like adjusting column width), you'd be better off not using a table. Table-like behavior can be as simple as using float:left in your column style, making sure to place a div with clear:both at the end of each row.
At these situations jQuery excels, let us play with all sort of selectors.
First you need to separate the header and body of the table (thead and tbody).
(Code not tested).
function refresh(new_count) {
//how many applications we have drawed now ?
var old_count = parseInt($('tbody').children().count());
//the difference, we need to add or remove ?
var rows_difference = parseInt(new_count) - old_count;
//if we have rows to add
if (rows_difference > 0)
{
//$('tbody').append() or prepend() new empty rows based on your pattern with a loop
}
else if (rows_difference < 0)//we need to remove rows ..
{
var index_start = old_count - rows_difference;//for the LAST X rows
$('tr:gt('+index_start+')').remove();
}
}
Related
I have a table that has rows appended to it. Each row has a select in column 2 {0, 1, [2]}. I am trying to get the text/value/option of the select using JavaScript or JQuery. This seems like it should be something easy but for the life of me I cannot figure out a way to get the select element in the selected row & column. Any help would be greatly appreciated.
Here is my table.
<div id="table_container">
<table id="computer_table" class="service_table">
<thead id="header_container">
<th class="table_header">COMPUTER NAME</th>
<th class="table_header">LIVE/HIDE</th>
<th class="table_header">MODE</th>
<th class="table_header">RUN</th>
</thead>
<tbody id="table_body">
</tbody>
</table>
</div>
Here is my JavaScript that adds rows to the table. Rows contain a select in column 2.
row = $('<tr class="row_white"><td class="tb_pc_name">' + value.pc_name + '</td><td class="tb_live_hide">LIVE</td><td class="tb_mode">' +
'<select id="select_mode" class="select_dropdown">' +
'<option value="0">0 - DEFAULT</option>' +
'<option value="1">1 - CLEAN UP</option>' +
'<option value="2">2 - SIGN IN</option>' +
'<option value="3">3 - SIGN OUT</option>' +
'<option value="4">4 - UPDATE IPSW</option>' +
'<option value="5">5 - OPEN DMG DIRECTORY</option>' +
'</select></td>' +
'<td class="tb_btn"><button type="button" id="btn_run">RUN</button></td></tr>');
$("#computer_table").append(row);
After all rows have been appended, the user can make a selection from the select. There is a button in column 3 that when clicked should show an alert with the select option and value of the select on the same row. The code below should show the selected option and/or value of the select in the row of the cell that is clicked. I can get the row and column but cannot get the value of the select.
$("#computer_table td").click(function() {
var table = document.getElementById('computer_table');
var column_num = parseInt( $(this).index() );
var row_num = parseInt( $(this).parent().index() );
alert('test');
/*Error here.*******************************************************************************************/
var combo = table.rows[row_num + 1].cells[2].getElementById('select_mode');
//$("#select_mode option:contains("?").attr('selected', 'selected');
alert(combo.value);
});
If you changed your buttons to use a class rather than an id they could be triggered with this:
$("#computer_table").on("click", "button.btn_run", function(e) {
alert($(this).parent().prev().children().find(":selected").text());
});
First of all there is something wrong with youre code that add the row. Every ID must be unique and it's not the case. Try using a counter (or something else) to avoid that like this:
var numberRowAdded = 0;
row = $('<tr class="row_white"><td class="tb_pc_name">' + value.pc_name + '</td><td class="tb_live_hide">LIVE</td><td class="tb_mode">' +
'<select id="select_mode'+ numberRowAdded +'" class="select_dropdown">' +
'<option value="0">0 - DEFAULT</option>' +
'<option value="1">1 - CLEAN UP</option>' +
'<option value="2">2 - SIGN IN</option>' +
'<option value="3">3 - SIGN OUT</option>' +
'<option value="4">4 - UPDATE IPSW</option>' +
'<option value="5">5 - OPEN DMG DIRECTORY</option>' +
'</select></td>' +
'<td class="tb_btn"><button type="button" id="btn_run'+ numberRowAdded +'">RUN</button></td></tr>');
$("#computer_table").append(row);
numberRowAdded++;
Then to select what you want :
$("#computer_table td").click(function() {
alert($(this).find(".select_dropdown").val());
});
Hope this help.
try passing in the ID onClick:
$("#computer_table td").click(function(this.id){ }
Just make sure all your cells have an ID.
Here is W3 example on enclosures and encapsulation. This is useful for giving all your elements a different ID. W3 encapsulation example
Adding elements with eventlisteners attached, and passing in a unique id!!
*Note: this is not an exact fix for your code. This should however aid you in understanding.
/*use this function to create unique id's*/
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})();
/*grab your table*/
var table =document.getElementById("computer_table");
/* create an element, set it's attributes*/
var newRow = document.createElement("th");
newRow.setAttribute("class", "table_header");
newRow.setAttribute("id", "table_header"+add());
/*add the event listener*/
newRow.addEventListener("click",function(this.id){ /* YOUR CODE HERE */ });
/*append to your table*/
table.appendChild(newRow);
This is my HTML code:
<table id="display_table"><tr>
<td>No. of Questions: </td>
<td><input type="text" id="questions_num"></td>
</tr><tr>
<td>No. of Options: </td>
<td><input type="text" id="options_num"></td>
</tr></table>
I want to make it such that when the user enters x in the text input (whose id is options_num), x rows will be created. For each new row that is created, there should be a left column and a right column. The left column will contain the "Option" + somenumber, where somenumber refers to the row that has been created, and the right column will create a text input.
This is what I have tried in my JS:
document.getElementById("options_num").onkeyup = function() {
var options_num = parseInt(document.getElementById("options_num").value);
var display_text = '<tr><td>No. of Questions: </td><td><input type="text" id="questions_num"></td></tr><tr><td>No. of Options: </td><td><input type="text" id="options_num"></td></tr>'
for(var i = 1; i <= options_num; i++) {
display_text += "<tr><td>Option " + i + ": </td><td>" + "<input type='text' id='option_" + i + "'</td></tr>";
}
document.getElementById("display_table").innerHTML = display_text;
document.getElementById("options_num").value = options_num.toString();
document.getElementById("options_num").focus();
}
And it works when I first enter a value into the text input (whose id is question_num), but when I change the value, it does not work (it does not do anything). Demo.
So how do I get my JS code to work?
The reason it doesn't work after the first time, is that innerHTML actually destroys event binding. So after you modify table.innerHTML browser completely rebuilds new DOM elements without original onkeyup event listener attached.
I would recommend to change HTML a little, it will make everything simpler:
<table id="display_table">
<tbody>
<tr>
<td>No. of Questions:</td>
<td><input type="text" id="questions_num"/></td>
</tr>
<tr>
<td>No. of Options:</td>
<td><input type="text" id="options_num"/></td>
</tr>
</tbody>
<tbody id="rows"></tbody> <!-- append generated HTML here -->
</table>
and modified JS:
document.getElementById("options_num").onkeyup = function () {
var options = document.getElementById("options_num"),
optionsNum = parseInt(options.value),
tbody = document.getElementById("rows"),
rows = '';
for (var i = 1; i <= optionsNum; i++) {
rows += "<tr><td>Option " + i + "</td><td>" + "<input type='text' id='option_" + i + "'</td></tr>";
}
tbody.innerHTML = rows;
options.focus();
}
So the idea is to put table rows into tbody and it makes easy adding new and replacing replacing old rows.
Demo: http://jsfiddle.net/8yYyW/2/
I hope this makes sense. I have an onclick and I am trying to write this data for each div with this.
jQuery('.circle_counter_div').each(function() {
var tagtext = '[circlecounter rel="' + jQuery('.circle_size').val() + '"][/circlecounter]';
})
I am cloning items but I can only write the data for one of them. How do I write data for each cloned item?
So with the above example I want tagtext to equal
[circlecounter rel="' + jQuery('.circle_size').val() + '"][/circlecounter]
[circlecounter rel="' + jQuery('.circle_size').val() + '"][/circlecounter]
[circlecounter rel="' + jQuery('.circle_size').val() + '"][/circlecounter]
Full Code
HTML
<div class="sc_options circle_counter_div" id="clone_this" style="display: block;">
<input type="text" class="circle_size"/>
</div>
<div class="sc_options circle_counter_div" id="clone_this" style="display: block;">
<input type="text" class="circle_size"/>
</div>
<div class="sc_options circle_counter_div" id="clone_this" style="display: block;">
<input type="text" class="circle_size"/>
</div>
<input type="submit" class="sc_options circle_counter_div" id="insert" name="insert" value="<?php _e("Insert", 'themedelta'); ?>" onClick="insertcirclecountershortcode();" style="display:none"/>
Script
// Insert the column shortcode
function insertcirclecountershortcode() {
var tagtext;
var start;
var last;
var start = '[circlecounters]';
var last = '[/circlecounters]';
jQuery('.circle_counter_div').each(function() {
var tagtext = '[circlecounter rel="' + jQuery('.circle_size').val() + '"][/circlecounter]';
})
var finish = start + tagtext + last;
if (window.tinyMCE) {
window.tinyMCE.execInstanceCommand(window.tinyMCE.activeEditor.id, 'mceInsertContent', false, finish);
//Peforms a clean up of the current editor HTML.t
//tinyMCEPopup.editor.execCommand('mceCleanup');
//Repaints the editor. Sometimes the browser has graphic glitches.
tinyMCEPopup.editor.execCommand('mceRepaint');
tinyMCEPopup.close();
}
return;
}
Extended Answer: After some more information was provided perhaps you're just missing the index and value properties on the loop. Its hard to tell, since little sample code is provided.
$('.test').each(function(i,v) {
var tagtext = $(v).html();
console.log(tagtext);
})
http://jsfiddle.net/4xKvh/
Original Answer:
Use use classes instead of an Id. Id's are only suposed to be used once on a page.
Since there should only be one occurance jQuery is filtering the result down to 1, even though the markup may have multiple elements with that Id on the page. This is to make use of the built-in browser function getElementById().
For proof checkout this jsFiddle
Using the class attribute is more appropriate for what you're trying to do.
jQuery('.clone_this').each(function() {
var tagtext = '[something][/something]';
})
And the markup:
<div class="clone_this"></div>
This will allow jQuery to return an array of elements like you're looking for
This is what I needed... Finally got it working.
tagtext = ' ';
jQuery('#circle_counter_div .circlecounter').each(function() {
tagtext += '[circlecounter rel="' + jQuery('.circle_size').val() + '" datathickness="' + jQuery('.circle_thickness').val() + '" datafgcolor="' + jQuery('.circle_color').val() + '" text="' + jQuery('.circle_text').val() + '" fontawesome="' + jQuery('.font_awesome_icon').val() + '" fontsize="' + jQuery('.circle_font_size').val() + '"][/circlecounter]';
});
var start = '[circlecounters]';
var last = '[/circlecounters]';
var finish = start + tagtext + last;
I am dynamically generating the input box using jquery and then embedding it into the document. The problem I am having is, although the correct value is being shown in the inspector, the browser shows an invalid value.
To be further clear, here is the image:
You can see that, in the inspector
<input name="txtTblAmount" class="num" style="width:70px;" type="text" value="1000" tabindex="29">
the value is 1000 while that being shown in the browser window is 1500. Can anyone please have a look and tell me, what's the problem here?
P.S: Have tried it in firefox as well. But still the problem is same i.e. different value in the inspector.
Here is the JS code:
function addrow(itemName, itemid, godown, godownid, quantity, rate, amount, gstAmount) {
gstAmount = typeof gstAmount !== 'undefined' ? gstAmount : '0';
if (typeof dTable1 != 'undefined') {
// dTable1.fnClearTable();
//$('#ItemRows').find('a[name="btnDelItem"]').off();
dTable1.fnDestroy();
// $('#ItemRows').empty();
}
//alert($('#ItemRows tr').length);
var strRow = '<tr id="row' + ($('#ItemRows tr').length + 1) + '">' +
'<td class="">' +
(($('#ItemRows tr').length + 1)) +
'</td>' +
'<td class="tdItemName" style="widtd: 250px">' +
itemName +
'<input name="hfItemId" style="width:200px;" type="hidden" value="' + itemid + '"/>' +
'</td>' +
'<td class="" style="widtd: 200px">' +
godown +
'<input name="hfGodownid" style="width:200px;" type="hidden" value="' + godownid + '"/>' +
'</td>' +
'<td class="" style="widtd: 200px">' +
'<input name="txtTblQuantity" style="width:200px;" class="num" type="text" value="' + quantity + '"/>' +
'</td>' +
'<td class="" style="widtd: auto">' +
'<input name="txtTblRate" style="width:70px;" class="num" type="text" value="' + rate + '"/>' +
'</td>' +
'<td class="" style="widtd: auto">' +
'<input name="txtTblAmount" class="num" style="width:70px;" type="text" value="' + amount + '"/>' +
'</td>' +
'<td>' +
'<input name="txtTblGstAmount" class="num" style="width:70px;" type="text" value="' + gstAmount + '"/>' +
'</td>' +
'<td class="ms"><div class="btn-group1"> <a class="btn btn-small" rel="tooltip" data-placement="left" data-original-title=" edit " name="btnDelItem" data-id="' + ($('#ItemRows tr').length + 1) + '" ><i class="icon-remove"></i></a> </div></td>' +
'</tr>';
console.log(strRow);
console.log(amount);
$('#ItemRows').append(strRow);
//SaveNewParty($("#drpAccId option:selected").text());
bindGrid();
//dTable1.fnDraw();
PopulateTotal();
// $('#ItemRows').find('a[name="btnDelItem"]').off();
var insertedRow = $('#ItemRows tr')[$('#ItemRows tr').length - 1];
$(insertedRow).find('a[name="btnDelItem"]').on('click', function () {
var row = $(this).parents('tr');
dTable1.fnDeleteRow(dTable1.fnGetPosition(row[0]));
$('#ItemRows tr').each(function (index) {
$(this).find('td:nth(0)').text((index + 1));
});
PopulateTotal();
})
$('#datatable_Items').css('width', '100%');
Populate_Events();
}
I just had a look at your code and found that there was no problem in the code you have shown us here. I agree with Afzaal Ahmad Zeeshan but the way he has explained it, it's not always the case. I recently had the same issue and after hours of scratching my head I found out that the value was being changed by some other jquery code.
Also note that, it is not always the case that the value set by the jquery is shown in the inspector for example, if you try $("#inputel").val(4), you will note that the value will not be updated in the inspector but in the backend this value has been updated. Inspector only shows the value that was sent from the server, not the one you set by jquery or something else.
Hope you got my point!
Kamran, that's of no importance. You are setting this value NOT DYNAMICALLY. Yes, you can see here! You are either setting this value while loading the page, or you are using some other code, that you are not showing us! I am not sure of that. Ok here.
In my example you can see, I am writing a text in the input but there is no value update in the element's inspection.
Also, its maybe not the answer but you can see that you're using widtd which is not a correct CSS property. The correct one is width. You know that.
I am sure you won't get any problem while sending the form to the server, as the value will get updated by the value that you just wrote.
I have seen your code, you are writing the field as:
<input name="txtTblAmount" class="num"
style="width:70px;" type="text" value="' + amount + '"/>'
According to me, the issue is at amount. You are havin this field in the function too.
function addrow(itemName, itemid, godown,
godownid, quantity, rate, amount, gstAmount) {
Now what you can do to prevent that is to change the value of amount there. If you donot want to change it, then its OK. And also, once again you should not fear this value difference, as once you click submit the value that you have entered will be sent to the server instead of value of the field itself. The value is just because you have it written there. Nothing else, so don't worry! Its ok. You cannot change the value now, if you want to. Then here is the hell code, you will have to hard code it. Like this!
<div id="input">
<input type="text" id="text" value="" onkeyup="updateVal()" />
</div>
function updateVal() {
// start function..
var val = $('#text').val(); // the value of field..
// after getting the value, update the div..
$('#input').html("<input type='text' id='text' value='" +
val + "' onkeyup='updateVal()' />");
}
But note, after using this code, you will get the current value in the field! But you will loose the focus on the input field. As the div will get updated but the values will be the newest ones!
Now to keep in focus?
You can use this:
$('#text').focus();
But while using this, you will get only one ONLY ONE word in the field.
Why?
Because once if will focus on the field, it will (select all) select the words or value inside the field and when you press another word, it will replace the previous one with the latest one! This way you will not get any correct field I mean the field of your choice! But you issue will be fixed.
So kamran believe me, let it be the way it is! You donot want to hard-code it. If you still wanna give it a try, use the code I shared!
Example for the code I am sharing is as under:
Now when you right the value or some words, you will get the value auto updated when you see this Developer Tools. Like this:
That was all. I gave you two options for your work. And still I will love to go with the option of Not using a code, to just update the value on the field. Rest is upto you Kamran.
Edit:
You mentioed that you want to use the value 1000 not the value that the user would add to the input. Then use this:
$("name='txtTblAmount'").val() == "1000");
This will automatically override the value that user will add and replace it with the value that you want to get!
Suppose this is the prepare table below. and each of 3 row there was a textbox and beside them there where 2 buttons the + or add and - for delete. when i click + in a row, a new textbox will be generated and when i click - the textbox will delete. like the sample below:
Could anyone suggest the snippet for this step or procedure?
Thank you
you could write something on these lines:
<script type="text/javascript">
$(document).ready(function(){
var counter = 2;
$("#addButton").click(function () {
if(counter>10){
alert("Only 10 textboxes are allowed");
return false;
}
var newTextBoxDiv = $(document.createElement('div'))
.attr("id", 'TextBoxDiv' + counter);
newTextBoxDiv.after().html('<label>Textbox #'+ counter + ' : </label>' +
'<input type="text" name="textbox' + counter +
'" id="textbox' + counter + '" value="" >');
newTextBoxDiv.appendTo("#TextBoxesGroup");
counter++;
});
$("#removeButton").click(function () {
if(counter==1){
alert("No more textbox to remove");
return false;
}
counter--;
$("#TextBoxDiv" + counter).remove();
});
});
</script>
If you do not want to create the div on the fly, you can find the id of your last table row, add 1 to it, create the table row, and then append the textbox creation html to it.
Assuming the html structure is as follows
<table border = "1">
<thead>
<tr><td> Text Boxes </td></tr>
</thead>
<tbody>
<tr><td><button class="add-text-box">+</button><button class="remove-text-box">-</button></td></tr>
<tr><td><button class="add-text-box">+</button><button class="remove-text-box">-</button></td></tr>
<tr><td><button class="add-text-box">+</button><button class="remove-text-box">-</button></td></tr>
</tbody>
the following jquery snippet should work
$(".add-text-box").click(function(){
$(this).parent().prepend(" <input class='text-box' /> <br>");
});
$(".remove-text-box").click(function(){
textboxes = $(this).parent().find('.text-box');
$(textboxes).last().remove();
if (textboxes.length === 0) {
$(this).siblings().remove();
$(this).remove();
}
});
You can see it in action here