How to get content of <noscript> in Javascript in IE7?
Asked Answered
W

9

27

I'm trying to get the content of a <noscript> tag using Javascript. I succesfully managed to get it in FF, Chrome, Opera and even IE6 but fail on IE7 (haven't tried IE8+ yet).

Basically, here's the reduced code version :

<noscript>Lorem ipsum</noscript>
<script>
    var noscript = document.getElementsByTagName('noscript')[0];
    noscript.textContent; // undefined
    noscript.innerHTML; // empty string
    noscript.childNodes.length; // 0
</script>

I tried adding element inside and targeting them, no success. I tried to wrap in a parent element and getting its .innerHTML, but anything between <noscript> tags is discarded.

Note : I'm building a lazyloader script and the <noscript> element is just what I need (<img> src attributes inside a <noscript> tag are not fetched by the browser.)

Wetterhorn answered 26/11, 2010 at 1:16 Comment(8)
have you tried putting an id to your noscript and and use getElementById?Alden
Yes, the issue is not selecting the noscript element (it works either with getElementById or getElementsByTagName), it really is accessing the content.Wetterhorn
document.getElementsByTagName('script')[0] - you're querying for a script element, not a noscript element. What did I miss?Bivins
Sorry, typo. I really am querying the noscript elements. I fixed that in the initial post.Wetterhorn
@Pixelastic: Does the noscript content need to be fully represented as a subtree in the DOM?Kindred
@Tim Down : I'm not sure to get what you mean ? I want the noscript content to display as normal DOM elements for js-disabled browsers but also want to be able to replace the noscript to div (for example) to display it on demandWetterhorn
@Pixelastic: OK. I was wondering whether a text representation of the HTML would be good enough, but actually that's a silly question. Ignore it.Kindred
I confirm that this is a problem in Internet Explorer 8 as well.Moo
K
25

In IE 7 and 8, it's simply impossible to retrieve the contents of a <noscript> element. Any content between the <noscript> and </noscript> tags in the HTML is not reflected in the DOM in IE, the element has no children and innerHTML and innerText are empty strings.

In IE 6, the situation is curious: in common with IE 7, the <noscript> element has no child nodes but its contents are reflected in the innerHTML and outerHTML (but not innerText) properties of the element.

All this being the case, your only option in IE is to put the content in your <noscript> element inside some other element instead. To emulate the behaviour of a <noscript> element, you could put the content in an element that is immediately hidden by JavaScript (when script is enabled):

<div id="noscript">Lorem ipsum</div>
<script type="text/javascript">
    document.getElementById("noscript").style.display = "none";
