3

I've been wondering if there is a way to prevent my functions hiding any current text/formatting.

<body>
<script type="text/javascript">
document.body.style.backgroundColor = "#F5F0EB";
var page = 0
function flip(){
document.write(page);
page++;
}
</script>
<input type=button value="Next" onClick="flip()">
</body>

When I press the button I lose the coloured background and the text appears. Is there a way to make the background stay and the text appear?

user2036239
  • 31
  • 1
  • 3

4 Answers4

3

Yes, by not using document.write(). MDN explains it clearly:

Writing to a document that has already loaded without calling document.open() will automatically perform a document.open call.

And about document.open() it says:

If a document exists in the target, this method clears it.

What you should be doing, is manipulate nodes in the DOM. For example, you could change the inner HTML of the body:

document.body.innerHTML += page;

Alternatively, you could create a text node and append it:

var textNode = document.createTextNode(page);
document.body.appendChild(textNode);

In both cases, the current document is not flushed, it is only modified.

Mattias Buelens
  • 19,609
  • 4
  • 45
  • 51
1

This is happening because you're writing non-html to a document which should be html. As indicated by others, it may also be clearing your existing html. Instead of using document.write, you may want to append new elements to your document.

You can do that using the document.createElement function and document.appendChild function.

Here's what a quick Google search brought back:

http://www.dustindiaz.com/add-and-remove-html-elements-dynamically-with-javascript/

cwharris
  • 17,835
  • 4
  • 44
  • 64
0

You are writing the page to document which is overwriting all over your HTML. Instead, write out the content to a DIV.

This should fix your background color problem as well.

Here is a JS Fiddle with an example.

<script type="text/javascript">
document.body.style.backgroundColor = "#F5F0EB";
var page = 0
function flip(){
document.getElementById("contentgoeshere").innerHTML=page;
page++;
}
</script>
<input type=button value="Next" onClick="flip()">
<div id="contentgoeshere">
</div>

Good luck.

sgeddes
  • 62,311
  • 6
  • 61
  • 83
0

As Mattias Buelens explained, document.write calls the open method, which clears the DOM, simply because -after loading- the document.close method is called automatically. There are a number of alternatives you can use, of course.
Use the innerHTML attribute of the body element, for example.
Using document.createElement and document.body.appendChild is an option, too

But perhaps it's worth taking into consideration that both methods have their downsides: using innerHTML allows you to inject badly formatted markup into the DOM, and could leave you vulnerable to XSS attacks.
Using document.createElement is slower (generally) and often requires more code, which in turn makes your script(s) less maintainable.

You could use something like this:

var flip = (function(tempDiv)
{//create a div once
    var page = 0,
    targetDiv = document.getElementById('contentgoeshere');//closure variables
    //page is now no longer an evil global, and the target element into which
    //we will inject new data is referenced, so we don't have to scan the DOM
    //on each function call
    return function(overridePage)//optional argument, just in case
    {//actual flip function is returned here
        overridePage = overridePage || page++;//new content
        tempDiv.innerHTML = overridePage;//render in div that isn't part of the DOM
        //any number of checks can go here, like:
        if (tempDiv.getElementsByTagName('script').length > 0)
        {
            alert('Naughty client, trying to inject your own scripts to my site');
            return;
        }
        targetDiv.innerHTML = tempDiv.innerHTML;
        //or, depending on your needs:
        targetDiv.innerHTML = tempDiv.innerText;//or the other way 'round
    };
}(document.createElement('div')));

A couple of side-notes: as it now stands, this function won't work because the DOM has to be fully loaded for the closure to work. A quick fix would be this:

var flip;//undefined
window.onload = function()
{
    flip = (function(tempDiv)
    {
        var page = 0,
        targetDiv = document.getElementById('contentgoeshere');
        return function(e)
        {
            tempDiv.innerHTML = e instanceof Event ? page++ : (e || page++);//ternary + logical or
            //your [optional] checks here
            targetDiv.innerHTML = tempDiv.innerHTML;
            if (e instanceof Event)
            {//this part is optional, but look it up if you want to: it's good stuff
                e.returnValue = false;
                e.cancelBubble = true;
                if (e.preventDefault)
                {
                    e.preventDefault();
                    e.stopPropagation();
                }
            }
            return e;
        };
    }(document.createElement('div')));
    //instead of using the HTML onclick attribute:
    document.getElementById('buttonID').onclick = flip;//use as event handler
};

Note that window.onload causes memory leaks on IE<9, check this link for the solution to this issue

Community
  • 1
  • 1
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149