Question

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.)

Was it helpful?

Solution

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>

OTHER TIPS

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

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> 

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

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

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://....

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.

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...

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>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top