45

I have a DIV with a form in it. When users submit the form and it gets successfully submitted, I replace the form with a simple "everything is good now" message:

$("#some_div").html("Yeah all good mate!");

Is there a good way to "reset" the div to its "original state" as per the HTML it has arrived with? I can only think of actually doing something like this:

//before I change the DIV
var originalState = $("#some_div").html();
//manipulate the DIV
//...
//push the state back
$("#some_div").html(originalState);

It doesn't look very elegant - I guess there is a better solution for this, no?

Manuel Allenspach
  • 12,467
  • 14
  • 54
  • 76
abolotnov
  • 4,282
  • 9
  • 56
  • 88
  • 2
    I think what you've shown there is the best way to go about it. Once you set the HTML of an element, it's previous content is destroyed. So you have to store it yourself before you destroy it. – Bernhard Hofmann Apr 05 '11 at 19:55
  • 5
    `html()` rewriting is nonsense. Just use `show()` and `hide()` to toggle the display of the form and message elements. – Šime Vidas Apr 05 '11 at 20:04

10 Answers10

92

I would clone the element, instead of saving the content. Then use replaceWith to restore it:

var divClone = $("#some_div").clone(); // Do this on $(document).ready(function() { ... })

$("#some_div").html("Yeah all good mate!"); // Change the content temporarily

// Use this command if you want to keep divClone as a copy of "#some_div"
$("#some_div").replaceWith(divClone.clone()); // Restore element with a copy of divClone

// Any changes to "#some_div" after this point will affect the value of divClone
$("#some_div").replaceWith(divClone); // Restore element with divClone itself
jbo5112
  • 824
  • 1
  • 11
  • 18
Josiah Ruddell
  • 29,697
  • 8
  • 65
  • 67
21

You can use the data attribute to save the state rather than a variable

$('#some_div').data('old-state', $('#some_div').html());
$('#some_div').html($('#some_div').data('old-state'));
gen_Eric
  • 223,194
  • 41
  • 299
  • 337
Vadim
  • 17,897
  • 4
  • 38
  • 62
5

What you're doing is not optimal. The best solution would be this:

When the form gets successfully submitted, just hide() the FORM element, and show() the message (which is initially hidden). And then, later, just show() the FORM element and hide() the message.

Šime Vidas
  • 182,163
  • 62
  • 281
  • 385
  • Mmmm, how much more beneficial is this? I mean - why is this not optimal - how much is show/hide better? – abolotnov Apr 05 '11 at 20:08
  • 4
    @abolotnov Writing your FORM element into a string will destroy all event handlers that are bound on that form or any of its ancestor elements (like form fields). All other changes that were done programmatically on the form element or any ancestor will be lost too. HTML rewriting is a horrible idea. – Šime Vidas Apr 05 '11 at 20:19
  • @ŠimeVidas what is your thought on using .clone(true, true) which will also clone data and event handlers, and will also do that for all children of the cloned element(as per jQuery API doc)? – Redoman Oct 01 '13 at 21:55
  • @jj_ In what context? – Šime Vidas Oct 01 '13 at 22:18
  • concerning the use case the OP was facing, or as in you example, in case might you want to clone a FORM element. – Redoman Oct 01 '13 at 22:28
  • @jj_ If OP wants to temporarily display a message instead of the FORM element, he can use `.show()` and `.hide()` on those elements. Creating clones for this is senseless. There is no reason do do such an expensive operation in this case. – Šime Vidas Oct 01 '13 at 22:33
  • I know already your point of view on what is the most optimal way to do this. You already stated it. I am just questioning you on wheter, in case OP or I wouldn't want to change the initial approach, the .clone(true,true) method would have worked for the purpose of avoiding the downfalls of writing an element in a string (which you've illustrated: loosing all event handlers and the rest). – Redoman Oct 01 '13 at 22:49
  • @jj_ I did a quick test: http://jsfiddle.net/simevidas/WUU9k/ Results: The bound event handler persists, but the user-entered content in the form fields does not persist. (Enter some text in the second text field and it won't persist). – Šime Vidas Oct 01 '13 at 23:22
  • The main idea though, is extensibility. Using `.clone()` and `.replaceWith()`, you can just instantiate a template DOM node then update the template instances as you need to, instead of statically duplicating different permutations of subnodes and toggling show/hide. – cowbert Aug 29 '17 at 19:25
4

In my opinion best is to use this:

var originalState = $("#some_div").clone();
$("#some_div").replaceWith(originalState.clone());

This way you can repeatedly use this to restore your div to original state while keeping the data in "originalState" intact. Worked for me.

Saurabh
  • 41
  • 2
4

Yeah, the way you have is the way to do it. The DOM does not save the previous states of DIVs, so you need to save that yourself.

gen_Eric
  • 223,194
  • 41
  • 299
  • 337
2

You have basically three options.

  1. Remember your original markup, as you do with your originalState variable above.
  2. Use AJAX to re-request the markup. You can do this easily if you have server side code using the $.ajax() method in jQuery.
  3. Cause the page to reload.
Devin Burke
  • 13,642
  • 12
  • 55
  • 82
2

Somewhat more elegant?

var originalState = $("#some_div").clone();
$("#some_div").replaceWith(originalState);
andrhamm
  • 3,924
  • 4
  • 33
  • 46
0

Making call to empty function in jQuery will do it

$(".div").empty();
Acapulco
  • 3,373
  • 8
  • 38
  • 51
0

This is my very first interaction on this site--I can't comment yet, but this is to @Fleuv's comment on @Josiah Ruddell's answer:

The default parameter for .clone() is "false", which will not clone event listeners. If you make it .clone(true) it clones the event listeners as well. I've tested it (with the rest of his answer) and it works.

w3schools jQuery clone() method

hypo644
  • 3
  • 4
0
var originalState = $("#some_div").clone(true, true);
$("#some_div").replaceWith(originalState.clone(true, true));
Pedram
  • 6,256
  • 10
  • 65
  • 87
  • 5
    May be your answer is correct. but this will consider as LOW QUALITY answer as it's contain only code. Please add some explanation covering how this will resolve an issue. – Hardik Upadhyay Feb 11 '20 at 06:50