2

This is probably very basic but I'm stalling ...

On page load, I need to save the html content of my element into a variable. I have other code in the page that will change the html content of the element. So I need to be able to revert the value back to it's default (what it was on page load). The issue is that my variable's value is being changed to most recent value.

How can I make the initial value I assign to the variable "stick"?

currentElementsHTML = $("#myDOMElement"),
currentElementsHTMLDefaultValue = currentElementsHTML.html()
... do stuff that changes currentElementsHTML 
... revert to currentElementsHTMLDefaultValue whenever i need to
IntricatePixels
  • 1,219
  • 6
  • 29
  • 55
  • 1
    ... and the problem is exactly what, may I ask? `html()` call will give you a string; unless you alter that variable, you'll still have the original content within. – raina77ow Oct 23 '12 at 23:20
  • need more code to confirm that you aren't doing something wrong by accident. – nickaknudson Oct 23 '12 at 23:29

4 Answers4

4

There are many ways you can store some data and make it available later, some of these require a knowledge of the way JavaScript's scope works - others just rely on jQuery methods.

the first things that come to mind

global variable

The bad way to do this would be to store the value as a global var:

function at_the_start(){
   /// notice there is no var keyword, this means the variable will be global
   global_html = $('element').html();
}

function later_on(){
   $('element').html( global_html );
}

You shouldn't do this because your data will "pollute the global namespace" - which basically means that other code will easily be able to access your variable (and mess around with it) and that you could inadvertantly overwrite some other code's global data - especially if you use a rather general variable name.

local variable kept in scope

A better way to do this would be to use the power of JavaScript for your own ends, namely its scope abilities, there are some good points to read here -- What is the scope of variables in JavaScript?:

function my_code(){

  var html = $('element').html();

  /* Do stuff here */

  $('element').html( html );

}

The above relies on a local variable and the fact that you must keep everything in the same function call. As it is most likely you will be relying on a mixture of user triggered events, you can't really use the above. This is because you will have many functions used in different locations and they can't all share the same local variable. Or can they?

The following is what I call a "global local" variable - completely most likely not its real name, but it describes things as I see them:

function my_code(){

  /// this variable is local, due to the var keyword
  /// but it will be accessible in both the functions below
  var html_local = '';

  var my_function_to_start = function(){
    html_local = $('element').html();
  }

  var after_other_things_have_happened = function(){
    $('element').html( html_local );
  }

  /// you can even apply these functions to say an event handler
  /// and the variable will be remembered because it exists within
  /// the "after_other_things_have_happened" function's scope.
  $('another.element').click(after_other_things_have_happened);

}

The above works because JavaScript functions can always access variables defined in previous parent blocks / parent scopes or parent functions.

jQuery data

Considering you are using jQuery, jQuery offers a very simple method for storing arbitrary data and you don't need to know anything about scope or local and global vars. It's taken me a while to write this and so obviously by this time other posters have correctly stated that the following is a good idea - jQuery Data:

$('element').data( 'old_html', $('element').html() );

This can then be accessed any time after by using:

$('element').data( 'old_html' );

So...

$('element').html( $('element').data( 'old_html' ) );

Will put the value back - this is stored along with the element so whereever you can access $('element') you'll be able to get at the data assigned to it.


Some other less relevant ways (but still methods of data storage)

storing as a property of an object

Another useful ability sometimes, is that JavaScript treats nearly every datatype as an object. This means you can add properties to nearly anything. The following is actually quite possible if a little odd.

var a = new String('This is a string');
    a.withAProperty = 'another string';

alert(a);
alert(a.withAProperty);

I occasionally use this to create pseudo static properties on functions, like so:

var my_function = function(){
  if ( ! my_function.staticProp ) {
    my_function.staticProp = 'abc';
  }
  /* use my_function.staticProp for something here */
}

var another_function(){
  /* you can also access my_function.staticProp here
     but only after my_function has been called once */
}

/* and my_function.staticProp here, but only 
   after my_function has been called once  */

This almost has the same affect of using a global var (especially if you apply it to global functions) but means your value is stored on top of your functions namespace, cutting down the possibility of collisions with other code quite drastically. It does still mean outside code can influence the content of your var -- which can actually be a benefit depending on what you want to do.

storing content in the dom

Depending on what you wish to store, it can sometimes be of benefit to record that data in the DOM. The most obvious of these would be to write the data into a hidden input or hidden element. The benefit of the latter is that you can still navigate this data (using the likes of jQuery or document.getElementById) if it happens to take the form of markup information (as yours does). This can also be beneficial way of avoiding memory leaks caused by circular references - if you are dealing with large amounts of data - as long as you make sure to empty your variables involved in the transporting of the data.

