How to reset DOM after manipulation? - javascript

My page contains some small wizard which I built using jQuery.
I would like to offer the user to restart/reset the wizard and start it from the beginning level.
There is anyway to do it without refreshing the page?

One way to achieve this would be to clone() the wizard's element tree in its initial state and store it in a global variable or in the document's data:
$(document).data("initialWizard", $("#yourWizard").clone(true));
(Note that passing true to clone() also clones element data and event handlers, which might prove handy in your case.)
Then, when you want to restore the wizard to its original state, you can do:
$(document).data("initialWizard").replaceAll("#yourWizard");

The only way to start over without refreshing the page is for you to manually return the DOM to the state it was in when the page loaded and to restore any javascript state too. You would either have to record/remember the initial state so you could go back to it or keep track of all your incremental changes so you could go back there too.
If you really want to start over, what's wrong with a refresh?

Similar to the above, here's what I ended up doing. I stored the entire jQuery doc contents in a bootup() function (and ran it). The initial contents of the body was stored in an originalDOM variable. Then within I had a playAgain function that would set the contents of the body to that originalDOM, and run the entire jQuery contents again by calling the bootup() function. This would all be triggered by clicking on a button of class ".startover".
bootup();
var bootup = function(){$(document).ready(function(){
var originalDOM=document.body.innerHTML;
//jQuery lines of code here
var playAgain = function(){
$(".startover").click(function(){
document.body.innerHTML = originalDOM;
bootup();
});
};
playAgain();
});};
Hope that helps for anyone looking for something similar, and happy to hear feedback if there's anything I could've improved on!

Related

whole document cloning not working in javascript

I am working on some stuff meanwhile i get into something which i didn't understand core reason behind it.
my idea(good or bad) is to clone a document and add changes to it and then reassign my cloned object into document
var tu=document.clone(true);
getComputedStyles(document)//returns all current css values
tu.getElementsByTagName("body")[0].style.backgroundColor="yellow";//when i print tu and inspect style is visible on body
tu.getElementsByTagName("body")[0].style.width="100px";
getComputedStyles(tu)//returns all empty values.
document=tu;
But every step return without an error but after assigning tu to document my body bgColor is still white.
one more thing why getComputedStyles() are returning empty values?
Finally i got something which might be usefull
var documentClone=document.clone(true);
documentClone.body.style.background="yellow";
documentClone.body.style.background="red";`\\many number of operations`
//after many changes
document.replaceChild(documentClone.documentElement,document.documentElement);
//now you can find all your changes..
window.document is not writeable.

Change Spotfire Document Properties value using javascript

