How to select the first and last occurring <td> in a <tr>? - javascript

So I have a html table which has a structure like :
<table>
<tbody>
<tr>
<input type="hidden" name="a" value="x">
<input type="hidden" name="b" value="y">
<td>First Cell</td>
<td>Some text</td>
<td>Some text</td>
<td>Last Cell</td>
</tr>
</tbody>
</table>
What i want is a generic way using CSS to always select the first and last occurring of each row as the number of hidden input element may differ with each instance.
PS: What I am trying to do is that in my application i want to remove the left-border from the first 's and right-border from the last 's from all the existing tables using a common css. The overall structure remains the same but the number of hidden input fields and cells may differ.
Any help would be appreciated. Thanks in advance!

You can separate multiple CSS selectors with a comma:
td:first-child, td:last-child { background: red; }
By the way, check your markup as it looks invalid (input element inside tr is not allowed).

You have keywords for that predefined in jquery
See reference :first and :last
To get first td
$("tr").find("td:first").html();
To get last td
$("tr").find("td:last").html();
this works and its easy
NOTE : dont put html content directly into a tr always use td to do so.
ex :
<tr>
<td> <input type="hidden" name="a" value="x"> </td>
<td> <input type="hidden" name="b" value="y"> </td>
</tr>

Related

innerHTML and jqueries .html() ... GOTCHA! any proper work arounds?

