I do have an URL which opens a webpage which is very slow to load and I have no control over it.
I do want to display a loading dialog when someone clicks this URL or to block page with an overlay div when this happens.
Note: this is not the same question as the ajax related ones, this for normal URL clicks form the user, not all of them only specific ones.
slow load...
I suppose that what I am looking for is what to put on the onClick.
You can do this :
$(function(){
$('a').click(function(){
$('<div class=loadingDiv>loading...</div>').prependTo(document.body);
});
});
Demonstration (change the link to a very slow page for best effect)
But it depends on the page : if the page sends immediately some content but not the whole content, you won't have the time to see your div.
If you also need an animation, it becomes a complicated matter as browsers behave very differently. Some stop all GIF animations when a new page starts loading. Basically it comes down to something like this if you have jQuery and download the spin.js library.
See working solution here:
http://jsfiddle.net/7aJyP/
<style>
#loading {
display:none;
position:absolute;
left:0;
top:0;
z-index:1000;
width:100%;
height:100%;
min-height:100%;
background:#000;
opacity:0.8;
text-align:center;
color:#fff;
}
#loading_anim {
position:absolute;
left:50%;
top:50%;
z-index:1010;
}
</style>
<div id="loading"><div id="loading_anim"></div></div>
link
<script>
$(function () {
$(".withanimation").click(function(e) {
e.preventDefault();
$("#loading").show();
var url=$(this).attr("href");
setTimeout(function() {
setTimeout(function() {showSpinner();},30);
window.location=url;
},0);
});
});
function showSpinner() {
var opts = {
lines: 15, // The number of lines to draw
length: 3, // The length of each line
width: 4, // The line thickness
radius: 30, // The radius of the inner circle
rotate: 0, // The rotation offset
color: '#fff', // #rgb or #rrggbb
speed: 2, // Rounds per second
trail: 70, // Afterglow percentage
shadow: false, // Whether to render a shadow
hwaccel: false, // Whether to use hardware acceleration
className: 'spinner', // The CSS class to assign to the spinner
zIndex: 2e9, // The z-index (defaults to 2000000000)
top: 'auto', // Top position relative to parent in px
left: 'auto' // Left position relative to parent in px
};
$('#loading_anim').each(function() {
spinner = new Spinner(opts).spin(this);
});
}
</script>
If you use an animated (GIF) the animation may freeze on some browsers. I used spin.js library ( http://fgnass.github.com/spin.js/ ). While GIFs get frozen the javascript animation seems to be working.
Please test with ALL browsers!
Although ajax would be more elegant, it's possible. You have to intercept the navigation by preventing the default event, then force an update to the UI, then change the location to the destination url. Something like this:
$('#mylink').click(function(e) {
e.preventDefault();
var url = this.href;
// Update the UI here
setTimeout(function() {
// This is a trick to force a repaint
window.location.href = url;
},0);
});
This is an old topic, but if you want a simple solution that doesn't depend on JQuery add the following to onClick in your link:
slow load...
Then somewhere on your page, have a hidden DIV that includes what you want for the loading dialog.
<div id="page-loader">
<h3>Loading page...</h3>
</div>
and hide the DIV with CSS as follows:
#page-loader {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 10000;
display: none;
text-align: center;
width: 100%;
padding-top: 25px;
background-color: rgba(255, 255, 255, 0.7);
}
Here's a JSfiddle to a working example: http://jsfiddle.net/meb69vqd/
I can't take full credit for this example. There are additional tips about this technique here: https://css-tricks.com/css-page-loader/
Presumably, you'll want the loading dialog to appear immediately, then to disappear and be replaced by the new page when the new page has rendered?
Three ideas come to mind.
If you have control of the source page but not the target - Use a click event handler to replace the tags' normal behavior with something like this:
Display the loading animation
Fire an AJAX request to the URL defined by the tag's href attribute (alternately, create a hidden with the URL as its source)
When the request has completed, replace the document's contents with the response.
This can get really hairy, though, since you won't lose javascript and css defined in the original page. It also won't change the URL displayed in the user's browser.
If you have control of the target and can make the target cacheable (even for a few seconds): You could load the page in the background via AJAX and then redirect to it. The first load will be slow, then the redirect will load the page from cache.
And yet another alternative: If you have control of the target page, you can define an optional parameter such that if the parameter is present, the server returns a page consisting of only the loading animation and a bit of javascript that loads the actual page.
initially store a spinner.gif some where in your form and keep it hidden
and also put src=""
thus there will be no src for image
but later on while making the ajax call you can set the src for the spinner image thus you page will seem to be loading
$(document).ready(function() {
// bind 'myForm' and provide a simple callback function
$("#tempForm").ajaxForm({
url:'url to be called',
type:'post',
beforeSend:function()
{
alert("this is the place where you place things to happen till your page is being transfered to the given URL so i am setting the src for the spinner image here");
$("#spinner image ID").attr("src","../images/spinner.gif");
},
success:function(e){
alert("do whatever you want with response here");
}
});
});
You can create a hidden iframe and listen for the load event. You will also need to do a manual check after about 1 sec, in case the destination has prevented x-frame content.
DEMO: http://jsbin.com/ijofih/1
$('a').click(function(e) {
$(this).text('Loading...'); // do your UI thing here
e.preventDefault();
var destination = this.href;
setTimeout(function() {
window.location = destination;
},1000);
$('<iframe>').hide().appendTo('body').load(function() {
window.location = destination;
}).attr('src', destination);
});
an improvement over #bfavaretto 's solution that worked for me
$('#mylink').click(function(e) {
e.preventDefault();
var url = this.href;
// Update the UI here
requestAnimationFrame(function() {
setTimeout(function() {
window.location.href = url;
});
});
});
the browser would inconsistently display my spinner. I tried hacking around with increasing the setTimeout's delay. The proper solution is to ask the browser when it is ready to show the spinner, then navigate away.
You might want to look into Modal boxes. You can activate a model box when the ajax request is send and on success maybe close it.
https://www.google.com/search?sugexp=chrome,mod=10&sourceid=chrome&ie=UTF-8&q=modal+box
Related
I run a free resource site providing tileable/seamless patterns and I'm trying to add a button (with a script) in my posts which visitors can click to change the background image of the page so that they can preview the pattern in action. So for instance on this post (http://tileablepatterns.com/denim-pattern/) I'd want the user to be able to click on a button/link which would change the background image from the grey background to the denim pattern.
How do I go about doing this? Also, preferably I'd want it to be a simple script that I can just insert into the post instead of having to edit theme files.
Thanks a lot for any help!
Give your button an ID, for example: id="button" and then the following should work:
$('#button').click(function(){ $('body').css('background', 'url(http://tileablepatterns.com/wp-content/uploads/2014/09/Denim.jpg) repeat 0 0'); });
So basically I tried this <button onclick="document.body.style.background = 'url(http://tileablepatterns.com/wp-content/uploads/2014/09/Denim.jpg) no-repeat center center'">change bg</button>
And it adds two white lines to the existing background, one close to the top and one close to the bottom but it's not changing the entire background. I think there's a wrapper over the background or something but I don't know how to change the code so that it changes the entire page's background including the wrapper?
If I were to do this using jQuery, I'd take a modular approach and one that's easy to template in HTML and still works when Javascript fails.
Start with some basic markup (I'm using Baconmockup as a sample image):
<div id="page" class="container">
<!-- Note that we're defining both href as well as two html5 attributes called data-src and data-background-change (data-background-change is what indicates that this particular link has some special functionality and data-src is the the source for the script below) -->
<a href="https://s3.amazonaws.com/baconmockup/img/baconmockup-470-300.jpg" data-src="https://s3.amazonaws.com/baconmockup/img/baconmockup-470-300.jpg" data-background-change>Click me</a>
</div>
And a bit of CSS:
// The container is your page, and the background we'll change in this example.
div.container {
background: red;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
And finally in main.js:
$(function () {
$.fn.changeBackgroundOnClick = function () {
var target = this[0];
var image = target.getAttribute('data-src');
$(target).on('click', function(e) {
// If JS is enabled, the click will prevent the browser from navigating to the image.
e.preventDefault();
$('#page').css({
'background-image' : 'url(' + image + ')',
'background-size' : 'cover',
'background-repeat' : 'no-repeat'
});
});
return this;
}
// We can now iterate over every element with data-background-change to give it the functionality you need. No code needs to be repeated. :)
$('a[data-background-change]').each(function () {
$(this).changeBackgroundOnClick();
});
});
Good luck.
Check out this fiddle: http://jsfiddle.net/Nyyby/31/
I am using a mixture of jQueryTools overlay (lightbox type thing) and a scroll-bar called Perfect Scrollbar. The problem I have is that when the overlay is loaded the scroll-bar doesn't show until you scroll within that box. I need to be able to make it clearer so that everyone knows it is a scroll-able content box. One way this could be possible is to make the content box scroll up one pixel when the overlay is opened. I have found the following code
$(".scroll-content").load(function() {
window.scrollBy(0,-1);
}
which I have been told should work but no matter what I can't get it to scroll at all.. Is there something i'm doing wrong?
Since you have the scroll bar method bind to an element that is initially in a 'hide' status, in fact .BigSuperBlock .block_overlay is hidden by display:none; in Css, the plugin can not properly calculate the height of the overlay container.
So, when you call the function that show-up the 'overlay' container, you have to call the method on the scroll-content class:
$('.scroll-content').perfectScrollbar('update');
You can find the documentation of this in the author's page.
To make it works, you have to call the plugin 'update' method, again, in the jQueryTools modal function, as a callback.
$(".block_overlay").overlay({
onLoad: function(event) {
$('.scroll-content').perfectScrollbar('update');
// here you update the perfectScrollbar plugin
},
onClose: function(event) {
// other custom code
}
});
Try with this:
jQuery("container").animate({ scrollTop: 50 }, 800);
Give that you want to make clear that there is a scrollbar, you can have it on all the time if you change the perfect-scrollbar.css
.ps-container .ps-scrollbar-x-rail {
...
opacity: 0.6;
}
.ps-container .ps-scrollbar-y-rail {
...
opacity: 0.6;
}
I am doing a rather simple Tween animation using MooTools. The opening animation is perfectly smooth. But then I added the closing animation (opposite of the opening animation), but it seems to stutter/hiccup at the end almost every time.
I tried the following with no success:
Removed all HTML content from the expanding DIV
Passing the Bounce settings directly to the Set function instead of using the variable
Commented the #content animation to be sure there is only 1 animation running
Commented the addClass and removeClass actions
I can't figure out what's causing the problem. Maybe someone else can have a look…
I put the test-case online here: http://dev.dvrs.eu/mootools/
window.addEvent('domready', function() {
// Set initial Div heights
$('sideBar').setStyle('height', window.getSize().y);
$('sideMenu').setStyle('height', window.getSize().y);
// Set Div heights on Window resize
window.addEvent('resize', function() {
$('sideBar').setStyle('height', window.getSize().y);
$('sideMenu').setStyle('height', window.getSize().y);
});
var bounce = {
transition: Fx.Transitions.Back.easeOut,
duration: 500
};
$$('.button.closeMenu').addEvent('click', function(event) {
event.preventDefault();
$$('.button').removeClass('active');
this.addClass('active');
$('sideMenu').set('tween', bounce);
$('sideMenu').tween('width', 0);
$('content').set('tween', bounce);
$('content').tween('margin-left', 90);
});
$$('.button.menu').addEvent('click', function(event) {
event.preventDefault();
$$('.button').removeClass('active');
this.addClass('active');
$('sideMenu').set('tween', bounce);
$('sideMenu').tween('width', 300);
$('content').set('tween', bounce);
$('content').tween('margin-left', 390);
});
});
Fiddle with example here
The transition you are using goes over the values defined as final value in the .set(property, value);. So when opening the final width is 300px but the transition/effect goes over that and than soft back to the final value.
This works great when opening because width can be 310px or more and then return to 300px, but when with has a transition under the with 0px, it doesn't work so good. It actually works ok if the final width is 10px (check here), but that's not the effect you want.
So my suggestion is to fix it with CSS, or change the transition when closing the sidebar, or use another effect altogether.
Option 1: fiddle - same transition opening, no easeout closing
Option 2: fiddle - same effect as you have but played with CSS and hidded 10px of the sidemenu under the sidebar. (z-index:3; on #sideBar and left:80px;width: 10px; on #sideMenu. Also 10px as the final value for the tween.)
To check different transitions at Mootools demo's look here.
I am making a page that displays data in the form of a heatmap. The script that writes the image to the page runs every second. As I am plotting from live data, it's very important that the heatmap updates every second.
The problem is that my image flickers. How can I get rid of that flicker?
I can't cache it as I need to change it. If the image flickering cannot be stopped, can it be given some smooth transition?
<script type="text/javascript" charset="utf-8">
function toggle (mainImage, backupImage) {
//$("#imagecontainer").load("./php/sarimage.png");
var refreshId = setInterval(function() {
var ele = document.getElementById(mainImage);
var imageEle = document.getElementById(backupImage);
var randomnumber=Math.floor(Math.random()*101);
var source ="./php/sarimage.png?dummy=";
source = source.concat(randomnumber);
imageEle.src = source;
$("#imagecontainer").load(source);
ele.src= imageEle.src;
}, 1000);
$.ajaxSetup({ cache: false });
}
</script>
It looks like you're feeding a SRC URL to the image using JavaScript that runs an AJAX call once a second to get fresh data. I suspect that the image is probably flickering because of network latency -- it takes a moment for the fresh image data to download and then get updated.
You might try introducing a one-second delay into the script. Use two images, one on screen for the currently displayed data, and one offscreen. Load fresh info into the off screen image. Then, swap the positions of the two images (onscreen goes off, offscreen goes on). Because the fresh data would be loaded into an image outside the viewport, the download wouldn't happen visibly. Just moving it into position should take place with no perceptible flicker.
It would go something like this (this is pseudo code that won't necessarily run). First, some HTML -- just a couple of images.
<img src="initial.png" alt="heatmap" class="heatmap onscreen" />
<img src="loading-area.png" alt="heatmap" class="heatmap" />
Then some CSS:
/* By default heatmaps are off screen. */
.heatmap { position: absolute; left: -999em; }
/* But then we override that for ones marked as on screen. */
.heatmap.onscreen { position: static; left: auto; }
Lastly some JavaScript.
var firstRun = true;
function loadNewImage(){
// Download fresh image and load it into an image OFF SCREEN.
var imagePath = '/path/to/image.png?dummy='+Math.floor(Math.random()*101);
$(".heatmap:not(.onscreen)").attr("src", "imagePath");
}
function updateImage(){
if(firstRun){
// The first time this function runs, load new data ...
loadNewImage();
// Now make a note that the function has run already.
firstRun = false;
// And return without doing anything else.
return false;
} else {
// The off screen image has fresh data by this time. Swap it.
$(".heatmap:not(.onscreen)").addClass("next");
// Remove the onscreen class from the current image, so it
// moves off screen.
$(".onscreen").removeClass("onscreen");
// Add onscreen to the next one, moving it into place.
$(".next").addClass("onscreen");
// Remove the "next" class from the newly displayed image.
$(".next").removeClass("next");
// Load more image data.
loadNewImage();
}
// Lastly, call this same function again in a second.
window.setTimeout(updateImage, 1000);
}
$(document).ready(function(){
// Start the swapping.
updateImage();
});
Assuming you have a reasonably speedy and reliable connection, something like that should take care of flickering caused by network latency. It does introduce a one second delay -- the currently displayed image will always be one second behind realtime. But if real time synchronicity is important to you, then HTML/CSS/JavaScript is probably the wrong tool for the job.
If there's some OTHER cause for your flickering, well, good luck.
I was having an issue where a flot graph would not render in a tabbed interface because the placeholder divs were children of divs with 'display: none'. The axes would be displayed, but no graph content.
I wrote the javascript function below as a wrapper for the plot function in order to solve this issue. It might be useful for others doing something similar.
function safePlot(placeholderDiv, data, options){
// Move the graph place holder to the hidden loader
// div to render
var parentContainer = placeholderDiv.parent();
$('#graphLoaderDiv').append(placeholderDiv);
// Render the graph
$.plot(placeholderDiv, data, options);
// Move the graph back to it's original parent
// container
parentContainer.append(placeholderDiv);
}
Here is the CSS for the graph loader div which can be placed
anywhere on the page.
#graphLoaderDiv{
visibility: hidden;
position: absolute;
top: 0px;
left: 0px;
width: 500px;
height: 150px;
}
Perhaps this is better solution. It can be used as a drop in replacement for $.plot():
var fplot = function(e,data,options){
var jqParent, jqHidden;
if (e.offsetWidth <=0 || e.offetHeight <=0){
// lets attempt to compensate for an ancestor with display:none
jqParent = $(e).parent();
jqHidden = $("<div style='visibility:hidden'></div>");
$('body').append(jqHidden);
jqHidden.append(e);
}
var plot=$.plot(e,data,options);
// if we moved it above, lets put it back
if (jqParent){
jqParent.append(e);
jqHidden.remove();
}
return plot;
};
Then just take your call to $.plot() and change it to fplot()
The only thing that works without any CSS trick is to load the plot 1 second after like this:
$('#myTab a[href="#tabname"]').on("click", function() {
setTimeout(function() {
$.plot($(divChartArea), data, options);
}, 1000);
});
or for older jquery
$('#myTab a[href="#tabname"]').click (function() {
setTimeout(function() {
$.plot($(divChartArea), data, options);
}, 1000);
});
The above example is applied to Bootstrap tags for Click funtion. But should work for any hidden div or object.
Working example: http://topg.org/server-desteria-factions-levels-classes-tokens-id388539
Just click the "Players" tab and you'll see the above example in action.
This one is a FAQ:
Your #graphLoaderDiv must have a width and height, and unfortunately, invisible divs do not have them. Instead, make it visible, but set its left to -10000px. Then once you are ready to show it, just set it's left to 0px (or whatever).
OK, I understand better now what you're actually saying... I still think your answer is too complicated though. I just tried this out using a tabbed interface where the graph is in a hidden tab when it's loaded. It seems to work fine for me.
http://jsfiddle.net/ryleyb/dB8UZ/
I didn't have the visibility:hidden bit in there, but it didn't seem necessary...
You could also have visibility:hidden set and then change the tabs code to something like this:
$('#tabs').tabs({
show: function(e,ui){
if (ui.index != 2) { return; }
$('#graphLoaderDiv').css('visibility','visible');
}
});
But given the information provided, none of that seems particularly necessary.
I know this is a bit old but you can also try using the Resize plugin for Flot.
http://benalman.com/projects/jquery-resize-plugin/
It is not perfect because you'll sometimes get a flash of the non-sized graph which may be shrunk. Also some formatting and positioning may be off depending on the type of graph that you are using.