[Javascript] document.write anyone ?



  •  Just using the "document.write" horror isn't enough to claim a WTF, yes I know.

     It's very bad practice in 99% of the cases, but still : it's all too common to be even noticed here.

     However, I found this one (should I say these two ?) .. well... interesting.

    document.write('<script type=\"text/javascript\">
    <!--
    var bseuri = \'http://script.banstex.com/script/affichagejs.aspx?zid=XXXX&rnd=\' + new String (Math.random()).substring (2, 11);
    document.write(\'<scr\'+\'ipt language=\"javascript\" src=\"\'+bseuri+\'\"></scr\'+\'ipt>\');
    -->
    </script>'
    )

     



  • I know many people use <script> tags and document.write() as a poor man's* include() replacement. Especially ad networks seem to be notorious for burying the actual banner code under heaps of iframes and script tags like that. I've always wondered what's the deal with that but I can only assume it has something to do with their ad rotation and impression count systems.

    I have no idea though what the guy who fabricated that thing above thought. My guess is: nothing.

    I like though how he even writes out the fake HTML comments. Just so browsers that don't understand JS don't get confused when they execute the outer JS... wait...

    *(Or not so poor actually - a request to add a proper include command for HTML in HTML5 has been declined with the reason "Why would you need it? You can just use script tags and document.write()...")

     



  • @PSWorx said:

    *(Or not so poor actually - a request to add a proper include command for HTML in HTML5 has been declined with the reason "Why would you need it? You can just use script tags and document.write()...")
    Not to defend ivory-towered decisions too much, but what you can do instead is create an [url=http://krook.org/jsdom/HTMLScriptElement.html]HTMLScriptElement[/url] and set its src attribute; no mess necessary.

    However, as any Enterprise Senior Architect Design Engineer knows, the real solution is to encapsulate the script source/content in a CLOB on an enterprise database enhanced with webservice-enabled enterprise middleware and fetch it via SOAP message interface dispatched from AJAX and decoded to the industry-standard best practice of a web-safe document.write invocation. That's how the big boys play, and we play for keeps.



  • @Xyro said:

    @PSWorx said:
    *(Or not so poor actually - a request to add a proper include command for HTML in HTML5 has been declined with the reason "Why would you need it? You can just use script tags and document.write()...")
    Not to defend ivory-towered decisions too much, but what you can do instead is create an HTMLScriptElement and set its src attribute; no mess necessary.

    What I meant was including bits of HTML, not script. Basically what <?php include(...) ?> does on the server side. What many people do is to have a JS file that only cointains a single statement - a document.write with a huge chunk of escaped HTML. Then they can "include" that JS file using <script> tags with src attributes. The detour via JS is only necessary because there is no way to include one HTML document directly in another. You can only include script.

    @Xyro said:

    However, as any Enterprise Senior Architect Design Engineer knows, the real solution is to encapsulate the script source/content in a CLOB on an enterprise database enhanced with webservice-enabled enterprise middleware and fetch it via SOAP message interface dispatched from AJAX and decoded to the industry-standard best practice of a web-safe document.write invocation. That's how the big boys play, and we play for keeps.

     

    I have nothing to add.



  • @PSWorx said:

    What I meant was including bits of HTML, not script.
    Oh, yes, that would be pretty useful. I wouldn't be surprised if the decision makers are under the impression that no one serves webpages from anything other than a behemothly enterprisey pre-processing xml-crushing application server.
    Say, didn't the late XHTML 2 spec have something or other like an include? I recall talk of being able to smoosh src attributes into anything. Sigh, I would have liked if XHTML had been realized. Oh well, it deserved its stupid death.

    One day we'll be able to ditch HTML for a useful structure-centric declarative description language, and our grandchildren will mock us for putting up with the stupidities and frustrations that currently make us money. "Sonny, back in my day, we had doubly nested iframes in triply nested divs! And boy were we ecstatic when ole' IE could render transparent clipart! Look at you kids these days, with your fancy includes and declarative animations and deterministic styling, how can you call this art if you've never suffered??"



  • @PSWorx said:

    there is no way to include one HTML document directly in another. You can only include script.

    <pedant>Unless you explain to your webserver to treat html as script. </pedant>


  • 🚽 Regular

    It looks like the only purpose for this is to use random strings in the URL, presumably to avoid caching, to circumvent some kind of ad blocker, or something like that.

    The second document.write is simply there to include that javascript using the generated URL. As far as I can tell, if you want to ensure a somewhat unique, random URL, and you want a single piece of Javascript to have random website owners, regardless of their web server's configuration, to simply copy and paste, this is the only way. If it wasn't for that randomization in the URL, a simple <script src="http://script.banstex.com/script/affichagejs.aspx?zid=XXXX"></script> would suffice, of course.



  • @Xyro said:

    Not to defend ivory-towered decisions too much, but what you can do instead is create an HTMLScriptElement and set its src attribute; no mess necessary.
    I would be very happy to agree. You just forgot to feed "the beast".


  • Considered Harmful

    Please, tell me you're trolling.

    You can do all of that with one document write... Or, more properly, by creating an HTMLScriptElement as Xyro pointed out.

    document.write is on my shit list along with eval, and passing strings into setTimeout/setInterval/the Function constructor. I have yet to find one example* using any of them that couldn't be better accomplished with either DOM methods or closures and currying.

    *I have yet to encounter one; I concede such an example may exist.



  • @RHuckster said:

    this is the only way


    var script = document.createElement('script');

    script.src = 'http://script.banstex.com/script/affichagejs.aspx?zid=XXXX&rnd=' + String(Math.random()).substring (2, 11);

    document.body.appendChild(script);



  • @toshir0 said:

    I would be very happy to agree. You just forgot to feed "the beast".
    Excuse my unclearness here (some people seem not to read the tags ... ?) : unless you have the sheer joy of working on a project where compatibility with IE6 has been abandonned.... the DOM alternatives don't work on this pile of shit. And, yes, totally yes, it is a pain in the ass.



  • @Xyro said:

    @RHuckster said:
    this is the only way


    var script = document.createElement('script');

    script.src = 'http://script.banstex.com/script/affichagejs.aspx?zid=XXXX&rnd=' + String(Math.random()).substring (2, 11);

    document.body.appendChild(script);

    That won't work if the page has multiple BODY tags. (I know, I know, I have retarded clients.)

    Replace the last line with document.getElementsByTagName('BODY')[0].appendChild(script) and you're golden.


  • 🚽 Regular

    @Xyro said:

    @RHuckster said:
    this is the only way

    var script = document.createElement('script');


    script.src = 'http://script.banstex.com/script/affichagejs.aspx?zid=XXXX&rnd=' + String(Math.random()).substring (2, 11);

    document.body.appendChild(script);

    Sorry, I must have not been clear on what I meant
    by "random website owners." I include all WTF website owners who may
    have no body tag, multiple body tags, or who have otherwise horribly screwed up DOMs that today's flexible browsers will somehow miraculously render fine, yet will leave DOM-specific functions like createElement and appendChild futile. If I had full confidence that the folks who will use my script will use at least some kind of coherent HTML, then I'd do it "right" but instead of getting inundated with email after email of idiots asking me why "the codez do not werk on my interweb page" because I assumed they'd be literate in HTML, I'd rather just say 'screw it' and dumb the Javascript down so even the most inept of webmasters who at least know how to Ctrl-C Ctrl-V can get it working.



  •  @Xyro said:

    @RHuckster said:
    this is the only way
    var script = document.createElement('script');
    script.src = 'http://script.banstex.com/script/affichagejs.aspx?zid=XXXX&rnd=' + String(Math.random()).substring (2, 11);
    document.body.appendChild(script);

    Creating an image object and setting its src, loads the image.

    What happens with that script?


  • Discourse touched me in a no-no place

    @toshir0 said:

    some people seem not to read the tags ... ?
    Some people simply don't get presented with them. (Email and threaded view.)



  • @PJH said:

    @toshir0 said:
    some people seem not to read the tags ... ?
    Some people simply don't get presented with them. (Email and threaded view.)

    And some people ignore them because they're dumped into the poster's signature and those people ignore signatures.



  • @Thief^ said:

    @PJH said:

    @toshir0 said:
    some people seem not to read the tags ... ?
    Some people simply don't get presented with them. (Email and threaded view.)

    And some people ignore them because they're dumped into the poster's signature and those people ignore signatures.

    Plus they get regularly deleted, so don't rely on them for any information critical to the thread. Or people reading it in a couple weeks when the tags are gone are going to be totally lost.



  • @dhromed said:

    Creating an image object and setting its src, loads the image.

    What happens with that script?

    In Firefox 3.6, the script does will not download until the element is attached to the DOM. Can't be bothered to check other browsers.

    After reading the responses to my excerpt, I have modified it to take a more robust and enterprise best practices approach to dynamic Javascript insertions. Hopefully this will address all of your concerns. Behold:

    <script type="text/javascript">//<![CDATA[
    	(function(){
    		var script = document.createElement('script');
    		script.type = 'text/javascript';
    		script.textContent =
    			'//alert(\'Calling document.write...\');\n' +
    			'document.write("'+
    				'<script language=\'JavaScript\'><!--\\n'+
    				'	alert(\'Hello, world.\');\\n' +
    				'--></'+'script>");\n' +
    			'//alert(\'...document.write called.\');';
    		(function(){
    			var bodies = document.getElementsByTagName('body');
    			if (bodies)
    				return bodies[0];
    			else
    				return document.documentElement;
    		})().appendChild(script);
    	})();
    	//alert('Done');
    //]]></script>
    



  • @Xyro said:

    @dhromed said:

    Creating an image object and setting its src, loads the image.

    What happens with that script?

    In Firefox 3.6, the script does will not download until the element is attached to the DOM. Can't be bothered to check other browsers.

    After reading the responses to my excerpt, I have modified it to take a more robust and enterprise best practices approach to dynamic Javascript insertions. Hopefully this will address all of your concerns. Behold:

    <script type="text/javascript">//<![CDATA[
    	(function(){
    		var script = document.createElement('script');
    		script.type = 'text/javascript';
    		script.textContent =
    			'//alert(\'Calling document.write...\');\n' +
    			'document.write("'+
    				'<script language=\'JavaScript\'><!--\\n'+
    				'	alert(\'Hello, world.\');\\n' +
    				'--></'+'script>");\n' +
    			'//alert(\'...document.write called.\');';
    		(function(){
    			var bodies = document.getElementsByTagName('body');
    			if (bodies)
    				return bodies[0];
    			else
    				return document.documentElement;
    		})().appendChild(script);
    	})();
    	//alert('Done');
    //]]></script>
    

    Doesn't Firefox use "innerText" or something instead of "textContent"?



  • @Xyro said:

    In Firefox 3.6, the script does will not download until the element is attached to the DOM. Can't be bothered to check other browsers.

    After reading the responses to my excerpt, I have modified it to take a more robust and enterprise best practices approach to dynamic Javascript insertions. Hopefully this will address all of your concerns. Behold:

     

    Well, almost. But to be really, really sure, you should attach your outermost script to the onload event instead of firing it directly. After all, executing script before the document has finished loading is bad practice, especially if document.write is called somewhere. I've taken the liberty to modify your script so you can reuse it in all web pages you design from now on:

    <script type="text/javascript">//<![CDATA[
    window.onload = function(){
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.textContent =
    '//alert(\'Calling document.write...\');\n' +
    'document.write("'+
    '<script language=\'JavaScript\'><!--\\n'+
    ' alert(\'Hello, world.\');\\n' +
    '--></'+'script>");\n' +
    '//alert(\'...document.write called.\');';
    (function(){
    var bodies = document.getElementsByTagName('body');
    if (bodies)
    return bodies[0];
    else
    return document.documentElement;
    })().appendChild(script);
    };
    //alert('Done');
    //]]></script>

     



  • <script type="text/javascript">//<![CDATA[

    	$(document).ready(function(){
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.textContent =
    '//alert('Calling document.write...');\n' +
    'document.write("'+
    '<script language='JavaScript'><!--\n'+
    ' alert('Hello, world.');\n' +
    '--></'+'script>");\n' +
    '//alert('...document.write called.');';
    (function(){
    var bodies = document.getElementsByTagName('body');
    if (bodies)
    return bodies[0];
    else
    return document.documentElement;
    })().appendChild(script);
    });
    //alert('Done');
    //]]></script>

     


    I've ported it to jQuery.



  • @dhromed said:

    I've ported it to jQuery.
    Here, I've turned it into a first-class jQuery plugin:

    <script type="text/javascript">//<![CDATA[
    window.onload = jQuery(function($){
    $.fn.writeScript = function(content) {
    var $this = $(this);
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.textContent =
    '//alert('Calling document.write...');\n' +
    'document.write("'+
    '<script language='JavaScript'><!--\n'+
    content.replace("&quot;", "\&quot;", 'g') +
    '"+\n"\n--></'+'script>");\n' +
    '//alert('...document.write called.');';
    var node = (function(){
    if ($this && $this[0]) {
    return $this[0];
    }
    var bodies = document.getElementsByTagName('body');
    if (bodies && bodies[0])
    return bodies[0];
    else
    return document.documentElement;
    })();
    node.appendChild(script);

    		return $(node);
    	};
    });
    
    jQuery(function($){
    	// Usage example:
    	$('body').append('&lt;div id=&quot;write&quot;&gt;').children('#write').writeScript(
    		'document.write(&quot;Goodbye, DOM!&quot;)'
    	);
    });
    

    //]]></script>



  • @Xyro said:

    @PSWorx said:
    What I meant was including bits of HTML, not script.
    Oh, yes, that would be pretty useful. I wouldn't be surprised if the decision makers are under the impression that no one serves webpages from anything other than a behemothly enterprisey pre-processing xml-crushing application server.
    Say, didn't the late XHTML 2 spec have something or other like an include? I recall talk of being able to smoosh src attributes into anything.

    Dunno about XHTML2, but [url=http://www.w3.org/TR/xinclude/]XInclude[/url] is a generic inclusion mechanism for XML, which could have easily been adapted into XHTML5 (but AFAIK, wasn't).



  • @Spectre said:

    Dunno about XHTML2, but XInclude is a generic inclusion mechanism for XML, which could have easily been adapted into XHTML5 (but AFAIK, wasn't).
     

    Nope, it couldn't, because in HTML5, XML and generic solutions are seen as antipatterns that are to be purged as quickly as possible. And XInclude contains far too much of both to be even considered.

    Incidentally, SGML, which technically every HTML version <= 4 is still an instance of does have an include mechanism - apparently that's the original purpose of entity references. Not that any browser had ever implemented that stuff though...



  • @joe.edwards said:

    document.write is on my shit list along with eval, and passing strings into setTimeout/setInterval/the Function constructor. I have yet to find one example* using any of them that couldn't be better accomplished with either DOM methods or closures and currying.

    *I have yet to encounter one; I concede such an example may exist.

    Here's that existing example for the Function constructor:

    For my employer's toolbox I built a really nice jQuery UI widget that wraps SWFObject and offers fancy stuff like scraping configuration for SWFObject from HTML5 data-* attributes or JSON embedded in script islands. I also included functionality to support the Flash ExternalInterface (where you can marshall function calls to and from ActionScript in the SWF). The AS->JS side works nicely with injecting the marshalled function calls as custom DOM events triggered by jQuery. The JS->AS side? Ehh... not so nice:

    The desired API here is:

    $("#mySWF").swf("marshall", "<functionname>", <arg0>, <arg1>, ...)

    You'd think that getting a variable number of arguments to work would be as simple as using Function.call or Function.apply, but in this case that will fail for IE browsers: the functions are available on the object tag hosting the SWF file, but in IE they're some weird hybrid of native JS and host browser functions, which completely crap out on Function.call and Function.apply.

    So, for each arguments.length used with each function name, you need to eval a function into existence (and ofcourse cache it for re-use) that directly calls these weird kind of functions on the object tag. For bonus points: you can't directly eval an anonymous function into existence in IE and assign it to a variable. Instead you have to resort to the more exotic method of using the Function constructor.

    Moral of the story? The real WTF is IE, ActiveX and Flash. (And not necessarily in the order described.)



  • @Ragnax said:

    Moral of the story?

    Switch to Silverlight.


Log in to reply