$.ajax('request_html.php').done(function(data){
  $('<div id="hidden_html" />').hide().html(data).appendTo('body');
  data = null;
  /// you only need mullify data if you were to have other
  /// sub/child functions within this callback, mainly being wary
  /// of closures - which are functions that are defined in a certain
  /// scope chain, but are then returned or put to use outside of
  /// that chain - i.e. like event listeners. 
  /// nullify vars and removing large properties is still good practice though.
});

Then when you want to retrieve:

$('#hidden_html').html();

And in the meantime between those two points you can obviously still traverse the data:

$('#hidden_html h1 > a[name=first]');
Pebbl
  • 34,937
  • 6
  • 62
  • 64
  • thanks for this great response, i'm sure a lot of people will find the detailed explanation useful! – IntricatePixels Oct 24 '12 at 02:23
  • actually maybe i'm missing something simple here, but when i use the jquery .data() my 'old_html' gets reset to the new .html() value – IntricatePixels Oct 24 '12 at 03:45
  • I change the value of $('element').html() so 'old_html' value gets update to that. i want the very first value stored on document ready to be retrieved at any time. so if i stored apple, i want to retrieve apple and not orange (which was injected later to 'old_html' via $('element').html())) – IntricatePixels Oct 24 '12 at 04:00
  • No worries at all, it's best to treat each answer as if it will be read by future peopel too :) Hmm, can you post your code to see what is going on..? What you describe should not be the case. – Pebbl Oct 24 '12 at 06:42
  • Exactly the kind of answers I'm looking for. For my case, I'm interested in keeping any initially-loaded-static-page in the DOM, regardless of view changes, so that my SPA doesn't re-query for it off the server. For example, a welcome or home page that rarely changes for months. For the time being, I'll just make exceptions for those cases before any DOM view change. When a route gets called, it'll check if the existing div matches any exception, and it will just hide that particular div (display: none) so it's ready for use in the SPA if the user navigates to it again. – Kalnode Dec 13 '17 at 22:36
  • @MarsAndBack you could also look towards the [localStorage API](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) for storing cached rendered low-frequency-change content, this has the added benefit of being findable as soon as your page starts rendering (before DOM is fully rendered). – Pebbl Dec 14 '17 at 14:06
1

You associate the original HTML with the same DOM element, that way it won't disappear:

$("#myDOMElement").data("initial-html", $("#myDomElement").html());
zmbq
  • 38,013
  • 14
  • 101
  • 171
1

something like that, but not tested yet:

$(function() {

  $('#id').data('store', $('#id').html());

});

...

$('#id').html(data('store'));
Reflective
  • 3,854
  • 1
  • 13
  • 25
0

Set it and forget it.

If you push the contents of .html() into a variable, it will stay there unless you do something with that variable to remove it:

var original = $("#foo").html(); // original HTML is now in 'origina'

This won't change unless you change it.

Storing data on the element with $.data()

It might be more advantageous for you to store it as data (using jQuery's .data method) on the element itself though:

var element = $("#foo");
element.data( "original", element.html() );

This way you can always access it at a later time:

console.log( element.data( "original" ) );

Record, Reset, and Restore Demo: http://jsfiddle.net/ft8M9/

Works on many items too

// Access all elements to restore
var restore = $(".restore");

// Save original HTML, and set new HTML
restore.each(function(i,o){
    var that = $(this);
    that.data("original", that.html())
        .html("Changed " + i);
});

// After 2 seconds, restore original HTML, remove stored data
setTimeout(function(){
    restore.each(function(i,o){
        var that = $(this);
        that.html( that.data("original") )
            .removeData( "original" );
    });
}, 2000);

Demo: http://jsfiddle.net/ft8M9/1/

Community
  • 1
  • 1
Sampson
  • 265,109
  • 74
  • 539
  • 565
  • I really wonder how this 'data' approach is more efficient than using just a JS variable. ) – raina77ow Oct 23 '12 at 23:22
  • 2
    @raina77ow You don't have to manage another variable out in the wild. If you have 10 elements you need to store original HTML on, it doesn't make sense to continue adding global variables for each one; instead, just store the data on the element itself. – Sampson Oct 23 '12 at 23:23
  • With 10 elements - definitely. But I've asked about the single element case (as described in the question). BTW, now I wonder how data is stored in MVVM frameworks; ain't it properties of Models, not `data-something` in DOM elements? – raina77ow Oct 23 '12 at 23:24
  • Because the item keeps its data - this value is property of the item so the best place to keep it is the item! – Reflective Oct 23 '12 at 23:24
  • @raina77ow The data belongs to this item, therefore it makes sense to keep it associated with the item. Secondly, it's generally wise to take an approach that will scale easily. – Sampson Oct 23 '12 at 23:25
  • 1
    @raina77ow you should also think about the reason why this `data` model for stroing data is made for. This is made actually to enable an DOM item to have user defined properties. – Reflective Oct 23 '12 at 23:29