</script>
Kindred answered 29/11, 2010 at 11:31 Comment(10)
^ This. It's pretty absolute - no DOM, no data.Transduction
Actually, you can get the content of a noscript in IE6 with .innerHTML, but not in IE7Wetterhorn
@Pixelastic: textContent doesn't exist in IE6, but you're right that innerHTML does contain the content. I've amended my answer.Kindred
@Tim Down : This will not exactly emulate the noscript behavior. By doing so, all iframe and img tags in the div#noscript will still have their src content fetched before being hidden. And that is precisely what I want to avoid. But thanks for your clarification, anyway.Wetterhorn
@Pixelastic: I know, and I've tried to think of a way round that but I don't think one that will satisfy you exists.Kindred
@Tim Down : I've accepted your answer, because even if it is not the perfect solution I was hoping for, you took the time to do some testing and we finally both get to the same conclusion.Wetterhorn
Instead of using a <div>, try using <script type="text/html">. This won't execute (because text/html isn't a known "scripting language"), nor will it be built into a DOM fragment (so images, etc. won't be loaded), but it will be available as a text node (.innerText / .textContent).Mecham
@Ben: You're right, and this was what I was trying to get at when I asked in my comment to the question *"Does the noscript content need to be fully represented as a subtree in the DOM?" but realised that this doesn't fulfill the requirements: the content has to be rendered when JavaScript is disabled, which it wouldn't be in your solution. It can only be turned into DOM nodes when JavaScript is enabled, which is precisely the wrong way round.Kindred
@Tim — Then I think you're stuck with a suboptimal solution. :-/Mecham
Thanks, both of you. The text/html trick could prove useful in another project.Wetterhorn
S
4

Not the most elegant solution - Images load as normal with IE7 and IE8, and all other browsers get the added benefit of lazi loading. You will end up with some empty comment blocks in the final output... but who cares, right?

<!--[if (gt IE 8)|!(IE)]><!--><noscript><!--<![endif]-->
  <img src="/path/to/img.jpg" alt="photo" />
<!--[if (gt IE 8)|!(IE)]><!--></noscript><!--<![endif]-->

JavaScript (jQuery - if you need real JS let me know):

jQuery(function($) {
  $('noscript').each(function() {
    var $this = $(this);
    $this.replaceWith($this.text());
  });
});

Tested with IE7+, Chrome, FF3.6+, Opera11

Suu answered 17/11, 2011 at 0:13 Comment(0)
A
2

One work around for this is to duplicate the content of noscript as its attribute.

For example:

<noscript id="ns" alt="Lorem ipsulum">Lurem ipsulum</noscript>

On the script get the value of alt attribute instead of its innerHTML

<script>
   var ns = document.getElementByid('ns');
   var htm = ns.innerHTML || ns.getAttribute('alt');

   alert(htm);

</script> 
Alden answered 26/11, 2010 at 2:25 Comment(2)
That is one ugly workaround! Why does IE do this to use... :(Pulmotor
This could be a useful workaround, but unfortunatly not in my case. I oversimplified my example but my real code contains hundreds of HTML lines in the <noscript>Wetterhorn
I
2

You can access the noscript tag textContent property in most modern browsers. For older browsers I have written a polyfill which runs pretty quickly and in all desktop and mobile browsers I could test.

View the blog post: http://queryj.wordpress.com/2012/07/06/read-noscript-tag-content-reliably-in-all-browsers/

View the code (Dual licensed under the MIT and GPL licenses): https://github.com/jameswestgate/noscript-textcontent/

EDIT:

The script works by reloading the page through an ajax request (which should be cached in the browser) and parsing the contents manually for browsers which do not support the textContent property

Intelligentsia answered 6/7, 2012 at 13:21 Comment(0)
S
1

You could

<script>document.write('<script id="images" type="text/html">')</script>

just before the images and then

<script>document.write('</scr'+'ipt>')</script>

after it. You'd have the images available without javascript, and with JavaScript there, you'd have their sources at your disposal in $('images').innerHTML

Silvanus answered 9/2, 2011 at 20:40 Comment(0)
M
0

I have a different approach, with a working example of it here: https://github.com/jokeyrhyme/noscript.js/blob/c104c480b595278e9d559aaf8a26668b7c852f72/noscript.js#L25

My approach is simple:

  1. perform an XHR to download a raw copy of the original HTML
  2. find all noscript elements in the DOM
  3. find all noscript elements in the original HTML
  4. replace the DOM noscripts with the contents of the original noscripts

My noscript.show() method tests whether this is necessary first. For most browsers, it just moves the contents of the noscript elements out so that they are visible.

Users who are stuck with these terrible browsers probably have no choice about it, and are probably used to having a slow experience, so an extra network request and some regular expressions aren't going to be too bad.

Note: due to the Same-Origin rule, you may have trouble using this technique when browsing files on your local disk via file:///..., so it's likely to work only when browsing via http://... or https://....

Moo answered 9/3, 2014 at 20:31 Comment(2)
This is better than many suggestions here, because you can use noscript elements the way you always have without needing any JavaScript class manipulation or duplication of content in attributes.Moo
I just realised that my approach is almost exactly like @james-westgate's solution. Oops!Moo
C
-1

I don't have an ie browser on me at the moment ;) but as far as I remember the content of a <noscript> tag is avaliable when you get its parent tag's .innerHTML(). Then it's up to you to get it out (with a nasty regexp for example)

I can't test it for at least 7 hours from now, so I post this info as is.

PS. My advice is to redesign. Noscript tags are ment to contain stuff that is NOT used when scripts are on.

Criterion answered 2/12, 2010 at 12:10 Comment(2)
I'm going to test your solution, that may work. And I'm understanding the noscript tag with a subtle difference : I think it is used to DISPLAY stuff when scripts are OFF. But I agree the subject is open to discussions.Wetterhorn
I just tried, and your solution does not work either. I got a <NOSCRIPT></NOSCRIPT> for the .innerHTML and a <DIV id=test><NOSCRIPT></NOSCRIPT></DIV> for the .outerHTML. Any content inside the <noscript> tags seems to get discarded from the DOM earlyWetterhorn
E
-2

You're querying the script elements instead of the noscript elements, This works in all browsers:

<noscript>Lorem ipsum</noscript>
<script>
    var noscript = document.getElementsByTagName('noscript')[0];
    alert(noscript.innerHTML); // Lorem ipsum
</script>
Evenhanded answered 29/11, 2010 at 10:42 Comment(3)
No it doesn't: try it in IE7, for example.Kindred
Oh. That was a typo, I really was querying the noscript elements. I updated my initial post. The innerHTML is still empty, btw. (And I wanted to up your response, but I have put too much points in the bounty and can't even up response anymore -_-)Wetterhorn
My bad, I tested in IE6, firefox and chrome.Evenhanded
A
-2

This is a really dirty hack, and completely untested but i just had the idea :D

You could do as others have suggested, put the content in a div rather than a noscript, and in addition to hiding it, immediately remove the src attribute of all the img tags using something to the effect of:

jQuery(function () { 
    jQuery('div#noscript img').attr('src', '');
  });

This should limit (but not eliminate) the fetching of images.

This is just a though based on comments and the suggestions of others, hope it helps.


Edit - another dirty hack i've just thought of, which assumes that you can change where the html lives, so may or may not be relevant:

Inside the noscript have a

<iframe width="100%" height="100%" src="?noscript=true" />

then you can XMLHttpRequest for the noscript content...

Ashliashlie answered 6/12, 2010 at 5:29 Comment(1)
Actually, this is how most of the lazyloader scripts works today. This is absolutly not cross-browser (removing the src elements will stop the request on some browsers only) and will only mitigate the image loading on image-heavy pages, anyway.Wetterhorn

© 2022 - 2024 — McMap. All rights reserved.