Kosmo零
Kosmo零

Reputation: 4151

Why elements after restoration loses their offset between each other?

I am trying to implement bookmarks thing for my site and testing this:

<html>
    <head>
        <title>test bookmark</title>
        <script type='text/javascript' src='libs/bookmarks.js'></script>
    </head>
    <body>
        <input type = "text" id = "txt_id" />
        <input type = "button" value = "create bk" onclick = "createBookmark();" />
        <input type = "button" value = "restore bk 0" onclick = "restoreBookmarkNumber(0);" />
    </body>
</html>

bookmarks.js:

function Bookmark(of_elem, name)
{
    this.name = name;
    this.of_elem = of_elem;    
    this.elems = new Array();

    for (var i = 0; i < of_elem.children.length; i++)
        this.elems.push(of_elem.children[i].cloneNode(true));

    return this;
};

Bookmark.prototype.restore = function ()
{
    while (this.of_elem.hasChildNodes())
        this.of_elem.removeChild(this.of_elem.lastChild);

    for (var i = 0; i < this.elems.length; i++)
        this.of_elem.appendChild(this.elems[i].cloneNode(true));
};

var bookmarks = new Array();

function createBookmark()
{
    var name = prompt("Enter bookmark name", "Bookmark " + bookmarks.length);
    var bk = new Bookmark(document.body, name);
    bookmarks.push(bk);
}

function restoreBookmarkNumber(num)
{
    var bk = bookmarks[num];

    if (bk)
        bk.restore();
}

For some weird reason, the space between textbox and buttons disappears after bookmark restoration, but I don't understand why this happens. I clearly clone all elements, so what else it need?enter image description here

Upvotes: 3

Views: 51

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1075219

In the places you're using children rather than childNodes (such as the Bookmark constructor), you're only dealing with element children (since that's the point of children vs. childNodes). Use childNodes throughout to ensure you maintain text nodes between elements, since text nodes between elements can be significant (e.g., for spacing).

Your original, which loses the spacing:

function Bookmark(of_elem, name)
{
  this.name = name;
  this.of_elem = of_elem;    
  this.elems = new Array();

  for (var i = 0; i < of_elem.children.length; i++)
    this.elems.push(of_elem.children[i].cloneNode(true));

  return this;
};

Bookmark.prototype.restore = function ()
{
  while (this.of_elem.hasChildNodes())
    this.of_elem.removeChild(this.of_elem.lastChild);

  for (var i = 0; i < this.elems.length; i++)
    this.of_elem.appendChild(this.elems[i].cloneNode(true));
};

var bookmarks = new Array();

function createBookmark()
{
  var name = prompt("Enter bookmark name", "Bookmark " + bookmarks.length);
  var bk = new Bookmark(document.body, name);
  bookmarks.push(bk);
}

function restoreBookmarkNumber(num)
{
  var bk = bookmarks[num];

  if (bk)
    bk.restore();
}
<html>
    <head>
        <title>test bookmark</title>
        <script type='text/javascript' src='libs/bookmarks.js'></script>
    </head>
    <body>
        <input type = "text" id = "txt_id" />
        <input type = "button" value = "create bk" onclick = "createBookmark();" />
        <input type = "button" value = "restore bk 0" onclick = "restoreBookmarkNumber(0);" />
    </body>
</html>

Updated to use childNodes instead of children in Bookmark, which doesn't lose the spacing:

function Bookmark(of_elem, name)
{
  this.name = name;
  this.of_elem = of_elem;    
  this.elems = new Array();

  for (var i = 0; i < of_elem.childNodes.length; i++)
    this.elems.push(of_elem.childNodes[i].cloneNode(true));

  return this;
};

Bookmark.prototype.restore = function ()
{
  while (this.of_elem.hasChildNodes())
    this.of_elem.removeChild(this.of_elem.lastChild);

  for (var i = 0; i < this.elems.length; i++)
    this.of_elem.appendChild(this.elems[i].cloneNode(true));
};

var bookmarks = new Array();

function createBookmark()
{
  var name = prompt("Enter bookmark name", "Bookmark " + bookmarks.length);
  var bk = new Bookmark(document.body, name);
  bookmarks.push(bk);
}

function restoreBookmarkNumber(num)
{
  var bk = bookmarks[num];

  if (bk)
    bk.restore();
}
<html>
    <head>
        <title>test bookmark</title>
        <script type='text/javascript' src='libs/bookmarks.js'></script>
    </head>
    <body>
        <input type = "text" id = "txt_id" />
        <input type = "button" value = "create bk" onclick = "createBookmark();" />
        <input type = "button" value = "restore bk 0" onclick = "restoreBookmarkNumber(0);" />
    </body>
</html>

Upvotes: 2

Related Questions