0

I have developed a JS library that renders layouts (similar to layout rendering as in Razor View Engine in ASP.Net MVC). In order to display the final result, I replace the whole document by calling the document.write(...) function. For example:

document.open()
document.write(renderedLayout)
document.close()

I'm using this methods because I need all scripts whether defined by the developer or acquired from an external resource to be run and evaluated right after the content is replaced. That said, replacing the inner HTML of the html node will fail.

The methods I described works in Opera, Chrome, and Firefox but when I try to test it under IE and Edge, it fails and the browser does not showing anything once the write method is called.

My test shows that, all console outputs are received just before write is called and after that everything disappears.

Even though some may suggest that it could be a security measure in IE or Edge which might be solved by changing their configs, I would like to know how I can solve it using pure JavaScript so that my solution could be used in all major browsers.

I have traced and tested my code carefully, and I'm 100% sure the block of code I attached in the question is causing the blocking.

Arnold Zahrneinder
  • 4,788
  • 10
  • 40
  • 76
  • 1
    You're aware calling `document.open()` clears the current document totally, and you're writing on a blank document, everything will be gone, the HTML, the DOM, everything. I'm afraid you've based your library on a feature which is not suitable for the purpose ... – Teemu Nov 01 '18 at 10:25
  • `document.open('text/html');` should work. – Sudhir Ojha Nov 01 '18 at 10:25
  • @Teemu: I need the existing document cleared and recreated. – Arnold Zahrneinder Nov 01 '18 at 10:25
  • But that wipes your library too, including all variables which are not inside of the currently running function. – Teemu Nov 01 '18 at 10:26
  • @SudhirOjha: Tried that before posting the question, it made no difference. – Arnold Zahrneinder Nov 01 '18 at 10:26
  • @Teemu: That would be ok, because that block is the last thing which will be run. It works on all other browsers though. – Arnold Zahrneinder Nov 01 '18 at 10:27
  • Sorry, but I think you decided to try and ride a dead horse here by using document.write in the first place. Even if it (still) works in some browsers, this is everything but a sophisticated or future-proof way to do things. I would _strongly_ recommend that you stop going down this wrong path now, before you run into a problem at some point in the future that simply won’t be fixable at all any more using this kind of architecture. – misorude Nov 01 '18 at 10:39
  • @misorude: What do you recommend? – Arnold Zahrneinder Nov 01 '18 at 10:41
  • @Teemu: You were somehow right. – Arnold Zahrneinder Nov 01 '18 at 10:41
  • 1
    Usually I am = ). – Teemu Nov 01 '18 at 10:54
  • @Teemu: Do you know of a better solution or alternative that suites my scenario? Rendering html within blocks defined in another in client side in a way that if developer defines scripts in the child document such as react or vuejs scripts, when loaded and appended to the parent, they would work as they should. – Arnold Zahrneinder Nov 01 '18 at 10:56
  • https://stackoverflow.com/questions/2592092/executing-script-elements-inserted-with-innerhtml – misorude Nov 01 '18 at 10:58
  • @misorude: in my case that does not work. I mean that by simply injecting the script somewhere in the document it fails running. By script, I'm talking about things written in Vue, React, etc. – Arnold Zahrneinder Nov 01 '18 at 11:02
  • _“By script, I'm talking about things written in Vue, React, etc”_ - well I’d rather question whether a system that tries to mush together components written using totally different frameworks makes that much sense to begin with … – misorude Nov 01 '18 at 11:05
  • @misorude: That is somewhat true, because what I'm doing is rather a general purpose library than something specific targeting a particular system. – Arnold Zahrneinder Nov 01 '18 at 11:08
  • @misorude: I'm making this client side library to get rid of the complexities of thymeleaf, mustache, etc in Spring Boot. That said, you can already figure out that I'm a backend developer. I wanna define a master layout and render other html content within that particular layout meaning that the child can contain anything written in any technology. – Arnold Zahrneinder Nov 01 '18 at 11:11

1 Answers1

1

document.write writes to the document stream, calling document.write on a closed (loaded) document automatically calls document.open, which will clear the document.

removing document.open() and document.close() might help.

Next time when you are confused if your function written works on browser, Open console(use ctrl+i or F12) - In Console place your Javascript code.

Here is the reference for you : https://developer.mozilla.org/en-US/docs/Web/API/Document/write

  • 2
    Note that `document.close();` is essential for some browsers to properly process all of the supplied HTML. Without it, they may "pause" parsing/rendering just before the last tag or text snippet. – Peter B Nov 01 '18 at 10:53
  • all modern browsers does have their engine support garbage collection i.e all the disconnection/reconnection/close is done in x amount of time. Edge is modern browser as well. IE 6 might not have it as it still works highly on DOM only with limited usage of ES6. – Ramakant Singh Nov 02 '18 at 09:41