I want to Change the value assigned to a Document Property in spot fire. Lets say i have created a new document property called "Test1" as a string and assign it a value "a". Is there are way to change this value using Javascript every time i load the spotfire dashboard ?
I'm unaware of a way to use JavaScript for this, but you can assign a string document property via custom expression (if it's a List Box) or run an IronPython script each time the value changes. So, you could set the expression to the current date, datetimenow() and then every time it's loaded the IronPython script would fire. However, I don't see why you'd need the property control for this.
I suppose it really depends on what you want the document property to be set to. Is it data from your tables? Output from complex code? These are all things to consider.
1) Create an input type property control using the Document Property you want to change.
2) Edit Html to assign parent element an id say "testInput". And add the script as shown below in the Edit HTML window.
<span id="testInput"><SpotfireControl id="7db34e6c423240f59fc99e6b80fa23ec" /></span>
<script>
$("#testInput input").val("after");
$("#testInput input").focus();
$("#testInput input").blur();
</script>
3) This script will change the document property value to "after" whenever you open a file.
As you comment seemed to suggest, something you can do is write this code in Python and attach the script to an action control, e.i. a Link or a Button. Something simple like: Document.Properties["Test1"] = newValue
or even: Document.Properties[changingProperty] = newValue
allowing the code to be more reusable.
Then you insert Javascript into the Text Area as well to the effect of: $("#VeryLongSpotfireControlID").click();
Which should simulate clicking on action control, which in turn triggers the Python script to update the value. Just be careful not to use this approach when it would result in reloading the text area HTML, as this will re-trigger the Javascript, thus creating an endless loop.
I believe I have found a possible solution/work-around for the issue, entirely based on pure JavaScript (since TIBCO removed jQuery starting from Spotfire X). The solution is to force a simulated Enter Keystroke while focusing the input box to trigger updating the Document Property. (No data function and R needed)
HTML (SpotfireControl Element is an single line input-box for a Doc. Prop.):
<div id="container"><SpotfireControl id="b8534f13dc62416db6d4eaab16030f5e" /></div>
JS (focus and blur might no longer be needed for this solution, but I'm still keeping them just in case):
const inputConfirmationEvent = new KeyboardEvent("keypress", {
    keyCode: 13,
    bubbles: true,
    cancelable: false
});
var elem = document.querySelector("#container input");
elem.value = "stringValue";
elem.blur();
elem.focus();
document.querySelector("#container input").dispatchEvent(inputConfirmationEvent);
Hope it helps someone.
Best,
Aaron

Trouble calling function after Infinite Scroll runs

I am using the Infinite Scroll plugin, for Wordpress, to load new posts on to the page when users scroll to the bottom. The problem is this has been loading duplicate posts, as the sorting changes extremely fast (due to popularity) and posts end up on different pages.
When the plugin grabs the next page, sometimes products that were originally on the FIRST page have been sorted to the SECOND page. So I end up with duplicates.
I was planning on waiting for the script to load the next page content, then loop through all of the post titles and locate the duplicates. Then I would remove the second instance of each post.
I noticed Infinite Scroll has a window in the settings labeled "Run after content is loaded/callback" so I thought I could enter a function in that field to be called.
removeDuplicates();
Then I entered something like this in the footer:
function removeDuplicates(){
var titleList = [];
$('.title').each(function(i, obj) {
/* The titles are in <h1> tags, I cycle through them,
if it's the first time seeing the title I add it to titleList.
If it's already in the array I hide the parent. */
});
});
I keep getting "undefined function" related to the .each, and it seems like it has something to do with scope but I'm not sure what's happening.
Is there an easier way to trigger the function to remove the duplicates? Am I at least on the right track?
Thanks for any insight you can provide!
It seems like jquery isn't loaded. Even if you use a selector that returns no elements, it should still have the .each() method.
Try using vanillaJS instead of jquery.
var titleNodeList = document.querySelectorAll('.title'); // get elements
var titleElArray = Array.prototype.slice(titleNodeList); // convert to array
titleElArray.forEach(function(el){...}); // iterate

Is it possible to make a change with jQuery and then immediately reverse that change?