innerHTML and jqueries .html() ... GOTCHA!
I had just created a little template html tag for my javascript to go get a copy of and push into a table... It looked like this:
<div id="TimesheetEntryRow">
<tr id="row{RowID}">
<td></td>
</tr>
</div >
So in jquery I thought, cool let's grab that:
timesheetTemplateHtml = $( "#TimesheetEntryRow" ).html();
and then I appended it to my awesome table:
$( "#TimesheetTable" ).append( timesheetTemplateHtml );
It didn't work?
It had stripped off the <tr> and the <td>s and left true tags like the <input />s I had inside it.
So I thought, oh jquery you naughty little critter, I'll use innerHTML so that I do not have to worry about jquery being clever:
timesheetTemplateHtml = document.getElementById( "TimesheetEntryRow" ).innerHTML;
document.getElementById( "TimesheetTable" ).innerHTML += timesheetTemplateHtml;
Still not working? Still it stripped off all the tags for my template...
I binged the hell out of it and stumbled across these two articles:
FIREFOX: https://developer.mozilla.org/en-US/docs/Web/API/element.innerHTML?redirectlocale=en-US&redirectslug=DOM%2Felement.innerHTML
IE: http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx
GREAT, so that function I've used my entire life has been a LIE I tell you. In fact, the only browser it does work in is Chrome ( I think they are ignoring the standards or something? ).
I managed to figure out that if you put the entire tag around the it, seems to copy it okay... Which is very annoying but has saved my bacon on this occasion.
<div id="TimesheetEntryRow">
<table>
<tr id="row{RowID}">
<td></td>
</tr>
</table>
</div>
Now the above makes sense, but I really did not know innerHTML also does html parsing to check you're not being silly... Can any of you think of another way of not having to put an entire tag set in my templater?
Crazy crazy crazy!
Related posts:
IE+jQuery+Ajax+XHTML: HTML getting clipped after .html() or .innerHTML
My full example template is this:
<div id="TimesheetEntryRow" style="display:none;">
<table>
<tbody>
<tr id="row{RowID}">
<td>blah</td>
<td class="timeSpent"><input name="timeMon[]" type="text" class="form-control inputTimeSpent timeSpent timeMon" placeholder="0" /></td>
<td class="timeSpent"><input name="timeTue[]" type="text" class="form-control inputTimeSpent timeSpent timeTue" placeholder="0" /></td>
<td class="timeSpent"><input name="timeWed[]" type="text" class="form-control inputTimeSpent timeSpent timeWed" placeholder="0" /></td>
<td class="timeSpent"><input name="timeThur[]" type="text" class="form-control inputTimeSpent timeSpent timeThur" placeholder="0" /></td>
<td class="timeSpent"><input name="timeFri[]" type="text" class="form-control inputTimeSpent timeSpent timeFri" placeholder="0" /></td>
<td class="timeSpent timeSpentWeekend"><input name="timeSat[]" type="text" class="form-control inputTimeSpent timeSpent timeSat" placeholder="0" /></td>
<td class="timeSpent timeSpentWeekend"><input name="timeSun[]" type="text" class="form-control inputTimeSpent timeSpent timeSun" placeholder="0" /></td>
<td class="timeSpent"><input disabled type="text" class="form-control timeSpent allocated" /></td>
<td class="timeSpent"><input disabled type="text" class="form-control timeSpent total" value="0" /></td>
<td><textarea name="note[]" class="form-control inputNotes" placeholder="Enter notes"></textarea></td>
</tr>
</tbody>
</table>
</div>
NOTE TO EVERYONE : If you use clone, do not forget to display:block on the css style.
Anyways, even with clone, the above example will not do what you expect (if you think it does, actually go inspect the element and it would have stripped the whole load out)
The problem that you're experiencing is due to the fact that the template isn't valid HTML. <tr> elements must be inside of a <table>, <tbody>, <thead>, <tfoot>, and maybe something else I'm forgetting. When the browser sees the <tr> elements in an invalid place, it just deletes them and moves on, leaving the content where it is. (Same for the <td>s not in a <tr>s.) Therefore, what you can do is to make your template element a <table>:
<table id="TimesheetEntryRow" style="display:none">
<tr>
<td>blah</td>
</tr>
</table>
See a working example here: http://jsfiddle.net/6GSJ4/2/
I know that some frameworks such as AngularJS (one I work with) allow you to put your templates inside of <script type="text/template"> elements since those are not processed as DOM elements by the HTML parser so all of your elements will stay intact. That may be an option if you need it (though .innerHTML obviously wouldn't work).
You could of course just add the html back to the template tag right away. Not optimal, but will get the job done
timesheetTemplateHtml = $("#TimesheetEntryRow").html();
$("#TimesheetEntryRow").html(timesheetTemplateHtml);
I would do it like this. Simply use a table for your template without displaying it:
<table id="TimesheetEntryRow" style="display: none;">
<tr>
<td>aaa</td>
</tr>
</table>
and than just select the template and the destination once on document ready. When needed, clone the template and append it to the destination:
$(function(){
var $table = $( "#TimesheetTable" );
var $row = $( "#TimesheetEntryRow tr" );
$('#button').on('click', function(){
$table.append($row.clone());
});
});
See a working example here: http://codepen.io/timbuethe/pen/czJla/
You can "misuse" the script tag like this:
<script type="text/template" id="TimesheetEntryRow">
<tr id="row{RowID}">
<td></td>
</tr>
</script>
Some JavaScript templating scripts use this, e.g. Underscore.js

unable to hide and show a particular table row with the same id names inside a div using jquery

I am creating a website and there are some pages containing the <div> tags as the wrapper of <table>. A <tr> of each table contains a <form> and another <tr> contains some <a> tags. I am using these anchor tags to make buttons just to add hide and show functionality. Whenever some new data is fetched from database, the set of said html structure is created dynamically. Every <div> contains the same id and every <tr> also containing the <form> assigned the same id. Below is my example htmlfor the better explanation.
HTML
<div class='static_archive'> // First Wrapper
<table>
<tr>
<td>Some data</td>
<td>Some data</td>
<td>
<a id='show_hide_details' href='#'>Show/Hide Button</a>
</td>
</tr>
<tr id='form_container'>
<td colspan='3'>
<form>
<input type='text' name'first' />
<input type='text' name'second' />
<input type='text' name'third' />
</form>
</td>
</tr>
</table>
</div>
<div class='static_archive'> // Second Wrapper
<table>
<tr>
<td>Some data</td>
<td>Some data</td>
<td>
<a id='show_hide_details' href='#'>Show/Hide Button</a>
</td>
</tr>
<tr id='form_container'>
<td colspan='3'>
<form>
<input type='text' name'first' />
<input type='text' name'second' />
<input type='text' name'third' />
</form>
</td>
</tr>
</table>
</div>
jQuery
$(document).ready(function(){
$("#form_container").hide();
$("#show_hide_details").click(function(){
$("#form_container").toggle();
});
});
As soon as the page loads, $("#form_container").hide(); hides all the <tr> containing the <form>. By clicking hide/show button with the toggle effect, hides and shows the every content with the same id.
I want to show only one form at a time when a particular button is hide/show button is pressed. How can i control such behavior?
With a new record fetched, a new DIV is created with only one table inside it. And the table contains only one form. The table row containing the form needs to be hide/show.
Here is the jsfiddle with my code structure jsfiddle
Every clicked hide/show should effects the respective form.
I have edited my post. Please have a look now.
You can use $(this) to do the toggle with particular block.
$(this).closest('tr').next("#form_container").toggle();
You should not use same id for multiple elements, assign class and use that
$(this).closest('tr').next(".form_container").toggle();
I think u want this or may this help u.
You can not have same id's for different controls.So u can have id's staring with same string
You can use ^ here:
$(document).ready(function(){
$("[id^='form_container']").hide();
$("#show_hide_details").click(function(){
$(this).parents().next("tr").toggle();
});
});
jsfiddle
I assume you want to show all of them hidden first. Obviously, you have to replace the id's with class.
$(document).ready(function(){
$(".form_container").hide();
$(".show_hide_details").click(function(){
$(this).parents("tr").next().toggle();
});
});

How to push content of a hidden div tag to a table row using javascript?

I have a table with add more button which adds a certain number of rows with inputs in it. But the HTML string for these rows have grown large enough and its becoming a pain.
So, what I am thinking is to have a div hidden tag with the required HTML that is repeated again and again on clicking the add more button.
So, how to push the div tag innerHTML inside a TR. Below is the code that I need to push, so I kept it inside the hidden DIV tag.
<tr>
<td><label for="bucket_size"><b>1.</b> Bucket Size:</label></td>
<td><input type="text" name="bucket_size[]" id="bucket_size"></td>
<td><label for="control_bucket_size">Control Bucket Size: </label></td>
<td><input type="text" name="control_bucket_size[]" id="control_bucket_size" value="0"></td>
</tr>
<tr>
<td><label for="from_date">Active From: </label></td>
<td><input type="text" name="from_date[]" id="from_date" class="hasDatePicker"></td>
<td><label for="to_date">To: </label></td>
<td><input type="text" name="to_date[]" id="to_date" class="hasDatePicker"></td>
</tr>
<tr>
<td><label for="location">Location: </label></td>
<td class="locationSelect">
</td>
<td style="text-align:center;" colspan="2"></td>
</tr>
It doesn't get inserted properly if I directly insert after the particular TR, the innerHTML of the div tag. How to do it?
You can't have a TR as a child of a DIV, even if the DIV is hidden (it's invalid markup). You can't modify a table by changing its innerHTML in IE < 9 (though you can write an entire table or change the contents of a cell). Use DOM methods.
Likely the best method is to clone a row, then update name and id properties, plus anything else that needs it, and append it to the TBODY. If you append to the TABLE, most browsers are OK but IE will barf, so append to the TBODY.
Extremely simple example:
<table>
<tr onclick="this.parentNode.appendChild(this.cloneNode(true))">
<td>Here is a cell in a row
<td>Here is a cell in a row
</table>
If you're trying to clone a table row then use another table row, not a div. And don't use innerHTML, use cloneNode
<table>
<tr id="clone_me" style="display:none">
<td>...</td>
</tr>
</table>
<script>
var original_node = document.getElementById('clone_me');
var clone_node = original_node.cloneNode(true);
clone_node.removeAttribute('id'); // Prevent duplicate ID
try {
clone_node.style.display = 'table-row';
}
catch(iesucks) {
clone_node.style.display = 'block'; // Should be 'table-row' but need this hack for IE 6-7
}
original_node.parentNode.appendChild(clone_node); // Add new node to end of table
</script>
If you find older IE's struggle with display:table-row then try toggling visibility instead.

