Add / Delete Rows from Table - javascript

I have created a table in Twitter Bootstrap here
I want to be able to do 2 things with it
Delete rows by pressing delete icon - will delete that row
Add a new name by adding text (name) to input field and then pressing "add new row"
DEMO - http://jsfiddle.net/qxdz4/2/
Looking for a way to do this with JavaScript / jQuery
My Code
<div class="input-prepend input-append"><span class="add-on"><i class="icon-picture"></i></span>
<input class="span2"
id="appendedInputButton" type="text" placeholder="Add New Name Here">
<button class="btn" type="button">Add New Row</button>
</div>
<table id="users" class="table table-bordered table-condensed">
<tr>
<th>name</th>
<th></th>
</tr>
<tr>
<td>Mike
</td>
<td class="taskOptions"> <a href="#deleteProject" rel="tooltip" data-toggle="modal" class="tip-top"
data-original-title="Delete Row"><i class="icon-remove"></i></a>
</td>
</tr>
<tr>
<td>John
</td>
<td class="taskOptions"> <a href="#deleteProject" rel="tooltip" data-toggle="modal" class="tip-top"
data-original-title="Delete Row"><i class="icon-remove"></i></a>
</td>
</tr>
<tr>
<td>Mary
</td>
<td class="taskOptions"> <a href="#deleteProject" rel="tooltip" data-toggle="modal" class="tip-top"
data-original-title="Delete Row"><i class="icon-remove"></i></a>
</td>
</tr>
</table>
Notes
Clicking the delete button should delete the row
Typing into the input field and pressing "add new row" button should add a new
row to the end of the table with the Name filled in

You can easily remove the row by doing this:
$('td.taskOptions a.tip-top').on('click', function(e) {
e.preventDefault();
$(this).tooltip('hide');
$(this).parents('tr').remove();
});
Similarly, adding a new row can be done as follows:
$('button.btn').click(function(e) {
e.preventDefault();
var the_name = $.trim($('#appendedInputButton').val());
var new_row = $('<tr>\
<td>\
'+the_name+'\
</td>\
<td class="taskOptions">\
<i class="icon-remove"></i>\
</td>\
</tr>');
new_row.appendTo($('#users'));
});
Please note that it might be worth adding a more specific class name to the button (when clicked to add the row) to avoid any confusion. An ID would work just as well.
I've updated your jsFiddle with the additional functionality. You can see here.

I don't know how you obtain each row's pk data (data-pk) attribute. That's up to you
On document.Ready
$('[rel=tooltip]').tooltip();
function bindCloseButtons(){
$("#users td.taskOptions a").click(function(e){
$(this).parent().parent().remove();
});
}
function addTableRow(name , pk){
// name column
var row = $("<tr></tr>");
row.append('<td>'+name+'</td>');
// close button
var btnClose = $('<td class="taskOptions"> <i class="icon-remove"></i></td>');
row.append(btnClose);
$("#users").append(row);
bindCloseButtons();
$('[rel=tooltip]').tooltip();
}
$("#addNew").click(function(e){
var name = $("#appendedInputButton").val();
var pk = 1; // TODO: set your pk here
addTableRow(name, pk);
});
bindCloseButtons();
Here's a fiddle:
http://jsfiddle.net/qxdz4/16/

