Why doesn't .html() replace everything with current value? - javascript

Here is my code:
$('table').html('<tr><td>test</td></tr>');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<img src="default.jpg" />
</table>
As you see, that image is still there. Why? I've used .html, so this is expected result after executing this: $('table').html('<tr><td>test</td></tr>');
<table>
<tr>
<td>test</td>
</tr>
</table>
How can I do that?

The reason is that the img isn't inside the table as of when you call html, because it's not allowed to be. <table><img ...></table> is invalid markup; tables can only directly contain certain table-related elements, not img elements. So the browser fixes it for you by moving the img out of the table. (For instance: Chrome fixes it by moving the img to just in front of the table: <img ...><table></table>.)
If it were in the table in the first place, yes, calling html to replace the table contents would work:
$('table').html('<tr><td>test</td></tr>');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td>
<img src="default.jpg" />
</td>
</tr>
</table>
In a comment you've asked:
...how can I select the image in this? <img src="#" /> <table></table> ? Actually I want to start selecting with table tag. like this $('table').sibiling ...
I don't think you can, reliably, because again the original markup was invalid and so browsers are free to do what they want to handle it. That said, Chrome, Firefox, and IE11 all seem to put the img before the table, so $("selector-for-the-table").prev() should be the img:
var table = $('table');
table.html('<tr><td>test</td></tr>');
table.prev().remove(); // Remove the img
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<img src="default.jpg" />
</table>

IMG is not a text tag. If you want to hide it, you must remove it.

Related

How to identify xpath of an element which do not have any attribute information

I want to identify an element which is a text "My Portal" from td tag. Below is my HTML
<tbody>
<tr>
<td>
<!-- rendered always true, custom column names are also label -->
My Portal
<!-- rendered always false, this feature is not required -->
</td>
</tr>
</tbody>
I have tried below xpaths as shown below, but none of them works:
1. .//td[text()="My Portal"]
2. .//td[contains(text(),"My Portal")]
After some search in the internet I found normalize-space() method which will remove the trailing and unnecessary white spaces. I have tried the method using the below xpath
.//td[normalize-space()="My Portal"]
Am able to identify the element, but in the firebug it is showing as 2 matching nodes. Please find the attachment for the highlighted elements in the firebug
My questions are:
Why two tags are getting highlighted?
Why .//td[contains(text(),"My Portal")] does not work?
How to identify the "My Portal" uniquely?
Can anyone please help?
There are several solutions. An efficient approach is to specify the exact path from the root node to the td you want. Something like
/html/body/table/tbody/tr/td/table/tbody/tr/td[normalize-space()='My Portal']
If you know that there are no more than two nesting tables, you can shorten this to
//td//td[normalize-space()='My Portal']
If you want the td in the innermost table regardless of table structure, try
//td[not(.//table) and normalize-space()='My Portal']
This isn't very efficient though. If you know that the text "My Portal" appears in an immediate text child of td, try
//td[text()[normalize-space()='My Portal']]
To uniquely identify the second td, what you have to do is add an additional filter. So if you look at the difference between the 2 tags highlighted, the parent has a class and the child doesn't. So if you need the second td, the xpath would be //td[normalize-space()='My Portal' and not(#class='rich-table-cell')]
If you need the parent then: //td[normalize-space()='My Portal' and #class='rich-table-cell']
Instead of using text() try .
.//td[contains(.,"My Portal")]
To Answer your questions:
1- Because you are using a global selector, "//", with this selector XPAth will find all the elements into the tree, so if you want select only one td you should specific the path, something like this
/table/tbody/table/td[contains(text(),"My Portal")]
2- The command that you are using it should work, I already tried, check your path again, maybe you are not selecting his parent or you are starting from the wrong path.
function xpath(){
var input = document.getElementById("xpath").value
var cell = document.evaluate( input, document, null, XPathResult.ANY_TYPE, null );
var cellvalue = cell.iterateNext();
console.log(cellvalue);
alert(cellvalue.data);
};
<html>
<head>
</head>
<body>
<input type="text" id="xpath" value='//body/table/tbody/tr/td/table//td[contains(text(),"My Value")]/text()'/> <input type="button" onclick="xpath()" value="Execute"/>
<table>
<tbody>
<tr>
<td>
<table>
<tbody>
<tr>
<td>
My Value
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</body>
</html>

