I have written a code where I have configured the OnPageShow(event) for checking if the page is from cache. If the page is from cache, I reload the same page for hitting the server. But while doing this, there is a screen flickering issue. The reason is When I click the browser back button, first the page from cache loads and is displayed, and then after complete loading it goes in the OnPageShow method which again refreshes the page. Is there any way to avoid the flickering issue ?
Here is the code:
function RefreshloadWindow()
{
if(!(window.performance && window.performance.navigation.type == 2))
{
console.log("In On Load");
GetLatestBreadcrum();
}
}
function GetLatestBreadcrum()
{
console.log("In Breadcrum function");
var matches=[];
var divElements=document.getElementById("breadCrumDiv").children;
console.log(divElements);
var j=0;
for(i=0;i<divElements.length;i++)
{
//console.log(divElements[i].tagName);
if(divElements[i].tagName=="A")
{
matches[j]=divElements[i];
j++;
}
}
for(z=0;z<matches.length;z++)
{
console.log(matches[z]);
}
var lastElement=matches.length;
//matches[lastElement-1].click();
window.name=matches[lastElement-1];
console.log(window.name);
}
function IsPagePersisted(event)
{
if(event.persisted || window.performance && window.performance.navigation.type == 2)
{
//console.log("From Cache 2");
var iLink=document.createElement('A');
iLink.href=window.name;
GetLatestBreadcrum();
iLink.click();
}
}
And Body tag is as follow:
<body onpageshow="IsPagePersisted(event)" onload="RefreshloadWindow()" >
If you do not want to show the page initially you can add
"display: none;" to the body tag and then remove that style after the reload.
Related
We have a Lottie animation that should act as a preloader and show only on the Home page.
We want to SHOW this when accessing the home page by:
clicking on a link from an external page (not on your website)
clicking refresh on the browser
when entering the URL in the browser's address bar.
We DON'T want to show the animation when
clicking on a link from an internal page (on your website)
navigate through the browser's prev/next history buttons.
<script src="https://code.jquery.com/jquery-3.6.3.min.js" integrity="sha256-pvPw+upLPUjgMXY0G+8O0xUf+/Im1MZjXxxgOcBQBXU=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.7.4/lottie.min.js"></script>
<div id="preloader">
<div class="logo" id="home-preloader"></div>
</div>
<style>
/* Some styling here */
</style>
<script>
function playPreloader() {
var animation = bodymovin.loadAnimation({
container: document.getElementById('home-preloader'),
path: 'preloader.json',
renderer: 'svg',
loop: false,
autoplay: true,
name: "Home Preloader",
});
}
</script>
Any ideas on how to do it? I tried a few things with PerformanceNavigation.type and PerformanceNavigationTiming.type but couldn't manage to figure it out. I'm not very skilled in JavaScript, but can manage things if I can have direction.
Even if this worked, it doesn't seem to differentiate between external and internal links.
window.addEventListener("load", function() {
var performance = window.performance || window.webkitPerformance || window.msPerformance || window.mozPerformance;
var navigation = performance.getEntriesByType("navigation")[0];
if (navigation.type === "navigate") {
console.log("The page was accessed by following a link, a bookmark, a form submission, or a script, or by typing the URL in the address bar.");
}
else if (navigation.type === "reload") {
console.log("The page was accessed by clicking the Reload button or via the Location.reload() method.");
playPreloader();
yesPreloader();
}
else if (navigation.type === "back_forward") {
console.log("The page was accessed by navigating into the history.");
noPreloader();
}
else {
console.log("Any other way.");
}
});
After researching for two days, I found a comment that was very helpful and helped me create a working solution to my problem. Here's the code for anyone having the same problem.
If somebody can confirm that all of this is correct, that would be nice.
/* (0) WHEN THE PAGE IS LOADED */
window.addEventListener("load", function() {
/* (1) FIND HOW THE PAGE WAS ACCESSED */
var result;
var p;
if (window.performance.navigation) {
result = window.performance.navigation;
// 255
if (result == 255) {
result = 4
}
}
if (window.performance.getEntriesByType("navigation")) {
p = window.performance.getEntriesByType("navigation")[0].type;
// Page was accessed from a link or address bar
if (p == 'navigate') {
result = 0
}
// Page was reloaded (browser reload operation)
if (p == 'reload') {
result = 1
}
// Back or Forward (browser history)
if (p == 'back_forward') {
result = 2
}
// Prerender
if (p == 'prerender') {
result = 3
}
}
console.info(result);
/* (2) WHAT TO DO IN EACH CASE */
if (result == 0) {
// Page was accessed from a link or address bar
console.info("Page was accessed from a link or address bar");
console.info("Result was 0, result=" + result);
// Was it an internal link or (external link or address bar)
if (document.referrer.indexOf(location.hostname) !== -1) {
// Page was accessed from an internal link
console.info("Page was accessed from an internal link");
$(document).ready(function() {
noPreloader();
});
} else {
// Page was NOT accessed from internal link
// Probably accessed from external link or address bar
console.info("Page was NOT accessed from internal link. Probably accessed from an external link or address bar");
$(document).ready(function() {
$(this).scrollTop(0);
document.body.classList.add("overflow-x-hidden");
document.body.classList.add("overflow-y-hidden");
playPreloader();
yesPreloader();
});
}
} else if (result == 1) {
// Page was reloaded (browser reload operation)
console.info("Page was accessed by reloading (browser reload operation)");
console.info("Result was 1, result=" + result);
$(document).ready(function() {
$(this).scrollTop(0);
document.body.classList.add("overflow-x-hidden");
document.body.classList.add("overflow-y-hidden");
playPreloader();
yesPreloader();
});
} else if (result == 2) {
// Back or Forward (browser history)
console.info("Page was accessed from the browser history back or forward buttons");
console.info("Result was 2, result=" + result);
$(document).ready(function() {
noPreloader();
});
} else {
// Any other instance
console.info("Page was accessed: Any other instance (prerender or 255)");
console.info("Result was probably 255 (4) or prerender (3), result=" + result);
$(document).ready(function() {
noPreloader();
});
}
});
/* [END OF] (1) WHEN THE PAGE IS LOADED */
I have a JavaScript issue. I am using it to open an HTML web page in a new frame with the following function:
function openBranch(url) {
if (url == "Ping") {
top.folderFrame.location = "Ping.html"
} else if (url == "Logout") {
top.top.location = "Logout.html"
}
}
HTML usage:
<a href='javascript:openBranch("Ping")'>Ping</a>
I am unable to open another web page in my side menu bar once my Ping.html page is processed (Post request is used). My side menu bar is unable to open the new page and is not able to process any request.
It looks like the argument of the function changes the source of the document. If you want to just change the source, why don't you just do something like this:
<iframe src="test1.html" id="top"></iframe>
change to 1
change to 2
<script>
function change(val) {
if (val === 1) {
document.getElementById("top").src = "test1.html";
} else {
document.getElementById("top").src = "test2.html";
}
}
</script>
I am playing with jquery and js, trying to build an ajax overlay image viewer for a PHP website. With this code included at the bottom of the 'gallery page', the viewer opens and i can navigate with next and previous links inside the viewer. But the back button and the history is hard to understand. The browser often shows only the response of the ajax call, without the underlying page and css files, after some clicks back.
Perhaps somebody knows what is generally happening in such a case? I would like to understand why back sometimes results in a broken page, i.e. only the ajax response.
<script type="text/javascript">
$(document).ready(function() {
function loadOverlay(href) {
$.ajax({
url: href,
})
.done(function( data ) {
var theoverlay = $('#flvr_overlay');
theoverlay.html( data );
var zoompic = $('#zoompic');
zoompic.load(function() {
var nih = zoompic.prop('naturalHeight');
var photobox = $('#photobox');
if($(window).width() >= 750){
photobox.css('height',nih);
}
theoverlay.show();
$('body').css('overflow-y','hidden');
$(window).resize(function () {
var viewportWidth = $(window).width();
if (viewportWidth < 750) {
photobox.css('height','auto');
zoompic.removeClass('translatecenter');
}else{
photobox.css('height',nih);
zoompic.addClass('translatecenter');
}
});
});
});
return false;
}
var inithref = window.location.href;
$(window).on('popstate', function (e) {
if (e.originalEvent.state !== null) {
//load next/previous
loadOverlay(location.href);
} else {
//close overlay
$('#flvr_overlay').hide().empty();
$('body').css('overflow-y','scroll');
history.replaceState(null, inithref, inithref);
}
});
$(document).on('click', '.overlay', function () {
var href = $(this).attr('href');
history.pushState({}, href, href);
loadOverlay(href);
return false;
});
});
</script>
edit
clicking forward works:
/photos (normal page)
/photos/123 (overlay with '/photos' below)
/locations/x (normal page)
/photos/567 (overlay with '/locations/x' below)
clicking back gives me the broken view at point 2.
Do you need to prevent the default behaviour in your popstate to prevent the browser from actually navigating back to the previous page?
you have to manage it by own code.
You have a few options.
Use localstorage to remember the last query
Use cookies (but don't)
Use the hash as you tried with document.location.hash = "last search" to update the url. You would look at the hash again and if it is set then do another ajax to populate the data. If you had done localstorage then you could just cache the last ajax request.
I would go with the localstorage and the hash solution because that's what some websites do. You can also copy and paste a URL and it will just load the same query. This is pretty nice and I would say very accessible
Changing to document.location.hash = "latest search" didn't change anything.t.
This goes into the rest of the jQuery code:
// Replace the search result table on load.
if (('localStorage' in window) && window['localStorage'] !== null) {
if ('myTable' in localStorage && window.location.hash) {
$("#myTable").html(localStorage.getItem('myTable'));
}
}
// Save the search result table when leaving the page.
$(window).unload(function () {
if (('localStorage' in window) && window['localStorage'] !== null) {
var form = $("#myTable").html();
localStorage.setItem('myTable', form);
}
});
Another solution is that use INPUT fields to preserved while using back button. So, I do like that :
My page contains an input hidden like that :
Once ajax content is dynamicaly loaded, I backup content into my hidden field before displaying it:
function loadAlaxContent()
{
var xmlRequest = $.ajax({
//prepare ajax request
// ...
}).done( function(htmlData) {
// save content
$('#bfCache').val( $('#bfCache').val() + htmlData);
// display it
displayAjaxContent(htmlData);
});
}
And last thing to do is to test the hidden field value at page loading. If it contains something, that because the back button has been used, so, we just have to display it.
jQuery(document).ready(function($) {
htmlData = $('#bfCache').val();
if(htmlData)
displayAjaxContent( htmlData );
});
I am using the HTML history API to manipulate the browser history stack to control navigation using JavaScript on my site. The function I have set up to change pages is working fine, but weirdly, when I added pushState to each individual page change, the pushState fires automatically, so that the last page change in the function is always the final one executed. This means the state being pushed is always the last page change statement.
The JavaScript:
// Change Page Function
function ChangeContent (page) {
var pages={"homepage":{title: "homepage"},"servicespage":{title: "servicespage"},"estimatespage":{title: "estimatespage"}};
HideNav();
//Show home page
for(var homepage in pages) {
if(page!==homepage) {
document.getElementById(homepage).style.display='none';
}
else {
document.getElementById(homepage).style.display='block';
history.pushState("homepage", "Home", "home" );
window.scrollTo(0,0);
}
}
//Show services page
for(var servicespage in pages) {
if(page!==servicespage) {
document.getElementById(servicespage).style.display='none';
}
else {
document.getElementById(servicespage).style.display='block';
history.pushState( "servicespage", "Our Services", "services");
window.scrollTo(0,0);
}
}
//Show estimates page
for(var estimatespage in pages) {
if(page!==estimatespage) {
document.getElementById(estimatespage).style.display='none';
}
else {
document.getElementById(estimatespage).style.display='block';
history.pushState( "estimatespage", "Get An Estimate", "estimates");
window.scrollTo(0,0);
}
}
}
When you run this code, instead of each individual page pushing it's state when that page is clicked, the state getting pushed is always the estimates page state. I've tried using else if statements instead, and I've tried embedding each for statement into self executing functions in the hope that it might solve a scope issue of some kind, but I've had no luck.
This is my onPopstate function:
// History State Change Display
window.onpopstate = function (event) {
var state = event.state;
console.log(state);
// Change History State Display To Home Page
if (state === "homepage") {
document.getElementById("homepage").style.display = 'block';
} else {
document.getElementById("homepage").style.display = 'none';
}
// Change History State Display To Services Page
if (state === "servicespage") {
document.getElementById("servicespage").style.display = 'block';
} else {
document.getElementById("servicespage").style.display = 'none';
}
// Change History State Display To Estimates Page
if (state === "estimatespage") {
document.getElementById("estimatespage").style.display = 'block';
} else {
document.getElementById("estimatespage").style.display = 'none';
}
};
For some reason each new page I click on has the URL extensions /estimatespage and then when I click the back button, it just cycles through the pages in reverse order in which they were written in the page change function, and properly updates the URL.
I'm not totally sure what the issue here is, but I think I'm pushing the state of all the pages automatically, which is weird, since the rest of the code is only executing when the proper page is selected.
Any help would be appreciated, as I think this is probably more obvious than I'm making it out to be.
HTML
<div id="nav">
<div class="headerlist" onclick="ChangeContent('homepage');">Home</div>
<div class="headerlist" onclick="ChangeContent('servicespage');">Services</div>
<div class="headerlist" onclick="ChangeContent('estimatespage');">Estimates</div>
</div>
<div id=homepage></div>
<div id=servicespage></div>
<div id=estimatespage></div>
You have three for loops in ChangeContent(). All three loops are testing for exactly the same condition -- merely with a renamed variable.
Keeping the style vaguely the same, you might try this instead, note that this single loop is to replace all three of those loops in ChangeContent():
for ( var p in pages ) {
if ( page !== p ) {
document.getElementById( p ).style.display = 'none';
}
else {
document.getElementById( p ).style.display = 'block';
if ( p === "homepage" )
history.pushState( "homepage", "Home", "home" );
else if ( p === "servicespage" )
history.pushState( "servicespage", "Our Services", "services");
else if ( p === "estimatespage" )
history.pushState( "estimatespage", "Get An Estimate", "estimates");
window.scrollTo( 0, 0 );
}
}
main question
Is there a javascript way to identify if we are accessing a page for the first time or it is a cause of a back?
My problem
I'm implementing html5 navigation in my ajax driven webpage.
On the main script, I initialize a variable with some values.
<script>
var awnsers=[];
process(awnsers);
<script>
Process(awnsers) will update the view according to the given awnsers, using ajax.
In the funciton that calls ajax, and replaces the view, I store the history
history.pushState(state, "", "");
I defined the popstate also, where I restore the view according to the back. Moreover, I modify the global variable awnsers for the old value.
function popState(event) {
if (event.state) {
state = event.state;
awnsers=state.awnsers;
updateView(state.view);
}
}
Navigation (back and forth) goes corectly except when I go to an external page, and press back (arrving to my page again).
As we are accessing the page, first, the main script is called,the valiable awnsers is updated, and the ajax starts. Meanwile, the pop state event is called, and updates the view. After that the main ajax ends, and updates the view according to empty values.
So I need the code:
<script>
var awnsers=[];
process(awnsers);
<script>
only be called when the user enters the page but NOT when it is a back. Any way to do this?
THanks!
Possible solution
After the first awnser I have thought of a possible solution. Tested and works, whoever, I don't know if there is any cleaner solution. I add the changes that I've done.
First I add:
$(function() {
justLoaded=true;
});
then I modify the popState function, so that is in charge to initialize the variables
function popState(event) {
if (event.state) {
state = event.state;
awnsers=state.awnsers;
updateView(state.view);
} else if(justLoaded){
awnsers=[];
process(awnsers);
}
justLoaded=false;
}
Thats all.
what about using a global variable?
var hasLoaded = false;
// this function can be called by dom ready or window load
function onPageLoad() {
hasLoaded = true;
}
// this function is called when you user presses browser back button and they are still on your page
function onBack() {
if (hasLoaded) {
// came by back button and page was loaded
}
else {
// page wasn't loaded. this is first visit of the page
}
}
Use cookie to store the current state.
yeah! This is what I have:
var popped = (($.browser.msie && parseInt($.browser.version, 10) < 9) ? 'state' in window.history : window.history.hasOwnProperty('state')), initialURL = location.href;
$(window).on('popstate', function (event) {
var initialPop = !popped && location.href === initialURL, state;
popped = true;
if (initialPop) { return; }
state = event.originalEvent.state;
if (state && state.reset) {
if (history.state === state) {
$.ajax({url: state.loc,
success: function (response) {
$(".fragment").fadeOut(100, function () {
$(".fragment").html($(".fragment", response).html()).fadeIn(100);
);
document.title = response.match(/<title>(.*)<\/title>/)[1];
}
});
} else { history.go(0); }
else {window.location = window.location.href; }
});
And:
$.ajax({url:link,
success: function (response) {
var replace = args.replace.split(",");
$.each(replace, function (i) {
replace[i] += ($(replace[i]).find("#video-content").length > 0) ? " #video-content" : "";
var selector = ".fragment "+replace[i];
$(selector).fadeOut(100, function () {
$(selector).html($(selector,response).html()).fadeIn(100, function () {
if (base.children("span[data-video]")[0]) {
if ($.browser.msie && parseInt($.browser.version, 10) === 7) {
$("#theVideo").html("");
_.videoPlayer();
} else {
_.player.cueVideoById(base.children("span[data-video]").attr("data-video"));
}
}
});
});
});
document.title = response.match(/<title>(.*)<\/title>/)[1];
window.history.ready = true;
if (history && history.pushState) { history.pushState({reset:true, loc:link}, null, link); }
}
});