First you create one method AddmultipleInput()
Inside the function,
.AddMultipleInput = function (btnAddId, btnDelId, inputContainerIdPrefix, inputContainerCss, firstChildInputIdPrefix) {
if ($('.' + inputContainerCss).length < 2) {
$('#' + btnDelId).attr('disabled', 'disabled');
}
$('#' + btnAddId).click(function () {
var num = $('.' + inputContainerCss).length; // how many "duplicatable" input fields we currently have
var newNum = new Number(num + 1); // the numeric ID of the new input field being added
// create the new element via clone(), and manipulate it's ID using newNum value
var newElem = $('#' + inputContainerIdPrefix + num).clone().attr('id', inputContainerIdPrefix + newNum);
newElem.children().each(function () {
var idPrefix = $(this).attr('id').substring(0, $(this).attr('id').length - 1);
var namePrefix = $(this).attr('name').substring(0, $(this).attr('name').length - 1);
$(this).attr('id', idPrefix + newNum).attr('name', namePrefix + newNum);
})
// insert the new element after the last "duplicatable" input field
$('#' + inputContainerIdPrefix + num).after(newElem);
// enable the "remove" button
$('#' + btnDelId).attr('disabled', '');
// business rule: you can only add 5 names
if (newNum == 5)
$('#' + btnAddId).attr('disabled', 'disabled');
});
$('#' + btnDelId).click(function () {
var num = $('.' + inputContainerCss).length;
$('#' + inputContainerIdPrefix + num).remove();
$('#' + btnAddId).attr('disabled', '');
if (num == 2)
$('#' + btnDelId).attr('disabled', 'disabled');
});

$('.icon-remove').live('click',function(){
$(this).parent('tr').remove();
});
If you are using jQuery 1.7 or above, then use .on instead of .live.

Add a class to your delete links (like delete-row) and use something like:
$(document).on("click",".delete-row",function(ev) {
ev.preventDefault();
$(this).tooltip('hide');
$(this).parents("tr").first().remove();
});
Note: "$(this).tooltip('destroy');" would be better than "hide", but your fiddle bootstrap version doesn't support destroy yet. Also, you can set $("#users") instead of $(document) as handler for this event if you want, so long as the delete-row buttons are children of the handler the event gets delegated properly.
To add a line the answer of BenM should work perfect.
PS:
.parents(selector) function travels more than one level up the DOM tree, while .parent() travels a single level up the DOM tree.
.parents(selector) function selects all parents that match the selector, so in case there is a change you end up putting a table inside a table (accidentally im sure) you should use .first(), ensuring you dont remove the wrong row.
Edit: As mentioned by BenM, the previous code would not work with new lines, forgot the add part of the question, the new code should work.

I would suggest you yo use following jQuery functions:
on(), click(), remove(), append()
Please do research on this, also look at the jQuery selectors in order to find how to select proper row.

Related

C# and Javascript - How to Add Remove Objects To A Javascript Array and Postback to Server?

I have a form where there is a section for a user to add multiple appointment dates. This section of the form has the following fields: startdate, enddate and a add button.
<form action="/someaction">
Start Date <input type="text" id="StartDate" name="StartDate"><br>
End Date: <input type="text" id="EndDate" name="EndDate"><br>
<a class="btn btn-default js-add" href="#" role="button">Add</a>
<table class="table" >
<tbody id="dates" >
</tbody>
</table>
// Other form fields
<input type="submit" value="Submit">
</form>
Each time a user adds an appointment I want to store the values in an JavaScript object array and display the number of items in the array along with details of the object added with an option to remove it from the list. Below is my initial attempt:
<script>
var appointments = [];
$(".js-add").click(function (e) {
e.preventDefault();
var startDate = $("#StartDate").val();
var endDate = ("#EndDate").val()
// What can I use to uniquely identify each object incase we need to delete???
appointments.push( { startDate: startDate , endDate: endDate });
$('<tr/>', { html: '<td >' + startDate + '</td><td>' + endDate + '</td><td><a class="js-delete" href="" data-id="">delete</a></td>'})
.appendTo($('#dates'));
}
$(".js-delete").click(function (e) {
e.preventDefault();
var id = $(this).attr("data-id");
// How do I remove the selected object from the array???
// appointments.splice(x,1);
}
</script>
How do I remove the object from the array using the array index. I have a data-id attribute on the delete link which would contain the array index.
But the array index can change each time an object is added or deleted so how can I update the data-id attribute on existing rows?
Secondly, how do I pass this object back to the server since it isn't attached to any form input field?
Some help would be appreciated?
How do I remove the object from the array. I have a data-id attribute on the delete link but what can I use to uniquely identify the object.
Because you create a new table row you need to:
delegate event (i.e.: $(document).on('click', '.js-delete', function (e) {)
use the data-id attribute to assign it the value of the index of the current
element in array.
on deleting a row you need to rearrange the values of the data-id
How do I pass this object back to the server
You may use an hidden input field and set its value with the array value.
The snippet:
var appointments = [];
//
// delegated event
//
$(document).on('click', '.js-delete', function (e) {
e.preventDefault();
var id = +$(this).attr("data-id");
appointments.splice(id, 1);
$(this).closest('tr').remove();
//
// rearrange the values of data-id attributes
//
$('#dates tr td:nth-child(3) a').each(function(index, element) {
var tId = +$(element).attr("data-id");
if (tId > id) {
$(element).attr("data-id", tId - 1);
}
});
});
$(function () {
$(".js-add").click(function (e) {
e.preventDefault();
var startDate = $("#StartDate").val();
var endDate = $("#EndDate").val();
// In order to uniquely identify each object you can set the
// value of data-id attribute with current array index
appointments.push( { startDate: startDate , endDate: endDate });
$('<tr/>', { html: '<td >' + startDate + '</td><td>' + endDate + '</td><td><a class="js-delete" href="" data-id="' + (appointments.length - 1) + '">delete</a></td>'})
.appendTo($('#dates'));
//
// a possible sorting.... Consider to use a date compare
// instead of a string compare function.
//
$.each($('#dates tr').get().sort(function(a, b) {
return a.childNodes[0].textContent.localeCompare(b.childNodes[0].textContent);
}), function(index, ele) {
$('#dates').append(ele);
});
});
//
// On form submit stringify your array and save it into
// an hidden input field
//
$('input[type="submit"]').on('click', function(e) {
e.preventDefault();
$('#appointments').val(JSON.stringify(appointments));
console.log($('#appointments').val());
});
});
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<form action="/someaction">
<input id="appointments" type="hidden">
Start Date <input type="text" id="StartDate" name="StartDate"><br>
End Date: <input type="text" id="EndDate" name="EndDate"><br>
<a class="btn btn-default js-add" href="#" role="button">Add</a>
<table class="table" >
<tbody id="dates" >
</tbody>
</table>
<!-- Other form fields -->
<input type="submit" value="Submit">
</form>

Child Div is not removed when tried to remove using Jquery

Clearing child div inside parent div, there are many answers like :
$(".ChildDiv").html("");
$('.ChildDiv > div').remove();
$(".ChildDiv").html("");
$("#ParentDiv").html("");
$(".ChildDiv div").remove();
$(".ChildDiv div").empty();
$('.ChildDiv ').find('div').remove();
Probably I have listed all possible way to remove the div's, but even after using all these, I still not able to clear all the div's inside Parent Div. let me explain what I am doing and what I need.
Scenario :
I have two container-1, one of the container has input search box, where I can search for entering employee name and select few employees Ex. 5 and can use "Add" button to move those employees to the other container-2 which is 'div'.
Now I click on report button event and get the information of those 5 people in different aspx, now if i go back to the page where i have to search for another 3 employees and when I again click on the "Add" button, it should add only 3 employees instead it is adding last searched 5 + 3 employees!!.
So i am trying to clear the 5 employees inside that div after i click on "Report" button , when i use alert() it says it has 0 element, but when I add it for the second time, it appends the data again, which i dont need. here is the code :
Points to remember :
1. ParentDiv is the container-2
2. ChildDiv is the child div inside ParentDiv(which is dynamically appended when we select 5 employees on "Add" button click"
Here is the code:
HTML :
<table id="topTable">
<tr>
<td id="leftpane">
<h4>Search for Employee by Name or Profile:</h4>
<input type="text" id="EmployeeSearchBox" class="search-box" aria-multiselectable="true" />
<select id="EmployeeList" size="20" multiple></select>
</td>
<td id="centerpane">
<div> <input type="button" value="Add >>" class="AddButton" id="buttonAdd" /></div>
<div> <input type="button" value="Add All >>" class="AddButton" id="buttonAddAll" /></div>
</td>
<td id="rightpane">
<h4>Selected Employees:</h4>
<div id="ParentDiv"></div>
</td>
</tr>
</table>
Run Report button event
<input class="data" type="submit" name="cmdSubmit" value="Run Report" onclick="return FormValidate();"
onserverclick="RunReport" runat="server" id="Submit1" />
Add Button Click :
which moves the employees from container-1 to container-2.
$(document).on('click', '#buttonAdd', function (e) {
$('#EmployeeList :selected').each(function (i, selected) {
myHash[$(selected).val()] = $(selected).text();
});
var myNode = $("#ParentDiv")[0];
while (myNode.firstChild) {
myNode.removeChild(myNode.firstChild);
}
for (var emp_id in myHash) {
var emp = $("#ParentDiv").append("<div class= ChildDiv id=" + emp_id + ">" + myHash[emp_id] + " <span class='close'>×</Span> </div>");
}
$('#EmployeeSearchBox').val("").trigger('input');
});
On click of "Report" button it should clear all the elements from ParentDiv/ChildDiv which is what I did, but still it is not clearing it, how can I resolve/remove these elements once "Report" button event clicked.
Here is a sample of "Report" button event :
function FormValidate() {//Part of my other code
$(".ChildDiv").html("");
$('.ChildDiv > div').remove();
$(".ChildDiv").html("");
$("#ParentDiv").html("");
$(".ChildDiv div").remove();
$(".ChildDiv div").empty();
$('.ChildDiv ').find('div').remove();
}
None of them is working, i feel there is an issue with the "Add" button event, where it is storing the data.
NOTE :
I don't want to clear the array of employee list, since I want to select multiple employees again again Ex. I can select 2 employees starts with the letter "M" and I can search the 2 employees of letter "L" and add those 2 employees, the container should hold 4 employees before "Report" button click.
Let me know if I am clear enough.
Console Log
Finally I could able to fix the issue, i was facing, I am posting the answer, now it is working as I need.
$(document).on('click', '#buttonAdd', function (e) {
var div_count = $('#ParentDiv').find('div').length;
if (div_count === 0) {
myHash = []; // Clearing the hash, so that it can add fresh employees, if count == 0 in container- 2.
$('#EmployeeList :selected').each(function (i, selected) {
myHash[$(selected).val()] = $(selected).text();
});
}
else { // If there are existing employees in container-2 then append few more.
$('#EmployeeList :selected').each(function (i, selected) {
myHash[$(selected).val()] = $(selected).text();
});
}
var myNode = $("#ParentDiv")[0];
console.log(myNode);
while (myNode.firstChild) {
myNode.removeChild(myNode.firstChild);
}
for (var emp_id in myHash) {
var emp = $("#ParentDiv").append("<div class= ChildDiv id=" + emp_id + ">" + myHash[emp_id] + " <span class='close'>×</Span> </div>");
}
$('#EmployeeSearchBox').val("").trigger('input');
});
What I did
Since I should be able to append multiple employees by searching, that is handled in 'else' part, if I generated the "Report" then, I am clearing the Container-2.
When I come back to page to search few more employees, by this time Container-2 will not be having any employees, so
var div_count = $('#ParentDiv').find('div').length;
if (div_count === 0) {
myHash = [];
//....
}
will clear the array which allow me to add fresh employees, hence it solved my problem :)
Thanks all for the support.
Edited to adjust on comments:
You need to clear the myHash variable. Otherwise employees will be added again from there.

Javascript: how to get the value of <a> tag i clicked from other previous page

<a> tags are on a table.
--HTML--
<tbody id="TableBody">
<tr>
<td class="span2"><span class="line"></span><b>1207012097</b></td>
</tr>
<tr>
<td class="span2"><span class="line"></span><b>1207011881</b></td>
</tr>
<tr>
<td class="span2"><span class="line"></span><b>1207011857</b></td>
</tr>
</tbody>
What I want to do is view the text value of the clicked < a > tag (example: 1207012097) to the href target page which is "home/nextpage". Can you show me how to do this using JavaScript? TIA
You can catch the click on the link and add a query string parameter to the link:
$('#TableBody a').click(function(e){
e.preventDefault();
window.location.href = $(this).attr('href') + '?code=' + escapeURIComponent($(this).text());
});
In the next page you can get the value from the query string:
function querystring(key) {
var re=new RegExp('(?:\\?|&)'+key+'=(.*?)(?=&|$)','gi');
var r=[], m;
while ((m=re.exec(document.location.search)) != null) r.push(m[1]);
return r;
}
var code = querystring['code'][0];
IF you wouldnt want to passed the value via url parameters you might want to consider passing it by instantiation of form when you click a certain <a>
First lets change the structure of your <a>
1207012097
to
<a class='clickable_post' href="#">1207012097</a>
Embed JQuery Lib
<script type='text/javascript' src='jquery-1.10.2.js'></script>
Then the scripts would be
$(function(){
$('.clickable_post').click(function(){
var POST_VALUE = $(this).text();
$('<form action="home/nextpage" method="POST">' +
'<input type="hidden" name="value" value="' + POST_VALUE + '">' +
'</form>').submit();
});
});
So what it literally does it
trigger a click event when a classname with '.clikable_post' is hit
store textValue of click <a> into a variable
Create a form within the script with the selected input value before submiting to your
previoously set href but now as an $_POST action
Finally results are show on the script form page action and can be access via $_POST
cheers! LYKAPIGS.

Add dynamic href to table with jquery

I have a table with a template to insert rows, I would like to make those rows clickable so that I can edit them. How do I append an href value to the template?
My Template
<tr class="template" style="display:none;">
<td><span class="item_num"> Num </span></td>
<td><span class="item_desc"> Description </span></td>
<td><span class="item_price"> Price </span></td>
<td><span class="item_ref">ref</span></td>
</tr>
My Javascript
var newRow = $('#quote .template').clone().removeClass('template');
var quoteItem = {
number: 1,
description: myDescriptionVariable,
price: myPriceVariable,
};
template(newRow, quoteItem)
.insertAfter('#quote tr.template')
.fadeIn()
function template(row, quoteItem) {
row.find('.item_num').text(quoteItem.number);
row.find('.item_desc').text(quoteItem.description);
row.find('.item_price').text(quoteItem.price);
row.find('.item_ref').attr('href','hello');
return row;
}
You can use .data()
row.find('.item_ref').data('ref','hello');
with
<span class="item_ref" data-ref="" > Edit</span>
Then you can use it like --
console.log($('.item-ref').data('ref'));
If you just wish to store data somehow then this might be useful. Let me know if there's something more you want to do. Or what kind of data href holds and how you want to use it further.
UPDATE
From what I understand up till now is, you want to add rows dynamically that needs to editable after insertion. Each row contain some fields with certain values. And you want to save ref in item_ref class.
So here's how you can do it -
var num = 1;
var myDescriptionVariable = 111;
var myPriceVariable = 999;
// You may have some other element triggers cloning
$("button").click(function(){
var newRow = $('#quote .template').clone().removeClass('template');
var quoteItem = {
number: num,
description: 'Description ' + myDescriptionVariable, // added to distinguish items
price: myPriceVariable + ' USD', // added to distinguish items
linkToPopup: myDescriptionVariable + '_link_goes_here' // added to distinguish items
};
template(newRow, quoteItem)
.insertAfter('#quote tr.template')
.show();
});
function template(row, quoteItem) {
row.find('.item_num').text(quoteItem.number);
row.find('.item_desc').text(quoteItem.description);
row.find('.item_price').text(quoteItem.price);
// here 'href' will hold desired link_to_popup
row.find('.item_ref').data('href',quoteItem.linkToPopup);
myDescriptionVariable+= 1; // added to distinguish items
myPriceVariable+=2; // added to distinguish items
num+=1; // added to distinguish items
return row;
}
$("#quote").on("click", ".item_ref",function(){
// this will give to desired link_to_pop_val
alert($(this).data('href'));
});
I've added a button to give demonstration. This approach definitely avoid unnecessary DOM elements like hidden inputs to be added for each row. With .data() you same multiple kind of information for every field like -
$("span").data('key_1', value_1);
$("span").data('key_2', value_2);
$("span").data('key_2', value_3);
fiddle for demonstration
I think that's what you want to do and should serve the purpose. :)
There are actually a few ways to do this, one of them being:
Add some inputs to your template that are hidden
Bind a click event to the row that will hide the spans and show the input
You would of course need a save button and do something with the values, but I didn't do that part.
A condensed not fully working demo: http://plnkr.co/edit/GGM0d9wfNcoZBd5kKCwA
<tr class="template" style="display:none;">
<td><span class="item_num"> Num </span><input type="text" style="display:none" /></td>
<td><span class="item_desc"> Description </span> <input type="text" style="display:none" /></td>
<td><span class="item_price"> Price </span><input type="text" style='display:none' /></td>
<td><span class="item_ref">ref</span><input type="text" style='display:none' /></td>
</tr>
jquery:
$(document).on('click', '#quote tr', function(e) {
$('span', this).hide();
$('input', this).show();
});
$('#add').on('click', function(e) {
var newRow = $('#quote .template').clone().removeClass('template');
var quoteItem = {
number: 1,
description: 'myDescriptionVariable',
price: 100,
};
template(newRow, quoteItem)
.insertAfter('#quote tr.template')
.fadeIn()
});
function template(row, quoteItem) {
row.find('.item_num').text(quoteItem.number).next().val(quoteItem.number);
row.find('.item_desc').text(quoteItem.description).next().val(quoteItem.description);
row.find('.item_price').text(quoteItem.price).next().val(quoteItem.price);
row.find('.item_ref').attr('href','hello').next().val('hello');
return row;
}

Select hidden input from within next td [jQuery]

I have a table layed out like this:
<td>
somename
</td>
<td class="hoverable value" >
somevalue
</td>
<td class="changed">
</td>
<td class="original value">
<input type="hidden" value="somevalue" />
</td>
And what I'm trying to do is, I hover over the hoverable td which turns it into a textbox. Once I hover out I want to check the hidden field for it's original value and put an image in changed if the 2 are different from each other. I already have this:
$(document).ready( function() {
var newHTML = '';
$('table td.hoverable').hover(
function () {
var oldHTML = $(this).html().trim();
$(this).html('<input type=\'text\' value=\'' + oldHTML + '\' size=\'' + ((oldHTML).length + 2) +'\' />');
},
function() {
newHTML = $('input', this).val();
var oldHTML = $(this).next('td.original').children('hidden').val();
if(newHTML != oldHTML) {
$(this).next('td.changed').html('Changed');
}
$(this).html(newHTML);
})
});
but it doesn't work. What fails apparently is grabbing the value of the hidden field, and I've tried selecting it in several different ways but just can't get to it.
Any ideas or tips are gratefully appreciated ;)
You need to use .nextAll()
var oldHTML = $(this).nextAll('td.original').find('input:hidden').val();
Why? Because .next() is taking the next element and seeing if it matches the selector. If you use .nextAll() you get the next element that matches the selector.
Try
$(this).next('td.original').find('input:hidden').val();
var oldHTML = $(this).next('td.original').children(':hidden').val();
Replace
var oldHTML = $(this).next('td.original').children('hidden').val();
With
var oldHTML = $(this).next('td.original').find('input:hidden').val();

Categories