title: Replacing a whole webpage with alternative content (HTML + CSS + JS)
body: <p>I am facing a problem that I am sure is pretty common. I found many solutions to this problem, and they all have their pros and cons. I'll post what I found here (which I believe will be useful to others), and I hope you'll point me in the right direction.</p>
  
  <p>Essentially, this is my scenario:</p>
  
  <ol>
  <li>I have a webpage in PHP: <code>http://example.com/page_with_content_a_or_b.php</code>.</li>
  <li>This page returns <code>Content A</code> when no POST parameters are specified, and <code>Content B</code> if there are.</li>
  <li>Assume a user connects to my page typing the previous URL in her browser (a GET request).</li>
  <li>My server returns the page with <code>Content A</code>.</li>
  <li>The user's web browser, via JavaScript, decides to replace <code>Content A</code> with <code>Content B</code>.</li>
  </ol>
  
  <p><strong>The question: How does the JavaScript replace the contents?</strong></p>
  
  <p>Well, as I've said, I've been looking for different solutions, but none seems perfect.</p>
  
  <p>In order to discuss each possible solution, let me introduce you the resulting HTML code of each version:</p>
  
  <p><strong>HTML of Content A</strong></p>
  
  <pre class="lang-html prettyprint-override"><code>&lt;html&gt;
    &lt;head&gt;
       &lt;link rel="stylesheet" type="text/css" href="style_A.css"&gt;
       &lt;script type="text/javascript" src="jquery.min.js"&gt;&lt;/script&gt;
       &lt;script type="text/javascript" src="gallery-animator.js"&gt;&lt;/script&gt;
    &lt;/head&gt;
    &lt;body&gt;
       &lt;div class="gallery"&gt;&lt;!-- images here --&gt;&lt;/div&gt;
       &lt;p&gt;Content A&lt;/p&gt;
       &lt;script type="text/javascript" src="content-b-loader.js"&gt;&lt;/script&gt;
    &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p><strong>HTML of Content B</strong></p>
  
  <pre class="lang-html prettyprint-override"><code>&lt;html&gt;
    &lt;head&gt;
       &lt;link rel="stylesheet" type="text/css" href="style_B.css"&gt;
       &lt;script type="text/javascript" src="jquery.min.js"&gt;&lt;/script&gt;
       &lt;script type="text/javascript" src="gallery-animator.js"&gt;&lt;/script&gt;
    &lt;/head&gt;
    &lt;body&gt;
       &lt;div class="gallery"&gt;&lt;!-- images here --&gt;&lt;/div&gt;
       &lt;p&gt;Content B&lt;/p&gt;
    &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p><strong>Differences between both versions</strong></p>
  
  <p>As you can see, in the example both versions are quite similar, but not identical. In general, these are the differences I might encounter:</p>
  
  <ul>
  <li>All or some or none imported stylesheets may be different.</li>
  <li>All or some or none imported javascripts may be different.</li>
  <li>There might be differences with inline stylesheets and/or javascripts.</li>
  <li>The content is different, but it may differ a little bit only or be completely different.</li>
  <li><code>Content B</code> does not includes the script for loading itself (last script in <code>Content A</code>).</li>
  </ul>
  
  <h1>Possible Solutions</h1>
  
  <h2>Replacing Content with document.open(), document.write(), and document.close()</h2>
  
  <p>The first solution I implemented is the following:</p>
  
  <p><strong>content-b-loader.js (option 1)</strong></p>
  
  <pre class="lang-js prettyprint-override"><code>$(document).ready(function() {
      $.ajax({
          type:  'POST',
          url:   window.location.href,
          data: { load_content_b: 'true' },
          success: function( html ) {
              document.open();
              document.write(html);
              document.close();
          }
      });
  });
  </code></pre>
  
  <p>Apparently, the solution works properly. However, there are situations in which I have problems. In my example, for instance, both contents load a script named <code>gallery-animator.js</code>. Assuming this script is the following:</p>
  
  <p><strong>gallery-animator.js</strong></p>
  
  <pre class="lang-js prettyprint-override"><code>var galleryInterval = setInterval(function() {
     // Fade out current image and fade in the next one
     $("body &gt; div.gallery &gt; img")...
  }, 5000);
  </code></pre>
  
  <p>after executing the script in <code>content-b-loader.js</code> there are two timeouts animating the gallery. As a result, the animation looks like a mess (two images moving at the same time, or not working at all).</p>
  
  <p>It looks like the sequence <code>document.open()</code>, <code>document.write(html)</code>, and <code>document.close()</code> does not stop and replace the original scripts.</p>
  
  <h2>Redirecting with POST data (using a form)</h2>
  
  <p>Another solution is doing a redirection described <a href="https://stackoverflow.com/questions/19036684/jquery-redirect-with-post-data">in this previous question</a>. The solution works like a charm: on the one hand, I load the URL I need to load with the required POST data, which means I'll get <code>Content B</code>, and on the other hand, <code>Content B</code> is loaded in a "new page", which means that the scripts loaded by <code>Content A</code> are no longer there.</p>
  
  <p>The problem here? If I refresh the page with <code>Content B</code>, I get a warning stating that "POST data is about to be resubmitted". This is undesirable, because it looks confusing for the user (I don't want her to know she had been redirected to a new page).</p>
  
  <p>I know there's a solution called <a href="https://stackoverflow.com/questions/21464128/post-redirect-get-solution-just-for-refreshing-the-page">PRG (Post-Redirect-Get)</a> which avoids this particular issue. However, it requires <code>Content B</code> to be accessible using a GET request (using GET params or COOKIES, neither of which I can use).</p>
  
  <h2>Using iframes</h2>
  
  <p>The last solution I've found is also interesting. Basically, it hides (or empties) the body from <code>Content A</code>, adds an <em>iframe</em> in the page, and loads <code>Content B</code> inside it:</p>
  
  <p><strong>content-b-loader.js (option 3)</strong></p>
  
  <pre class="lang-js prettyprint-override"><code>$(document).ready(function() {
      $.ajax({
          type:  'POST',
          url:   window.location.href,
          data: { load_content_b: 'true' },
          success: function( html ) {
              $("body").css('', ''); // Remove all paddings and margins
              $("body").empty();
              $("body")append('&lt;iframe id="content" seamless="seamless"' +
                  'src="anchor.html"&gt;&lt;/iframe&gt;');
              // Initialize vars in anchor.html and call the redirect functions
              document.getElementById('content').contentWindow.url = window.location.href;
              document.getElementById('content').contentWindow.options = {
                  load_content_b: 'true'
              };
              document.getElementById('content').contentWindow.redirect();
          }
      });
  });
  </code></pre>
  
  <p><strong>anchor.html</strong></p>
  
  <p>This page implements the second solution (it uses a POST redirect).</p>
  
  <pre class="lang-html prettyprint-override"><code>&lt;html&gt;
      &lt;head&gt;
          &lt;script type="text/javascript" src="jquery.min.js"&gt;&lt;/script&gt;
          &lt;script type="text/javascript" src="jquery.redirect.min.js"&gt;&lt;/script&gt;
          &lt;script type="text/javascript"&gt;
              var url;
              var options;
              function redirect(){
                  $().redirect(url, options, 'POST');
              }
          &lt;/script&gt;
      &lt;/head&gt;
      &lt;body&gt;&lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>By making the <em>iframe</em> as big as the window view, I can show the alternative content. If the user refreshes the webpage, the page that is refreshed is the "container" page (the one that originally had <code>Content A</code>), so no warnings appear at all.</p>
  
  <p>The problems I am facing with this solution, however, are:</p>
  
  <ul>
  <li>Users can disable iframes. How do I detect whether iframes are enabled or disabled?</li>
  <li>When the user clicks a link in the frame (or submits a form), the "new page" is opened inside the iframe. This is not what I want: I want it to be opened in the main window. How do I do this? I know that there is the <a href="https://stackoverflow.com/questions/1037839/how-to-force-link-from-iframe-to-be-opened-in-the-parent-window"><code>base</code> directive</a> for links... but what about forms? And JavaScript code that performs a redirection?</li>
  <li>Does everything work properly inside iframes? Responsive themes, javascripts, ... As far as I can tell, they do, but I ignore whether users can limit what iframes can do.</li>
  </ul>
  
  <h1>TL;DR - Conclusions</h1>
  
  <p>I have a page <code>http://example.com/page_with_content_a_or_b.php</code>. The page returns <code>Content A</code> when accessed using a GET request, and returns <code>Content B</code> when accessed using POST. When user types the URL, she gets <code>Content A</code>, and <code>Content B</code> is loaded using JavaScript.</p>
  
  <p>All solutions entail problems:</p>
  
  <ul>
  <li>With document.open(), document.write(), document.close(), scripts get messed.</li>
  <li>With POST redirections, refreshing the page popups a warning</li>
  <li>With iframes, they are not always available, and I am somehow "stucked" inside them.</li>
  </ul>
  
  <p><strong>Any ideas? Am I missing something? Is there a preferred way to do what I'm trying to do?</strong></p>
  
  <p>Thank you very much!</p>