I have a pretty specific scenario where I would like to select all elements with jQuery, make a CSS change, save the elements, then reverse the change I made.
The Goal
I created a jQuery plugin called jQuery.sendFeedback. This plugin allows the user to highlight areas of the screen, as shown in this demo. When they submit their feedback the plugin grabs all the HTML on the page and dumps it into a callback function. Like so:
$('*').each(function ()
{
$(this).width($(this).width());
$(this).height($(this).height());
});
var feedbackInformation = {
subject: $feedbackSubject.val(),
details: $feedbackDetails.val(),
html: '<html>' + $('html').html() + '</html>'
};
if (settings.feedbackSent)
settings.feedbackSent(feedbackInformation);
The callback function accepts this feedback information and makes an AJAX call to store the page HTML on the server (this HTML includes the red box highlights the user drew on the screen). When someone from tech support needs to view the user's "screen shot" they navigate to a page that serves up the stored HTML so the developer can see where the user drew their highlights on the screen.
My original problem was that different screen resolutions made the elements different sizes and the red highlights would highlight the wrong areas as the screen changed. This was fixed pretty easily by selecting all elements on the page and manually setting their height and width to their current height and width when the user takes the snap shot. This makes all the element sizes static, which is perfect.
$('*').each(function ()
{
$(this).width($(this).width());
$(this).height($(this).height());
});
The Problem
The issue with this is that when the plugin is done transmitting this HTML the page currently being viewed now has static heights and widths on every element. This prevents dropdown menus and some other things from operating as they should. I cannot think of an easy way to reverse the change I made to the DOM without refreshing the page (which may very well end up being my only option). I'd prefer not to refresh the page.
Attempted Solution
What I need is a way to manipulate the HTML that I'm sending to the server, but not the DOM. I tried to change the above code to pull out the HTML first, then do the operation on the string containing the HTML (thus not affecting the DOM), but I'm not quite sure what I'm doing here.
var html = '<html>' + $('html').html() + '</html>';
$('*', html).each(function ()
{
$(this).width($(this).width());
$(this).height($(this).height());
});
This did not work. So either I need to be able to manipulate the string of HTML or I need to be able to manipulate the DOM and undo the manipulation afterward. I'm not quite sure what to do here.
Update
I employed the solution that I posted below it is working beautifully now. Now I am wondering if there is a way to statically write all the css for each element to the element, eliminating the need for style sheets to be referenced.
I think you are mostly on the right track by trying to make the modifications to the HTML as a string rather than on the current page for the user.
If you check this post, you might also want to follow the recommendation of creating a temporary <div> on the page, cloning your intended content to the new <div> ensuring it is invisible using "display:none." By also putting a custom Id on the new <div> you can safely apply your static sizing CSS to those elements using more careful selectors. Once you have sent the content to the server, you can blow away the new <div> completely.
Maybe?
After much pain and suffering I figured a crude but effective method for reverting my modifications to the DOM. Though I hadn't gotten around to trying #fdfrye's suggestion of cloning, I will be trying that next to see if there is a mroe elegant solution. In the meantime, here is the new code in case anyone else can benefit from it:
$('*').each(function () {
if ($(this).attr('style'))
$(this).data('oldStyle', $(this).attr('style'));
else
$(this).data('oldStyle', 'none');
$(this).width($(this).width());
$(this).height($(this).height());
});
var html = '<html>' + $('html').html() + '</html>';
$('*').each(function () {
if ($(this).data('oldStyle') != 'none')
$(this).attr('style', $(this).data('oldStyle'));
else
$(this).removeAttr('style');
});
When I'm looping through every element and modifying the css, I log the original value onto the element as data. After I assign the DOM HTML to a variable I then loop through all elements again and restore the style attribute to its original value. If there was no style attribute then I log 'none' to the element data and then remove the style attribute entirely when looping through again.
This is more performance heavy than I wish it was since it loops through all elements twice; it takes a few seconds to finish. Not horrible but it seems like a little much for such a small task. Anyway, it works. I get a string with fixed-sized HTML elements and the DOM goes back to normal as if the plugin never touched it.

How to dynamically delete a div and clear the memory so I could add a new div with the same ID but different content using jQuery?

I am using the Picasa Web Integrator (PWI) code, that allows me to present a picture gallery using a picasa account. Using a form the user writes a keyword and then a code creates a div and calls for the PWI.
It works perfectly, but I'm trying to add a "back" button in order to let the user select a different keyword without refreshing.
But the code doesn't seem to clear the memory and the result is the same as the first time.
Here is the code:
//The button that the user presses when he has written the keyword.
$("#boton2").click(function() {
//Creates a new div
$(".shop3").append("<div></div>");
$('.shop3 > div').attr('id', 'container3');
//gets the keyword and creates a variable called "competidor"
competidor = $('#competidor_txt').val();
//calls for the PWI code...
$("#container3").pwi({
username: 'davidagnino',
mode: 'keyword',
...
//This part works perfectly.
//The "back" button that should delete the div called #container3
$('#back3').click(function() {
event.preventDefault();
competidor=null;
delete competidor;
$("#container3").empty(); //should make my div empty
$("#container3").remove(); //deletes the div...
});
I think the best approach here would be to change the Div's ID on the fly, and thus set it up as a whole new div each time.
I'd set up a counter variable (ideally static, but global if that's over your head):
var divCounter=0;
$("#container"+divCounter).pwi({/*...*/});
when it's time to destroy that, increment divCounter and generate a whole new div. Should get the job done!
Obviously, in all your event handlers you'd refer to it generically:
$("#container"+divCounter);
A quick note, removing something completely removes it from the DOM, thus emptying it in the same operation. It's also good jQuery practice to chain your functions together, like this:
$("#container3").append(/*whatever*/).attr(/*whatever*/);

Categories