jquery not picking up html

So I have the following HTML
<div class="tmpl" id="query_tmpl">
<tr>
<td></td>
<td class="primary_email"></td>
</tr>
</div>
and the following JS:
console.log($('#query_tmpl').html());
For some reason this only logs the 'a' tag. (Ex: http://jsfiddle.net/L8RQq/ )
Why does this happen and how do I get around it so that I can properly pick up the tr/td? I'm using jQuery 1.9.2 if that makes any difference.
Update:
Yes, the markup is 'bad html', but the whole point of this question is how to get around that. Using the HTML present and without altering it, how can I grab the contents even though it's 'bad'?
You don't have table tags around your tr. Try this:
<div class="tmpl" id="query_tmpl">
<table>
<tr>
<td></td>
<td class="primary_email"></td>
</tr>
</table>
</div>
This will log the div's contents properly.
the reason it wasn't logging, is because the browser sees some invalid tr and td tags, and removes those, because they can only be in a table, leaving you with only the a.
If you can't change the markup, tell the person / company that wrote that markup to fix it. It's invalid HTML.
Make it like this
<table class="tmpl" id="query_tmpl">
<tr>
<td></td>
<td class="primary_email"></td>
</tr>
</table>
Then it will surely work correctly
If you want to pick up tr's or td's you can use css manipulation functions such as children([selector]) where selector is eventually a class

javascript jquery response HTML into a div do not retrieve all HTML

I am doing a Ajax call with jquery and putting the content inside a div like this:
$('#replace').html(response);
But it is not replacing all the content I got from 'response'.
When I do :
alert(response)
I see all the HTML code with no problem.
But when I do:
$('#replace').html(response);
It does not put all the HTML code from response.
When I do an alert
alert(response);
I got this (which is correct):
#
<div id='replace'>
<tr onclick='javascripot:gravaJOBparaView(5746);' ondblclick='fnOpen(5746);' >
<td class='preview' title='8746' >8746</td>
<td>XXXX</td>
<td>xxxxx</td>
<td>xxxx</td>
<td>xxx</td>
<td>xxxxx</td>
<td title='xpto'>XXXXXX</td>
<td></td>
<td> <br/>18:00</td>
<td>22/07/2012</td>
<td title='Check XXXXX' class='popups' ><a href='#popup_5746'><img src='xpto.png' alt='Check XXXXXX' width='40px'></a></td>
</tr>
</td>
#
But When I do the:
$('#replace').html(response);
It puts this code in the div 'replace':
#
<div id="replace">
8746
XXX
XXXX
XXXX
XXXXX
XXXXX
RXXXXXX
<br>18:00
22/07/2012
<img width="40px" alt="Check XXXXX" src="xxxxxx.png.png">
</div>
#
As you can see for some reason it does not put all the tags from response.
What should I do?
Your HTML isn't valid. <tr> must be in a table tag.
Replace
<div id='replace'>
by
<table id='replace'>
Replace the last </td> by a </table>
http://jsfiddle.net/wk4eD/1/
Two element must not have the same id in your page
You need to mind the html nesting rules. <td> must be inside a <tr> which must be within a <table> (technically you need a tbody or thead, but browsers are tolerant of this one).
You should use this service:
http://validator.w3.org/#validate_by_input
Under More Options, choose to validate HTML fragment and match your doctype. You can use that to make sure the HTML is valid before trying to stuff it into that div.
you have to close the div you might want to use
</tr>
</div>
</td>
at the end. JQuery might replace text before because it cannot find proper div end statement.

jquery append and jquery html not working in IE 7 or 8

I have the following code in an external JavaScript file that is called within <head>:
function dailyDealWidget() {
$.getJSON('http://myurlhere.com?_render=json', function(data) {
$('#dd-thumb').append('<img src="'+data.value.items[0].deals.deal.splashpagemainimage+'" />');
$('#dd-description').append(data.value.items[0].deals.deal.offer+' from '+data.value.items[0].deals.deal.merchantname);
$('#dd-value').append('$'+data.value.items[0].deals.deal.productvalue);
$('#dd-discount').append(data.value.items[0].deals.deal.totaldealcount+'%');
$('#dd-price').append('$'+data.value.items[0].deals.deal.saleprice);
$('#dd-sold').append(data.value.items[0].deals.deal.inventorytaken+' Sold');
}); //End json
}
Within <body> I have this:
<script type="text/javascript">dailyDealWidget()</script>
<div id="dd-widget"></div>`
<div id="dd-widget">
<div id="dd-container">
<div id="dd-thumb"></div>
<div id="dd-infobox">
<div id="dd-description"></div>
<table width="165px" cellpadding="0" cellspacing="0">
<tr>
<th>Value</th>
<th>Discount</th>
<th>Save</th>
</tr>
<tr>
<td id="dd-value"></td>
<td id="dd-discount"></td>
<td id="dd-price"></td>
</tr>
<tr>
<td colspan="3" id="dd-sold"></td>
</tr>
</table>
</div>
<div style="clear:both;"></div>
</div><!--End container-->
</div><!--End dd-widget-->
It appears that .append() is not adding the content to the desired locations in IE. I've also tried using .html() rather than .append() but without any luck.
There are no errors in the console... both in Firebug and in IE's developer tools.
Any help would be appreciated.
Try to invoke dailyDealWidget after the page has been loaded.
.append() & .html() DO work in IE 7 & 8, so this is not the problem. Have you tested to make sure that the callback function for getJSON is actually being called? Have you examined the actual strings being passed to .append() prior to trying to perform the append itself?
Try logging something to the console at the beginning of the $.getJSON callback function to make sure that's actually running, and then try logging the strings you're passing to the .append() functions.
Are the DIV appends working and just not the TD appends? if so, try to re-draw the whole TR row into one variable then replace the existing row.

Can you use CSS to reference a parent or child of a certain object?

I guess I am spoiled with JavaScript. If you want to change something about the parent, you can code something like parentNode.style.etc.
<TABLE id="hasID">
<TBODY>
<TR>
<TD>
<IMG id="hasID2" src="somePicture.png">
<IMG id="hasID3" src="someOtherPicture.png">
</TD>
</tr>
<tr>
<td>other stuff</td>
</tr>
</tbody>
</table>
As you can see from my code table has an id, and the img tags have ids. What I would like to do is add a stype class to the first TD, so that all the images are aligned to the left or middle, that kind of thing.
However, here is a tricky part, I don't want to user JavaScript, because it looks to slow. Everything starts out on the right, and then jump to the center, after everything is loaded.
Also, here is a second tricky part. I can't change add a class to the TD, because it generated by JSF.
So my main question is can I do this with CSS.
UPDATE:
I don't really need to reference a parent. Referencing a child will also work for me.
You can't select a parent via CSS. It was proposed as a feature but it's not even close to implementation.
I will suggest that you move any javascript you have to just after the content above, which means that it will run as soon as that part of the section is rendered, thus removing any delay.
<TABLE id="hasID">
<TBODY>
<TR>
<TD>
<IMG id="hasID2" src="somePicture.png">
<IMG id="hasID3" src="someOtherPicture.png">
</TD>
</tr>
<tr>
<td>other stuff</td>
</tr>
</tbody>
</table>
<script type="text/javascript">
var img = document.getElementById("hasID2");
img.parentNode.style.textAlign = "right";
</script>
Inline Javascript is OK to use in these scenarios.
Sorry no way to select parent in css.
Is there a CSS parent selector?
Not sure if this will help, but I'll mention that you can add classes using JSF with styleClass="", depending on how you are generating the table. There is also a columnClass="" if you are putting these in a datatable.

Categories