27

I am creating a simple ajax call that retrieves the content of a specified url and writes it to the page. The problem I am having is that it replaces the entire body contents with this information

here is the JS:

(function(){
    var mb = window.mb = {};

    function get_ad(url, parameters){
        var result = "";
        var http_request = false;

        if (window.XMLHttpRequest) { // Mozilla, Safari,...
            http_request = new XMLHttpRequest();
            if (http_request.overrideMimeType) {
                http_request.overrideMimeType('text/html');
            }
        } else if (window.ActiveXObject) { // IE
            var avers = ["Microsoft.XmlHttp", "MSXML2.XmlHttp", "MSXML2.XmlHttp.3.0", "MSXML2.XmlHttp.4.0", "MSXML2.XmlHttp.5.0"];
            for (var i = avers.length -1; i >= 0; i--) {
                try {
                    http_request = new ActiveXObject(avers[i]);
                    if (http_request){
                        break;  
                    }
                } catch(e) {}
            }
        }
        if (!http_request) {
            alert('Cannot create XMLHTTP instance');
            return false;
        }

        http_request.onreadystatechange = function(){
                                              if (http_request.readyState == 4) {
                                                 if (http_request.status == 200) {
                                                    gen_output(http_request.responseText);
                                                 } else {
                                                    alert('Error');
                                                 }
                                              }
                                           }

        http_request.open('GET', url + parameters, true);
        http_request.send(null);
    }

    function gen_output(ad_content){
        document.write("<div id=\"mb_ad\">");
        document.write(ad_content);
        document.write("</div>");
    }

    get_ad("http://localhost/test/test.html", "");
})();

and here is the html:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>

<body>
    i am text before <br/>
    <script type="text/javascript" src="mb.js"></script>
    <br />
    i am text after 
</body>
</html>

using firebug to inspect, i do not see the text before or the text after, just the <div id="mb_ad"> and the content from the test.html page. If i remove the ajax call and just do 3 document.writes the text before and the text after will display properly. jQuery is not an option, I have to do this without the help of a large library as size and speed are of the essence.

Russ Bradberry
  • 10,705
  • 17
  • 69
  • 85
  • 2
    I can't find what might be wrong with your code, I guess it need more inspection/break point. but for the "jQuery is not an option", I really don't agree, 24ko of javascript (which is probably cached if using google CDN) is really not making a difference on a webpage. If you have that strong requirement I'm not sure a website or even a network application is a good idea. – Mathieu Mar 02 '10 at 00:19
  • moreover, you could use lightweight library such as DOMAssistant or similar. – dusoft Mar 02 '10 at 00:21
  • it has to do with the fact that this script will be inserted into other websites, so to add a library like jquery to a website that is probably using other libraries, or maybe even jquery itself, will just cause problems. – Russ Bradberry Mar 02 '10 at 00:24
  • 2
    @downvoter care to comment as to why you downvoted a 5 year old question? – Russ Bradberry Jun 04 '15 at 19:21

7 Answers7

47

You can't use document.write once the document has completed loading. If you do, the browser will open a new document that replaces the current.

Use the innerHTML property to put HTML code inside an element:

function gen_output(ad_content){
  document.getElementById('mb_ad').innerHTML = ad_content;
}

Put the element before the script, so that you are sure that it exists when the callback function is called:

i am text before
<div id="mb_ad"></div>
i am text after
<script type="text/javascript" src="mb.js"></script>

It doesn't matter much where you place the script, as nothing will be written to the document where it is.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • is it at all possible to accomplish what i am trying without a separate `div`? This is supposed to be something that is embedded into a clients site, and I was asked to do it with a single script call. – Russ Bradberry Mar 02 '10 at 00:17
  • Yes, you could use document.write to write the div to the page before making the AJAX call. – Guffa Mar 02 '10 at 00:19
14

in case you cant control the remote script you might be able to write something like so:

<script>
var tmp = document.write;

document.write = function () {
  document.getElementById('someId').innerHTML = [].concat.apply([], arguments).join('');
};
</script>
<script .....>
document.write = tmp;

Well it is a nasty hack but it seems to work...

Tivie
  • 18,864
  • 5
  • 58
  • 77
Leon Fedotov
  • 7,421
  • 5
  • 30
  • 33
2
var div = document.createElement('div');
div.id = 'mb_ad';
div.innerHTML = ad_content;

Now, you can append this node wherever you want it to be.

N 1.1
  • 12,418
  • 6
  • 43
  • 61
0

you can use <script>document.body.innerHTML+="//Your HTML Code Here";</script>

raven myers
  • 585
  • 1
  • 6
  • 5
0

Same Leon Fedotov answer but more jQuery

{
  var old_write = document.write;

  var $zone = $('.zone.zone_' + name);
  // redefine document.write in this closure
  document.write = function () {
    $zone.append([].concat.apply([], arguments).join(''));
  };
  // OA_output[name] contains dangerous document.write
  $zone.html(OA_output[name]);

  document.write = old_write;
}
Aivils Štoss
  • 858
  • 11
  • 9
0

I had the same problem with the following code :

$html[] = '<script>
           if($("#mf_dialogs").length == 0) {
               document.write("<div id=\"mf_dialogs\"></div>");
           }
           </script>';

The following code replaces document.write efficiently :

$html = '<div id="dialogHolder"></div>
         <script>
              if($("#mf_dialogs").length == 0) {
                  document.getElementById("dialogHolder").innerHTML="<div id=\"mf_dialogs\"></div>";
              }
         </script>';
kundun
  • 1
0

The way you can emulate document.write somewhat is the following code:

<script>
  (function(script) {
    var parent = script.parentNode;
    var node = document.createTextNode('Surprise!');
    parent.replaceChild(node, script);
  })(document.currentScript);
</script>

This way you can put arbitrary HTML in place of a script element. If you have a simpler case, like you can wrap a script in another tag, you can do even simpler version.

<script>
  document.currentScript.parentElement.innerHTML = 'Surprise!';
</script>
Alexander Solovyov
  • 1,526
  • 1
  • 13
  • 21