Hiding empty inputs by parent row in jquery

I have the following HTML:
<table>
<tr class="row">
<td class="field">
<input type="text" />
</td>
<td class="field">
<input type="text" />
</td>
<td class="field">
<input type="text" />
</td>
</tr>
<tr>
...
...
</tr>
</table>
I want to be able to hide the <tr> with the class="row" but only when the input within the <td> with the class="field" is empty when the page loads.
I've tried this, but it doesn't work:
$('td.field:text[value=""]').parents('tr.row').hide();
However, for some reason, this DOES work:
$('td.field).parents('tr.row').hide();
(ie: it hides all of the rows with class="row")
Also, the following DOES work:
$('td.field:text[value=""]').val('test');
(ie: all empty inputs are populated with 'test' on page load)
I'm new to JQuery so I'm suspecting that I may have just misunderstood the way chaining works. can anyone give me any pointers? It semms like the two parts of what I am trying to do are correct when attempted separately, but don't work together as one.
I think it should be in this way:
$('td.field :text[value=""]').parents('tr.row').hide();
The reason: :text (input) is child from td.field. If you put td.field:text it's wrong because they are diferente selectors.
and why dont you go the oposite way - select the INPUT with empty value, and than go to its
parents().parents().hide()
first parents to get TD, the second one to get TR

How to allow user to enter elements in an HTML table

I want to allow a user to enter a list of persons in a web application, and then submit them as one batch. Each row looks roughly like this:
<TR>
<TD> <INPUT name="person.fname"> </TD>
<TD> <INPUT name="person.lname"> </TD>
<TD> <INPUT name="person.birthdate"> </TD>
</TR>
The form starts out with a single row of blank inputs, and I want a fresh row added to the list whenever the user fills in any of the fields -- i.e. the list grows on demand. Likewise, I want a row to disappear whenever the user clears all fields in it.
What is the easiest, most robust and most maintainable way to implement this?
Finally, how do I submit this table of values back to the server? What is the preferred way to name each field so that the server can create a list of Person entities based on the entered values?
If you are familiar with jQuery, you can use the .change handler to catch them changing the field. Test to see if it's the last row and if there is data in it. If they have taken everything out of the row, remove it. jQuery has some great ways to do this, but it's all dependent on how you want to write it. If so, append the new row using jQuery's .append function. If you're using Python and cgi_app and you use the same name attribute for each type of cell, you can use form.getlist('fname[]') and it will return an array of the names.
What is the preferred way to name each field so that the server can create a list of Person entities based on the entered values?
You can do:
<TR>
<TD> <INPUT name="person[fname]"> </TD>
<TD> <INPUT name="person[lname]"> </TD>
<TD> <INPUT name="person[birthdate]"> </TD>
</TR>
Which generates array 'person'
JQuery is a good suggestion, but if you don't want to use it, you can try generating input name by appending an index. For example:
<TR>
<TD> <INPUT name="person_0.fname"> </TD>
<TD> <INPUT name="person_0.lname"> </TD>
<TD> <INPUT name="person_0.birthdate"> </TD>
</TR>
...
<TR>
<TD> <INPUT name="person_N.fname"> </TD>
<TD> <INPUT name="person_N.lname"> </TD>
<TD> <INPUT name="person_N.birthdate"> </TD>
</TR>
where "N" is the row index. This way may help you to easily get the entire whole row values by using (i.e.) $GET['person'.$i.'fname'], $GET['person'.$i.'lname']... and so on.
CSS:
input:not(:first-of-type){
display:none}
jQuery:
$('input').click(function(){
$(this).val('');
}).blur(function(){
if($(this).val().length>1){
$(this)
.toggleClass('processed')
.hide('slow')
.parents('#person').find('input:not(.processed):first').show('slow');
}
});
$('#person').prepend('Click on blank space to proceed<br/>');
HTML:
<tr>
<form id=person method=post action='/your_page_on_server'>
<td><input name="fname" value='Enter the first name'/></td>
<td><input name="lname" value='Enter the last name'/></td>
<td><input name="birthdate" value='Enter the birth date'/></td>
<td><input type=submit value='Submit'/></td>
</form>
</tr>
I'm not familiar with server-side scripting, so my answer in only partial. Here's an example.
Also, I recommend to add input validation by JS.

Categories

Resources