简体   繁体   中英

"undo" a DOM-manipulating function in Javascript

I'm really new to Javascript (but not programming). I have two ready-made functions in my page that work well separately:

  1. One changes the font size in some <p> element.
  2. Another magically breaks the <p> element into lines, and wraps each line (as seen in the current browser display) with a <span> . This way I can highlight the line above which the pointer hovers.

When using the first function to increase the font size (say, click a button), the whole line structure changes and the <span> s are no longer in the right places.

So basically I want my font-size increasing button to first "undo" the action of the second function.

My question is whether I'll have to manually write a function that undoes the line breaking of the paragraph (removes the <span> s), or maybe Javascript has the ability to restore the page to a point before the function was called?

You can not "undo" a function call. What you want to do is strip the HTML tags inside the p tag like this:

pelement.innerHTML = pelement.innerText;

That strips of all the span elements. You can increment the font size and apply your spanify function afterwards.

An important hint by Derija93: This technique does strip of every HTML tag inside the paragraph, not only the span tags.

Another important hint by jwatt1980: innerText is not a 100% cross-browser compatible. See link for further informations: http://www.quirksmode.org/dom/w3c_html.html#t04

There is no built-in way. However you could save the changes to a variable and restore that variable to undo. The following two examples are a bit complex but I'm sure they could work.

Example 1 — Would restore the entire content to the original/page load format:

<script>
var orignalContent;

function setContent(content) {
    document.getElementById('changableContent').innerHTML = content;
}

function getContent() {
    return document.getElementById('changableContent').innerHTML;
}

function resetContent() {
    updateContent(originalContent);
}

window.onload = function() {
    originalContent = getContent();

    document.getElementById('resetButton').onclick = resetContent;
};
</script>

Example 2 — Reset change by change (might run into large variable... you could add a way to limit the undo steps)

<script>
var contentChanges;

function setContent(content, save) {
    if(save !== false) {
        contentChanges.push(content);
    }
    document.getElementById('changableContent').innerHTML = content;
}

function undoChange() {
    setContent(contentChanges.pop(), false);
}

window.onload = function() {
    document.getElementById('undoButton').onclick = undoChange;
};
</script>

You will need to write your own function. One possibility is to store the original state of the text before transformation, such as with a public variable or a hidden element. You can also use the element.getElementsByTagName() to get all spans in an element and reconstruct the text with element.innerHTML .

Something like this may work to "undo" the spans.

var pList = document.getElementsByTagName('p'); //get all p elements
var p, s, sList, text;

for (p = 0; p < pList.length; p++) {
   sList = pList[p].getElementsByTagName('span'); //get all spans within a p
   text = '';

   for (s = 0; s < sList.length; s++) 
      text += sList[s].innerHTML + ' '; //reconstruct the text

   pList[p].innerHTML = text; //update the p back to non-span text
}

If you want to remove only span's with a certain class, you could update the second for loop with something like this

for (s = 0; s < sList.length; s++) {
   if (s.className && s.className != 'classname') {
      text += (sList[s].outerHTML) ? sList[s].outerHTML : '<span class="' + sList[s].className + '">' + sList[s].innerHTML + '</span>';
   } else {
      text += sList[s].innerHTML + ' ';
   }
}

Change your addSpans code to add an extra class to the spans that is only used by addSpans. Create a new function called undoSpans. It uses jquery to get all of your spans by getting all elements of that class. It can then iterate through them, calling .innerHTML() and inserting the results into the parent node and then deleting the span. At this point you can do your font resizing and then re-span.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM