This is a very basic question but I am not sure how to research it. Let's say I have an html file with an input field and a javascript file that contains a function to grab the values entered in the the input:
HTML:
<input type='text' id='value' onclick='getValue()'>
JS File:
var val;
function getValue(){
val = document.getElementById('value').value;
console.log(val)
}
When a user inputs a value, that value is stored in the DOM. I then grab the value from the DOM and store it in my script file loaded in the browser.
Since this is stored within my script file now. If I were to reload the page, all the values stored would be reset to their original files.
Is it accurate to say the value taken from the DOM is stored in my loaded javascript file? Or is that stored someplace else?
Th input value gets stored in the DOM tree (if you want to know where exactly: see the code, e.g.: of Chrome and Firefox). Th JavaScript code you posted makes a copy of that value. The copy is independent of the value stored in the DOM tree, you can delete the input-element and will still have the copy in JavaScript. So the answer is threefold:
the value is in the DOM-tree first
a copy of the input value is in the JavaScript Stack when you copy it and in the DOM-tree; at least I know of no one-step way to move it.
if you delete the DOM element the copy you made in JavaScript stays in JavaScript
That makes it possible for example to run JavaScript and DOM-parsing with two distinct programs. Chrome does it with their V8-machine which you can put into some thin wrap and run it separately. You may call the result "node" if you want.
Saying that it's stored "in [your] script file" is a little misleading, but technically accurate.
Any data for DOM elements is stored within the browser's memory for that tab, which it manages itself. Since your Javascript is just a part of that memory, it is in some way stored there. The actual fiddly bits of how that all works is hidden within the browser, and is probably different between browsers.
Related
I want to restore an ajax entire modified page along with the javascript variables in memory when the browser back button is pressed. It was added to the brwoser history manually using window.history.pushState(). I'm trying to save/restore the page using :
function changeURL(){
window.history.pushState(document.body.innerHTML,"","...");
}
window.onpopstate = function(e){
if(e.state){
document.body.innerHTML = e.state;
}
};
Seemingly this works but just a problem that the javascript variables that were in memory at the time page was loaded are no longer there as they are modified by subsequent ajax requests but I didn't made any provision to restore them on pressing back button. How can I restore all those values to the variables ?
Write a function that will serialize all of the variables you want to track into some easy to manage format (I'd suggest JSON).
Write a second function that can accept the serialized data and parse/deserialize it, restoring variables as it goes (this will be a mirror image of your first function).
Find some reasonable place to store your serialized state so that it is preserved across page loads. Personally I've used cookies for this in the past, though you can also use localStorage or any other mechanism you prefer.
Add code to your page to store/update the serialized state either every time the state changes, or at least at some point right before the user leaves the page.
Add code to your page to check for stored/serialized state when the page loads, and load it if it exists.
Edit: I'd also recommend not treating the entirety of document.body.innerHTML as your serialized "state". It should be possible to isolate the variables that you are using to modify the HTML content, and use that as your state. Then you can just regenerate the corresponding HTML by re-applying your variables.
I would like to be able to save the state of the html page after I've interacted with it.
Say I click a checkbox, or the javascript set the values of various elements.
How can I save the "javascript-rendered" page?
Thanks.
In Chrome (and apparently Firefox), there is a special copy() method that will copy the rendered content to the clipboard. Then you can do whatever you want by pasting it to your preferred text editor.
https://developers.google.com/chrome-developer-tools/docs/commandline-api#copyobject
Console Example:
copy(document.body.innerHTML);
Note: I noticed Chrome reports undefined after the method is run, however, it seems to execute correctly and the right content is in the clipboard.
That should do and will grab the ALL page not just the body
console.log(document.getElementsByTagName('html')[0].innerHTML);
document.body.innerHTML will get you the HTML representation of the current document body.
That will not necessarily include all internal state of DOM objects because the HTML contains the initial default state of objects, not necessarily the state that they may have been changed to. The only way to guarantee you get all that state is to make a list of what state you want to save and actually programmatically get that state.
To answer the part of your question about saving it, you'll have to describe more about what problem you're really trying to solve.
To get the equivalent of view source with javascript rendered, including doctype and html tags, copy the command into the chrome console:
console.log(new XMLSerializer().serializeToString(document.doctype) + document.getElementsByTagName('html')[0].outerHTML);
In the chrome console, hover at the end of the output and click on the copy link to copy to the pasteboard.
Wondering if anyone out there has ran into this before....
I'd like to use JavaScript to identify a DOM element on a page, then store it's reference in a database or cookie for later retrieval.
To get specific, what I'm looking to do is create a UI so that when the user CLICKs an element on a page, JavaScript fires the click event, passing the instance of the DOM element clicked on.
easy so far, right?
So what I want to do is store the "identity" of this DOM element, say in a database, so when I later return to this page, I can pull out all stored DOM element identities and get access to them in the page once more.
So this is quite simple if this DOM element has a unique ID. Just store the ID, then when the page comes back up, we just do a getElementByID and we've got our DOM element again.
The problem is that not everything in the DOM has a unique identifier, so there the problem lies.
I had some bad ideas initially, like iterating through the entire DOM and incrementing them with unique class names (dom-01, dom-02, etc) and this would give me an identifier. But this would cause a lot of initial overhead and if the page ever changed, the order of the DOM elements wouldn't be the same, so we wouldn't get back the correct DOM elemet.
I'mve never tried it, but another thought was to serialize the DOM element, stick it in the DB, and then on reload parse to an object, and use that object to find my original DOM element. I've never done that before, so how I can actually compare the restored (parsed) object to the one in the DOM is a big unknown.
Specifics on the serialization solution or any other original ideas for accomplishing this are welcome!!
Thanks in advance everyone!
Here's a jsFiddle solution attempt: http://jsfiddle.net/techbubble/pJgyu/7720/
The approach I took was to compute a simple hash of the HTML content of the target element, or if no such content is present, a hash of the aggregated attributes and values of the element. I have a getElementHash() function that returns a string in the format: TAG:[H | A]:Hash (the H or A indicates if the HTML content or attributes were used to calculate the hash). This produces a unique key for any element on the page that either has HTML content or has at least one attribute (miniscule risk of duplication possible).
For retrieving an element with a previously saved key, I created a getElementByHash() function. It uses the tag that is extracted from the key in a jQuery selector. For each element returned, the HTML content or attributes hash is computed (based on the value "H" or "A" specified in the key) to see if it matches the hash in the key. If there is a match, the search ends and the element is returned.
This approach is impervious to the element being moved around on the page as long as its HTML content (or attributes) remain unchanged. It does not produce a key for elements that have neither any HTML content nor any attributes (which makes them pretty useless anyway).
If you want to keep the location of the node in the DOM, why not just keep an XPath of it? XPath allows you to keep an exact location of a node in a document, as long as that location doesn't change. For instance, you can say something like
//div[#id="xpath_is"]/span[class="cool"]/a[4]
Meaning the 4th <a> tag within a <span class="cool"> within a <div id="xpath_is">
http://www.w3.org/TR/xpath/
http://www.w3schools.com/xpath/default.asp
You can get the XPath of an attribute by Inspecting it with Firebug and right clicking on the node and selecting "Copy XPath". I'm not sure how easy it is to get it from a DOM Node (there are ways, but not sure how many baked implementations there are lying around). It'd be relatively easy to simply look for an ancestor (by traversing upward with .parentNode and building one) and adding .classNames and .ids as you go - but I'm too lazy to write this right now, ;).
I've got some Javascript code which serializes the entire DOM tree as follows:
(new XMLSerializer()).serializeToString(document)
But what I get is somewhat different than I'd expect. Specifically, I get the HTML source, but not the values of the various input/selects. If objects are inserted into the DOM, I get those objects, but again, no values.
However, if I were to walk through the DOM in Javascript for some other purpose, I would have access to every input's value.
What gives? Obviously, I'm missing some very basic concept, but I've no idea what.
Can I get the full DOM as an HTML/XML formatted string, with input/select values? If so, how?
This is due to the fact that a DOM form input maintains its value property (which reflects the current state) separately from its value attribute (which represents the initial value of the input and is used by XMLSerializer to serialize the DOM).
I've written about this several times on Stack Overflow. Here's a recent example: jQuery .attr('value', 'new_value') not working?
Knowing that my document.activeElement is an input field (I don't know exactly the name of the component, but may be the Google's search input field, for example), how can I set a text on it programmatically?
--update
I'm trying it from a xul application, via javascript after the page is loaded. A paste command works fine, so I know the field have the focus. (and I didn't put the Xul tag becouse it's just about the javascript)
See the mozilla reference. This is the same type as document.getElementById()
document.activeElement.value = 'new value';
If you are sure it is a input text field, just set the value:
document.activeElement.value = 'value'
Without seeing your code and the context it is running in, I can only speculate. However, my guess is that you are calling document.activeElement from your XUL app, which means document is the chrome document, not the content page. In this case, the active element is likely to be the browser or iframe element you are using to display the content.
I think there's a little more trouble because I'm in a Xul app. Javascript was supposed to work like in the browsers, but it didn't.
What I did to make it work was (after put the content in the clipboard):
controller.doCommand('cmd_selectAll');
controller.doCommand('cmd_paste');
If you want the focused element wherever it may be relative to the given application window, e.g. it may be inside a <browser> element, use document.commandDispatcher.focusedElement.value which is the same as document.commandDispatcher.focusedWindow.document.activeElement.value. This gives you the element that cmd_paste operates on.