innerHTML not working as expected - javascript

I have searched everywhere for a solution to this problem which I cannot explain.
here is the problem, whenever I use javascript's innerHTML to inject the following string:
example:
var s = "<div><p><div><p></p></div></p></div>"
document.getElementById("id").innerHTML = s;
In Firefox, using firebug, I look at the latest markup and see <div><p></p><div><p></p></div></div>
Anyone know what this occurs?

You cannot nest p or div inside another p. Closing the p is how the browser attempts to make your invalid HTML valid.

Related

Javascript create element and add HTML

say for instance i have the following line:
var arrowBase = document.createElement('div')
Now within this div tag i want to add some HTML (i.e text).
Then i tried the following:
arrowBase.innerHTML('hello');
However this does nothing:S
i have also tried: arrowBase.HTML('hello');
But once again without any result
I know is that rather simple but in my search i could'nt find the answer hope someone is able to help me out here
Read the docs, it is not a method.
arrowBase.innerHTML = 'hello';
arrowBase.textContent = "HELLO"
also does the same thing but only text can be specified. Whereas in innerHTML html tags can be specified along with the text.

Javascript replace does not work only in IE

This code work greate in any browser (included IE)
document.getElementById('solicit').innerHTML += document.getElementById('prod1').innerHTML+"< br >";
But when I try remove this same substring using IE, it does not work! In Firefox or Chorme works OK.
var text=document.getElementById('solicit').innerHTML;
document.getElementById('solicit').innerHTML = text.replace(document.getElementById('prod1').innerHTML+"< br >","");
IE does not recognize the substring with < br > ?
I tried without < br > tag and IE works correctly, but I need to be able to add and remove spaces in my HTML element.
using Firefox or Chorme it's replaced with no problem.
How to solve this problem?
Thanks a lot!
The innerHTML property doesn't have to return the exact string that you assign to it. Some browsers do, but IE doesn't.
In IE when you read the property, the HTML code is constructed from the elements in the DOM, not from the HTML code that was used to create the elements. In IE you will get back <BR> even if you use <br> in the HTML code to create the element. That could be solved with a case insensetive replace, but the same applies to the elements inside prod1, which might not be as simple to solve depending on what the code looks like.
You should rather add/remove elements in the DOM instead of manipulating HTML. When you use += and replace on the innerHTML property, you will be converting the elements to HTML, then create new elements again, including all the elements in the solicit element that you don't change. You might consider using a library like jQuery, which makes it a lot easier to manipulate elements.
View source and you might see
<BR>
so add a ,"i" to the replace to ignore case - and possibly a regex to handle the missing white space in the result tag
Thanks for all the help!
Knowing the information that you passed me by saying that IE interprets the < br > as < BR > I was only able to develop this solution:
var text=document.getElementById('solicit').innerHTML;
if (navigator.appName=='Microsoft Internet Explorer')
document.getElementById('solicit').innerHTML = text.replace(document.getElementById('prod1').innerHTML+"<BR>","");
else
document.getElementById('solicit').innerHTML = text.replace(document.getElementById('prod1').innerHTML+"<br>","");
With this browse verification my code works correctly. But I'm sure my solution is not the most "elegant" as possible.
Is there any other alternative using only javascript?
Thanks again

document.evaluate in chrome and firefox

