How can I unload/load pages using jQuery? - javascript

Here is the things I want to achieve with jQuery.
First of all, I want to save a copy of the entire page as is in a variable.
I then want to replace the currently loaded page with a loading page from another html file or URL without redirecting to that page.
After it has done loading, I want to replace the page back with what it originally was (the variable from step 1).

The question asked
At it's simplest (and this is a gross simplification that will lose state like event handlers, iframe state, shadow DOM etc.) you "save a copy" of the page's HTML by using .html() on the root element (html or body for example).
You can replace the entire top level element with fixed content from another HTML file or URL by providing the data to the same .html(data) function as well.
You can restore the original content by repeating step 2 using the data you saved off in step 1.
// Step 1 - save old page
const oldPage = $('html').html();
// result of fetch() or fixed HTML from file
// const newHTML = ...
// Step 2 - load new page
$('html').html(newHTML);
// Step 3 - restore old page
$('html').html(oldPage);
What you might actually want
If you only care that the user can't see the old page, you may want to wrap all of the UI inside a div that you can set display property to none on. You could also just overlay the new UI elements on top of the old one, possibly wrapped in a container with a solid background (to prevent old UI elements from being shown through transparent background).

Related

How to capture the displayed link in HTML (JavaScript) and pass to another HTML page as a variable?

I am building a website (and I am a novice) and the site has 2 frames. On the left side (frame 1), I have a list of links that when you click on a link it will load a page in frame 2 (right side). But the links are on the left side are actually the result of a query and will change.
Rather than hard coding a site for each link, I want to use one target page to display data. I want to use the link on the left side as a variable value to pass to the right side so I can use the link name in a query on the target page.
MyUniqueLink
Any help would be very appreciated.
In your first <iframe>, you can access the parent document like so:
// window.parent will be undefined if you are not in an iframe.
window.parent.document
Then, as spencer said, it would be easier for you to use document.getElementById("secondFrameId") to get to your second iframe.
Also, the onclick event might be a bit more suited to your needs.
So together the code would look like:
<a onclick="window.parent.document.getElementById('secondFrameId').src='http://example.com'">MyUniqueLink</a>
If you want to access the data in your <a>'s, you should start by giving them an id:
<a id = "myId" href="JavaScript:void(top.frames[2].location.href='Recap.html');" >MyUniqueLink</a>
Then you can grab their data using standard js:
document.getElementById("myId").innerHTML; // grabs MyUniqueLink
document.getElementById("myId").getAttribute("href"); // resolves to href value
Or accomplish the same using jQuery:
$("#myId").html();
$("#myId").attr("href");
If you are dynamically creating the <a>'s in the first place, you can also assign them an id at this point using newElement.setAttribute("id", "someNewId");.

how to combine append() and replaceWith() in jquery?

Is ther a Jquery way to combine append() and replaceWith()?
I have a login form in a JQM project, sitting on every site. As multiple pages will be loaded into the DOM, I need to move the long form "along", as the user goes from page to page, to avoid having duplicate form#ids in the DOM.
My question:
I can do like this:
$('.form_in_new_page').replaceWith('.form_in_old_page')
But is there a way to "append and replace", so I can do this with one line of code?
Thanks for help!
EDIT: some more info
Here is my script which I'm running on pagebeforehide:
$('div:jqmData(role="page").basePage').on('pagebeforehide', function(e, data) {
// look for unique elements on the page being left
$(this).find(':jqmData(unique="true")').each(function(){
var uniqueID = $(this).jqmData("unique-id"),
nextPage = data.nextPage,
nextUnique = nextPage.find( ":jqmData(unique-id='"+uniqueID+"')" ),
nextUniqueID = nextUnique.jqmData('unique-id') === uniqueID;
// if a unique element with id=123 is on both from and next page
if ( nextUniqueID == true ) {
// append element from page being left to and replace it on next page
nextUnique.replaceWith( $(this) );
}
});
});
I need to keep my pages inside the DOM in my app. All pages have a login/logout popup, which includes a form and inputs with ids. So if I have 10 pages in my DOM I will have 10 popups with 10 forms and 10x each ID. I'm inserting the popups automatically on every so they are there if the user calls a subpage directly. However as soons as the user goes to the next page I need to make sure the form on the first page appends and replaces the form on the 2nd page.
Hope it's clear now.
The above only replaces the form on the new page, but still leaves it in the old page.
In jquery since functions return this ($) you can chain calls:
$("#selector").replaceWith("<div>Hello</div>").append('<div>test2</div>');
Of corse, that means you need to chain calls in the correct order.

Completely Reload TinyMCE

I have been writing a CMS for a while now and am currently putting the last few touches on it. one of which includes using ajax to deliver a tinyMCE editor in a lightbox styled window.
when it is loaded, the first time it works perfectly, but when i do it the second time or more, the element names get messed up and it doesn't send data back, or display the current value in the TinyMCE window. When I use Chrome to inspect the element, I can see that the span that contains the previous tinyMCE window is still there.
I use document.body.removeChild to remove the div that is holding it. Does anyone have any ideas?
Addition:
when AJAX gets back from making the request (it has all the html code of what goes in the window), it creates a new div element and uses document.body.appendChild to add the element to the document and puts the html code into the div tag.
Then it travels through the new code and searches for the scripts in that area (of which one is the MCE initiator) and appends them to the head so they are executed.
if the user clicks cancel rather than save, it removes the div tag by using:
document.body.removeChild(document.getElementById("popupbox"));
which works fine,
however when i bring up popup and repopulate as said before, and inspect the elements there, there is still a span there which was created by TinyMCE and the naming has been changed (instead of being identified by 'content', it is now 8 for some reason) and there is no content in the editor region.
I have used:
tinyMCE.execCommand('mceRemoveControl',true,'mce{$Setting['name']}');
tinyMCE.editors[0].destroy();
but neither of them work. They return the tinymce window to a textarea, but the elements are still there.
Removing the editor as you described (using the correct tinymce editor id) before moving or removing the html element holding the tinymce iframe is a good choice. Where do you load your tinymce.js? If you deliver it using ajax i think it might be better to load it on the parent page(!). Some more code would be helpfull.
EDIT: I remember a situation where i had to remove a leftover span. Here is my code for this:
// remove leftover span
$('div .mceEditor').each(function(item){
if (typeof $(this).attr('style') !== "undefined" ){
$(this).removeAttr('style'); // entfernt "style: none";
}
else {
$(this).remove();
}
});

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.

Can you turn off the loading screen in Submodal?

We are using the enhanced sub-modal script (http://gabrito.com/files/subModal/) and would like to bypass the loading.html screen that comes up by default. Can this be turned off? Setting the value to "null" shows a "page not found" error before the actual page loads.
It's not hard, but the code is scattered all over the place in the Javascript source. You might want to use a more modern alternative instead (especially if you're already using a library on your site)
First of all, we strip out all instances of the gLoading variable - this means removing the setPopUpLoadingPage function and the src="'+gLoading+'" in the part where they build the HTML string to inject into the page. And finally, one last reference to gLoading exist in the hidePopWin function, to reset the iframe source back to the loading page when the modal is hidden.
Then finally we replace the line gPopFrame.src = url; in the showPopWin function with this:
if(gPopFrame.src != url){
gPopFrame.src = url;
}
To stop the iframe from reloading if it's the same source.
You can see a live demo of the new script here: http://www.jsfiddle.net/yijiang/T2u2Z/ and also grab a copy of it here: http://dl.dropbox.com/u/1722364/submodalsource.js

Categories