3

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?

6
  • 4
    JavaScript is just a programming language, so if you want an undo feature you'll need to write one. One possibility is to clone the element and maintain a "pristine" version of it in memory, and then restore from that as needed. Commented Aug 4, 2012 at 22:35
  • To be exact, I think you're talking about the browser's natural ctrl+z functionality. Otherwise, you're likely to get a lot of the @MattGreer comments. Commented Aug 4, 2012 at 22:37
  • Many WYSIWYG editors implement this... I think it's native browser functionality that you can access Commented Aug 4, 2012 at 22:37
  • 2
    @Pekka: You just read the headline, didn´t you? Commented Aug 4, 2012 at 22:38
  • 1
    @fheshwfq: cloneNode is probably what you're looking for. Commented Aug 4, 2012 at 22:50

4 Answers 4

2

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

Sign up to request clarification or add additional context in comments.

4 Comments

To be exact, since the asker is not so familiar with JavaScript yet, this takes the pure textual contents and uses it as the HTML code of the p tag chosen. So also other tags like b or div will be stripped off, not only span. Just to clarify...
Yep, I definately want to keep style elements withing the <p>, even spans. Is there a way to strip only spans with a particular "class"?
innerText is not fully cross-browser: quirksmode.org/dom/w3c_html.html#t04 But there is a hack. See link.
@jwatts1980: Thanks for pointing that out. I did not know that. I will add that to the answer.
1

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>

Comments

0

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.

Comments

0

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 + ' ';
   }
}

4 Comments

This is not capturing the content between the spans
@Amberlamps: text += sList[s].innerHTML
I was talking between content between different spans like so: <div><span></span></div><div><span></span></div> Your function would lose the div tags.
@Amberlamps: Agreed. However the questioner indicated that all lines within the p tags were broken up into spans. Another limitation of this approach is nested spans

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.