I need help with this. I am new to using XPath in javascript and this one has stumped me.
My script retrieves the contents of a web page using xmlhttp and then wraps it up in a 'div':
div=document.createElement('div');
div.innerHTML=xmlhttp.responseText.replace(/<img[^>]*>/);
I need to access the body content of this wrapped division and I am using Xpath to do this:
bodyContent = document.evaluate("//*[#id='bodyContent']", div ,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
bodyContent = bodyContent.snapshotItem(0);
While this works perfectly well in firefox and retrieves the required XpathObject it does not give the desired result for google chrome browser. Where instead of returning the bodyContent division of the 'div' element created (and passed as contextNode) it returns the bodyContent of the current document page.
I have checked and in chrome -- the correct xmlhttp.reponseText is received.
Any ideas regarding this?
Thanks,
Does document.evaluate(".//*[#id='bodyContent']", div ,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null) give you the desired result in both browsers?

Append html to jQuery element without running scripts inside the html

I have written some code that takes a string of html and cleans away any ugly HTML from it using jQuery (see an early prototype in this SO question). It works pretty well, but I stumbled on an issue:
When using .append() to wrap the html in a div, all script elements in the code are evaluated and run (see this SO answer for an explanation why this happens). I don't want this, I really just want them to be removed, but I can handle that later myself as long as they are not run.
I am using this code:
var wrapper = $('<div/>').append($(html));
I tried to do it this way instead:
var wrapper = $('<div>' + html + '</div>');
But that just brings forth the "Access denied" error in IE that the append() function fixes (see the answer I referenced above).
I think I might be able to rewrite my code to not require a wrapper around the html, but I am not sure, and I'd like to know if it is possible to append html without running scripts in it, anyway.
My questions:
How do I wrap a piece of unknown html
without running scripts inside it,
preferably removing them altogether?
Should I throw jQuery out the window
and do this with plain JavaScript and
DOM manipulation instead? Would that help?
What I am not trying to do:
I am not trying to put some kind of security layer on the client side. I am very much aware that it would be pointless.
Update: James' suggestion
James suggested that I should filter out the script elements, but look at these two examples (the original first and the James' suggestion):
jQuery("<p/>").append("<br/>hello<script type='text/javascript'>console.log('gnu!'); </script>there")
keeps the text nodes but writes gnu!
jQuery("<p/>").append(jQuery("<br/>hello<script type='text/javascript'>console.log('gnu!'); </script>there").not('script'))`
Doesn't write gnu!, but also loses the text nodes.
Update 2:
James has updated his answer and I have accepted it. See my latest comment to his answer, though.
How about removing the scripts first?
var wrapper = $('<div/>').append($(html).not('script'));
Create the div container
Use plain JS to put html into div
Remove all script elements in the div
Assuming script elements in the html are not nested in other elements:
var wrapper = document.createElement('div');
wrapper.innerHTML = html;
$(wrapper).children().remove('script');
var wrapper = document.createElement('div');
wrapper.innerHTML = html;
$(wrapper).find('script').remove();
This works for the case where html is just text and where html has text outside any elements.
You should remove the script elements:
var wrapper = $('<div/>').append($(html).remove("script"));
Second attempt:
node-validator can be used in the browser:
https://github.com/chriso/node-validator
var str = sanitize(large_input_str).xss();
Alternatively, PHPJS has a strip_tags function (regex/evil based):
http://phpjs.org/functions/strip_tags:535
The scripts in the html kept executing for me with all the simple methods mentioned here, then I remembered jquery has a tool for this (since 1.8), jQuery.parseHTML. There's still a catch, according to the documentation events inside attributes(i.e. <img onerror>) will still run.
This is what I'm using:
var $dom = $($.parseHTML(d));
$dom will be a jquery object with the elements found

Problem with jQuery - error when trying to find 2 tags

I have the following DOM structure:
/*:DOC += <div id='testDiv' class='testDivClass'><div id='innerTestDiv'></div></div><span id='testSpan' class='testSpanClass'><span id='innerTestSpan'></span></span>
Now I tried to run jQuery select against them as follow. The first one returned alright, but the second one failed:
// works
var result = $('#testDiv')[0];
alert(result.id);
// failed: id is null or not an object
var result2 = $('#testSpan')[0];
alert(result2.id);
I tried selecting id instead of class and got the same results.
My question is: how can I get the second select to work? Is there some sort of invisible iterator/pointer in jQuery which I need to reset to the beginning of the DOM before the second select?
Thanks.
EDIT: Ok this is the official "does not work" version. testDiv matched, but testSpan did not, hence I got an error saying id is null or not an object error in the second alert.
UPDATE: I did a test by swapping testDiv and testSpan in the html. Now BOTH select failed.
UPDATE2: I have changed the html back to what it used to look like. I'm using JsTestDriver to write up the test, but it is actually not calling anything at the moment. The actual html looks messier than this (more nested tags). I'm trying to get this simplified version to work first. It appears that jQuery was able to get into the first select, whether it'll be span or div, but couldnt get out of it to do the second select. I've replaced jQuery.js and jsTestDriver.jar to no avail.
Thanks.
The .className selector matches by class, not ID.
Therefore, $(span.testSpan) won't match any elements.
You need to change it to $('span.testSpanClass') ot $(span#testSpan') (using the #id selector, which matches ID).
For more information, read the documentation.
I don't know why, but for me your code worked well.
I added $(document).ready(function() { before that code, and when I opened the test page, the alert box showed up perfectly, both of them! I don't know when do you want this alert box showed, but if it is when visitor open the page, just add that code. Otherwise, add
function objectid() {
var result = $('#testDiv')[0];
alert(result.id);
var result2 = $('#testSpan')[0];
alert(result2.id);
}
That code worked well for me, too.
PS: Sorry if you don't understand my bad english.
More than likely, there is something else wrong with the HTML you're actually using. Since you're posting only a tiny bit of the html, we can't actually test your problem. Post the entire page, or at least the smallest piece of it that actually has the problem when you run your test.
I tested the jQuery code you reported on JS Bin, and the code worked fine. As the code is very basic, I don't think the problem is caused by the version of jQuery used.
What I ended up doing is wrapping the entire html with a div or span tag. I found that jQuery could not get out of a div/span tag once it gets into one (in my above example), so I just make it to go into a div/span tag once.
Not sure whether this is a patch or ugly fix, but it solved my problem for now.
Thanks for all the help!
Use "#" to select by id, use "." to select by class...

Categories

Resources