I have a page that takes information from MySQL database and using PHP generates HTML.
Since this is only a test run, I began to wonder about using the ID's like this, because the final page would be using upwards of 400 different #td[i]'s and #bubble[i]'s.
Questions:
Is there a better practice I should be using?
What whould be a viable option for showing the bubble tables temporarily on mouse hover, but permanently (until another td is hovered/clicked) on click.
Script:
$(document).ready(function(){
$("#maintable").show();
$( "#td1" ).click(function() {
$("#bubble1").toggle();
$("#bubble1").css("background-color", "yellow");
});
$( "#td2" ).click(function() {
$("#bubble2").toggle();
$("#bubble2").css("background-color", "yellow");
});
$( "#td3" ).click(function() {
$("#bubble3").toggle();
$("#bubble3").css("background-color", "yellow");
});
$( "#td4" ).click(function() {
$("#bubble4").toggle();
$("#bubble4").css("background-color", "yellow");
});
$( "#td5" ).click(function() {
$("#bubble5").toggle();
$("#bubble5").css("background-color", "yellow");
});
$( "#td6" ).click(function() {
$("#bubble6").toggle();
$("#bubble6").css("background-color", "yellow");
});
});
</head>
<body>
<h1>Dynamic tables</h1>
<br>
<table id="maintable" border="1">
<tr>
<td id="td1">TD1</td>
<td id="td2">TD2</td>
<td id="td3">TD3</td>
<tr>
<td id="td4">TD4</td>
<td id="td5">TD5</td>
<td id="td6">TD6</td>
</tr>
</table>
<br><br>
<table id="bubble1" border="1">
<td>
Selected tablepart:<br>
<b>TD1</b><br>
Location:<br>
<b>R1F:D3-4:E1</b><br>
Connection:<br>
none <button id="create1">Create</button>
</td>
</table>
<table id="bubble2" border="1">
<td>
Selected tablepart:<br>
<b>TD2</b><br>
Location:<br>
<b>R1F:D3-4:E2</b><br>
Connection:<br>
none <button id="create2">Create</button>
</td>
</table>
<table id="bubble3" border="1">
<td>
Selected tablepart:<br>
<b>TB3</b><br>
Location:<br>
<b>R1F:D3-4:E3</b><br>
Connection:<br>
none <button id="create3">Create</button>
</td>
</table>
<table id="bubble4" border="1">
<td>
Selected tablepart:<br>
<b>TB4</b><br>
Location:<br>
<b>R1F:D3-4:E4</b><br>
Connection:<br>
none <button id="create4">Create</button>
</td>
</table>
<table id="bubble5" border="1">
<td>
Selected tablepart:<br>
<b>TB5</b><br>
Location:<br>
<b>R1F:D3-4:E5</b><br>
Connection:<br>
none <button id="create5">Create</button>
</td>
</table>
<table id="bubble6" border="1">
<td>
Selected tablepart:<br>
<b>TB6</b><br>
Location:<br>
<b>R1F:D3-4:E6</b><br>
Connection:<br>
none <button id="create6">Create</button>
</td>
</table>
And my CSS:
table {
margin-left:auto;
margin-right:auto;
display: none;
border: 1px solid black;
border-collapse: collapse;
}
EDIT:
The best solution so far: (Combined from several answers)
https://jsfiddle.net/Zimpari/3wm01nmL/
As i said i have cooked up a version where the data required for bubble table is implicitly stored inside each record.
https://jsfiddle.net/tLqbks0c/
<table id="maintable" border="1">
<tr>
<td id="td1" data-bubble='{"part":"TD1","location":"R1F:D3-4:E1"}'>TD1</td>
<td id="td2" data-bubble='{"part":"TD2","location":"R2F:D3-4:E1"}'>TD2</td>
<td id="td3" data-bubble='{"part":"TD3","location":"R3F:D3-4:E1"}'>TD3</td>
</tr>
</table>
<table id="bubbleTable" border="1" style="display:none;">
<td>
Selected tablepart:<br>
<b class="part"></b><br>
Location:<br>
<b class="location"></b><br>
Connection:<br>
none <button id="create3">Create</button>
</td>
</table>
$( "#maintable td" ).click(function() {
$("#bubbleTable").show();
var bubData=jQuery.parseJSON($(this).attr("data-bubble"));
console.log(bubData);
$("#bubbleTable b.part").text(bubData.part);
$("#bubbleTable b.location").text(bubData.location);
});
I have to warn you this is a fairly rough draft. You have to handle the server rendering in PHP and MySql . Converting data to JSON format in PHP is fairly easy using json_encode()
For a case like this, it's best to use event delegation. This can be accomplished by utilizing the delegation style syntax for .on(). For example:
$('#maintable').on('click', 'td', function (evt) {
var index = this.id.substring(2);
$('#bubble' + index).toggle();
$('#bubble' + index).css('background-color', 'yellow');
});
This snippet effectively replaces all the event handlers used above in the $(document).ready block. By attaching the single event to a parent element, you allow the events to bubble up the DOM tree and execute via a single handler.
This also works with dynamically generated content. When new content is added new event handlers are not needed.
Reference: .on()
It is pretty much OK to use 400 different ID's but then if there are certain consistent characteristics of these DOM elements, then you should add a class attribute to such elements. So that when trying to access it via selector calls in jQuery it is easier access.
So, even before trying to build a data heavy DOM, here is what you should do
Break your DOM elements into indivisible elements
Combine these indivisible elements into more complex objects
Build a hierarchy among these complex objects
These three steps should help you pretty much in every application.
Considering the current DOM that you are trying to build above, here are my suggestions:
Add a class='bubble' attribute to the <table> elements. Since, all seem to have consistent reason to exist
Inside them, they have <button> elements, it could be given a class='bubble-button' to show the similarity in application.
So while the button is the indivisible element, combine it with <td> to get the complex table data element.
Collection of such table data could make your bubble table.
I hope you see the hierarchy building up. While designing all this, you should realize that JS parsing is not the bottleneck in web applications. It is the modification of the DOM which takes a lot of time. So, you can have a lot of ID's but proper addressing could help you traversing the DOM tree more efficiently. Bad hierarchy in the DOM tree would cost you in the long run.
Now you could add the click and hover handlers as:
$('.bubble').on('yourevent', function(e){
/* handle the click, or onmouseover, or onmouseout events appropriately
by adding or removing CSS classes */
});
Let me know for more clarifications.
Yup. Here's all-encompassing jQuery. Should work.
#War10ck is right, substring is better.
$('td').each(function(){ //you might want to add a class selector, but whatever
var mybubble=$('#bubble'+this.id.substring(2));
$(this).click(function(){
mybubble.toggle().css('background-color','yellow');
});
$(this).mouseover(function(){
if(mybubble.css('display')=='none'){
mybubble.toggle().css("background-color", "yellow")
.attr('data-mouseover','true');
}
});
$(this).mouseout(function(){
if(mybubble.attr('data-mouseover')=='true'){
mybubble.toggle().css("background-color", "yellow")
.attr('data-mouseover','false');
}
});
});
Related
I have a footable
. When I click on the plus to expand a row
I want to access with jQuery the yellow elements:
If I inspect the element the DOM looks like that after the click:
<table class="footable-details table">
<tbody>
<tr><th>
DOB (hide)
</th><td style="display: table-cell;">
10/16/1977
</td></tr><tr><th>
Description
</th><td class="someText" style="display: table-cell;">
Some description
</td></tr>
</tbody>
</table>
What I would like to do, is to set colspan="2" for td.someText and hide the <th>Description</th>. But I can't access td.someText
I tried to access it with
$('.footable').on('expand.ft.row', function(e, ft, row){
$(row.$details).find('td.someText'));
});
but he does not find anything. In fact, alert($(row.$details).html()); only returns
<td colspan="4">
<table class="footable-details table">
<tbody>
</tbody>
</table>
</td>
Any idea how to access the td with class someText after click?
Here is a jsFiddle
Note: This is not a duplicate of Footable and capturing the expand row event. The linked question is about how to access a row in general. This question is if I select it with the method from the API the content is not loaded correctly. The question helped me to get here, but does not to solve the here presented issue.
expand.ft.row event fires before it appends the dom content.so if you try to read the row content, it's not there.
The correct event for your case is expanded.ft.row which fires after appending the content.
$('.footable').on('expanded.ft.row', function(e, ft, row) {
alert($(row.$details).html());
});
check this demo
https://jsfiddle.net/bfmaredn/
I found this event by analyzing the source code from GitHub repository https://github.com/fooplugins/FooTable/blob/V3/src/js/classes/FooTable.Row.js
Use "async function", try the following code:
$(function() {
$(".footable").footable();
$('.footable').on('expand.ft.row', async function(e, ft, row) {
alert($(await row.$details).html());
});
});
Refer:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
I have a calendar where the day cells are clickable "td" elements. Inside each is an "a" that has a title. I need to use this title in a JavaScript function that is called when any of the "td" elements are clicked. I had to disable the PostBack for all "a" elements
Here is code for one of the cells:
<td align="center" style="width:14%;">15</td>
I just need to access the 15 text technically. I can get the month elsewhere.
Is this possible using JavaScript?
Using jQuery for this would be a pretty good idea since you can select elements pretty conveniently. With jQuery you'd use:
$('td a').attr('title');
If you still want to use pure Javascript, you can select the title of the element by using:
document.querySelectorAll('td a')[0].title;
In the end, they both get the job done but the jQuery code is shorter.
So you'd do something similar to this with jQuery.
$('td a').on('click', function() {
console.log($(this).attr('title'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<th>
<tb>
<tr>
<td>
Hey
</td>
</tr>
<tr>
<td>
Oh
</td>
</tr>
<tr>
<td>
Goodbye
</td>
</tr>
</tb>
</th>
</table>
It's not exactly clear to me what you're after, but if you can control the call, then including this in the call gives you a reference to the element that called the listener, e.g.
<a href="javascript:__doPostBack('ctl00$MainContent$Calendar2','6314', this)"...>
Then in the listener, you have a reference to the element and you can get its title property directly, e.g.
function __doPostBack(arg0, arg1, element) {
var title = element.title;
// title is the value of the element's title property
}
I had to disable the PostBack for all "a" elements
I don't understand what that means. If it means you don't want to use __doPostBack to get the title and want to add a listener to each of the links, then you can do that quite simply too:
window.onload = function(){
[].forEach.call(document.querySelectorAll('td a'), function(a){
a.addEventListener('click', showTitle, false)
});
};
function showTitle(){
console.log(this.title);
}
<table>
<tr><td><a href="#" title="foo">foo
<tr><td><a href="#" title="bar">bar
<tr><td><a href="#" title="fum">fum
</table>
<table border="1" cellpadding="5" id="newtable">
<tr>
<th>Room No</th>
<th>AC</th>
<th>Deluxe</th>
<th>Tariff</th>
</tr>
<c:forEach var="room" items="${myrooms}">
<tr bgcolor="#4B476F" onMouseOver="this.bgColor='gold';" onMouseOut="this.bgColor='#4B476F';">
<td class="nr"><c:out value="${room.roomno}" /></td>
<td><c:out value="${room.ac}" /></td>
<td><c:out value="${room.deluxe}" /></td>
<td>₹<c:out value="${room.price}" /></td>
<td><button type="button" class="mybutton" onclick="rowFunction()">Pay</button> </td>
</tr>
</c:forEach>
</table>
On clicking the button corresponding to every row, I want my script to return the Room number i.e. the first cell data of the row. I have tried a lot of things after referring various articles on the Internet. Nothing seems to work. Please help.
You can use something like
Demo
$(window).on('click', '.mybutton' ,function() {
alert($(this).parent().parent().find('.nr').text());
//Or you can use, which is even better
//alert($(this).parent().siblings('.nr').text());
});
Here, the selector is pretty simple, we are first binding click event on the button, and onclick we select the button element parent i.e td and we select the parent of td i.e tr and later we find an element with a class of .nr
You can also write td.nr instead of just .nr to be more specific.
Your rows are being dynamically added, in order for your click listener to work you will have to delegate the events
Credits to #Patsy Issa for suggesting .siblings()
$(".mybutton").click(function(){
alert($(this).parent().siblings().eq(0).text());
});
usually im using DataTables js for solution, you can check at: https://datatables.net/reference/api/row().data()
I am trying to execute a function for each "tr" child element of my "table" with jquery, but this code does not identify the children. I've used this code for "div" based designs before and it works perfectly if I change the "table" and "tr" tags to "div" but it doesn't run here!
This is simple design:
<table id="tblSearch" border="1px">
<tr>
<td>Hello</td>
</tr>
<tr>
<td>Hey</td>
</tr>
<tr>
<td>Hi</td>
</tr>
<tr>
<td>There!</td>
</tr>
</table>
<table>
<tr align="center">
<input id="btnSearch" type="button" value="Search" />
</tr>
</table>
And this is jquery:
$(function () {
$('#btnSearch').click(function () {
var a = $("#tblSearch").children("tr").each(function(){
alert($(this).text);
});
});
});
jsfiddle:
Note that the alert is run just once! And I have also removed the "tr" for children in my jsfiddle to make the code runnable...
could anyone help me?
The tr elements are not children of table, the are children of tbody (or thead or tfoot). The tbody element is automatically created if you don't specify it. You can figure this out easily for yourself if you inspect the generated DOM.
Long story short, either search for all descendants, with .find
$("#tblSearch").find("tr")
// simpler:
$("#tblSearch tr")
or include tbdoy in your selector:
$("#tblSearch").children("tbody").children("tr")
// simpler:
$("#tblSearch > tbody > tr")
That being said, you also have to add the actual content inside td elements, as noted in the other answers.
If you are new to HTML and tables, read the MDN documentation.
There are 2 problems, an invalid html and the selector is wrong
<table id="tblSearch" border="1px">
<tr>
<td>Hello</td>
</tr>
<tr>
<td>Hey</td>
</tr>
<tr>
<td>Hi</td>
</tr>
<tr>
<td>There!</td>
</tr>
</table>
then
$(function () {
$('#btnSearch').click(function () {
var a = $("#tblSearch").find(">tbody > tr").each(function () {
alert($(this).text());
});
});
});
Demo: Fiddle
Problems were:
tables automatically have tbody elements inserted into the DOM, so you should not reference TR's as children of a TABLE element.
You referenced a non-existant text property instead of the jQuery text() function.
You probably want to reference the tds anyway (and probably only a specific TD in each row), as returning the text of an entire row (TR) seldom makes sense in HTML.
JSFiddle: http://jsfiddle.net/TrueBlueAussie/TdGKj/1/
$(function () {
$('#btnSearch').click(function () {
var a = $("#tblSearch td:first-child").each(function () {
alert($(this).text());
});
});
});
The #tblSearch td:first-child selector basically says: "Find the element with id=tblSearch then search for any td elements that are the first child of their parent. Note I added a second column of dummy TDs cells to the JSFiddle so you could see this in practice.
There any many selectors for choosing specific children, which will vary based on your specific needs, but that just needs a little research of jQuery selectors
You don't need to use children at all. You can just create a selector -
$('#tblSearch tr td')
WORKING DEMO - http://codepen.io/nitishdhar/pen/Aiwgm
First you need to fix your HTML structure, place the child td elements inside each tr -
<table id="tblSearch" border="1px">
<tr>
<td>Hello</td>
</tr>
<tr>
<td>Hey</td>
</tr>
<tr>
<td>Hi</td>
</tr>
<tr>
<td>There!</td>
</tr>
</table>
<div>
<input id="btnSearch" type="button" value="Search"/></td>
</div>
Now you can alert each value using this javascript snippet -
$(function () {
$('#btnSearch').click(function () {
$("#tblSearch tr td").each(function(){
alert($(this).text());
});
});
});
Note - This will alert each value separately as you needed.
First of all fix up your html and add the correct tags around the cell data
Then this should do what you're wanting:
$('table#tblSearch tr').children().each(function(){
alert($(this).text());
});
You have multiple problems in the question you provided:
Your HTML is not valid; Place a td element inside each tr
Call the correct jQuery function. Instead of using children('tr'), which it won't find because there are no tr that are children to the table element (only tbody,thead, etc), you will need to call the find() jQuery function (e.g. find('td')) and from there you will be able to get the text of the cell; however, you may also be able to find tr and get text of the whole row in that case.
Here is HTML markup of 2 rows from my huge table (which generated by PHP and applied Datatables after that)
<tr url="?page=item&id=850">
<td class="item_id"><input type="checkbox" name="checkbox[]" method="post" value="850" class="checkbox"/> 850</td>
<td> 9007</td>
<td style="text-align:center">BK</td>
<td style="text-align:center">41</td>
<td style="text-align:center" id="qt">1</td>
<td style="text-align:center">7</td>
<td style="text-align:center">11</td>
<td>09.02.2012</td>
</tr>
And here is second row
<tr url="?page=item&id=587">
<td class="item_id"><input type="checkbox" name="checkbox[]" method="post" value="587" class="checkbox"/> 587</td>
<td> 779-59</td>
<td style="text-align:center">BR</td>
<td style="text-align:center">37</td>
<td style="text-align:center" id="qt">2</td>
<td style="text-align:center">15</td>
<td style="text-align:center">14</td>
<td>08.02.2012</td>
</tr>
Function below works for 90% rows. I really have no idea why this script works for second row from examples but doesn't do anything for first row. These 2 rows are nearly same.
$("td").not('.item_id').click(function(){
window.open ($(this).closest("tr").attr("url"));
});
How do you think, what can cause this problem?
Instead use this which will attach click handler on tr and ignore if clicked on checkbox or its containing cell. Try this.
$("tr").click(function(){
window.open($(this).attr("url"));
});
$("td.item_id").click(function(e){
e.stopPropagation();
});
Alertnatively you can also use event.target to check if it is checkbox don't do any this.
$("tr").click(function(e){
if(!$(e.target).is(':checkbox') && !$(e.target).is('.item_id')){
window.open($(this).attr("url"));
}
});
I understand this piece:
$("td").not('.item_id').click(function(){
...
});
But could this piece be updated to perform better?
window.open ($(this).closest("tr").attr("url"));
Also, does the property url validate? You may want to use data attributes for a more predictable experience. Maybe this would work better:
<tr data-url="">
...
</tr>
with your window open even like this:
window.open( $(this).parent().attr("data-url") );
See this example: http://jsfiddle.net/Zuhrx/
its working HERE something else is wrong. Are you wrapping up the code in ready handler?