I have put together a script which is very much like the flickr photostream feature. Two thumbnails next to each other, and when you click the next or prev links the next (or previous) two images slide in. Cool!
Currently when the page loads it loads the two images. The first time nxt / prv is used then the next two images or previous two are loaded via ajax, with the id of the first image being passed in the url and the HTML for the two new images returned and displayed via ajax.
simple enough, but it got me to thinking, on a slow connection, or heavy server load then the two images, although relatively small thumbnails could still take a while to load, and the nice things with sliding panes is the fact that the hidden data slides in quickly and smoothly preferbly without a loading delay.
So I was wondering from a performance and good practice point of view which option is best, this is what I can think of for now, open to suggestions.
1, call each set of images via JSON (its supposed to be fast?)
2,load all the possible images into a json file and pull in the details that way - although browser will still have to load image. Plus sometimes there might be 4 images, other times there could be upto 1000!
3, Load 10 images via php into a Json or other file, and load all 10 images into the browser hiding the 8 which are not on show, and always showing the middle two. Problem here is that each time someone clicks, the file has to reload the first and last images, which still takes up time, although i suppose the middle images will have all been cached via the browser by now though. But still there is a loading time.
4, Is it possible to have a json image with all the image details (regardless of numbers) and use no 3 above to load 10 of those images, is it possible to use ajax to only read 10 lines and keep a pointer of the last one it read, so the json file can be loaded fast, short refresh and images either side are cached via the browser!!
Hope thats clear, any suggestions on how you would handle this?
To preload an image from Javascript, you don't need to do anything that sounds like AJAX or JSON. All you need is this:
var img = new Image();
img.src = "http://example.com/new/image.jpg";
The browser will quite happily load the image in the background, even though it's not displayed anywhere. Then, when you update the src field of another (displayed) image tag, the browser will immediately show the part of the image it's already loaded (hopefully all of it).
Fetching JSON Via Ajax will just slow you down.
You're better off using inline JSON and generated Javascript.
<?php
$images = array( "foo.jpg","bar.jpg" );
?>
<script type="text/javascript">
jQuery(function($){
var images = ( <?php echo json_encode($images); ?> );
/* Creating A Hidden box to preload the images into */
var imgbox = document.createElement("div");
$(imgbox).css({display: 'none'});
/* Possible Alternative trick */
/* $(imgbox).css({height:1px; width: 1px; overflow: hidden;}); */
$('body').append(imgbox);
$.each( images , function( ind, item )
{
#Injecting images into the bottom hidden div.
var img = document.createElement("img");
$(img).src("/some/prefix/" + item );
$(imgbox).append(img);
});
});
</script>
In the case where you want to concurrently preload a larger number of resources, a little ajax can solve the problem for you. Just make sure the caching headers are such that the browser will use the resources on the next request. In the following example, I load up to four resources concurrently.
<script>
var urls = [
"a.png",
"b.png",
"c.png",
"d.png",
"e.png",
"f.png"
];
var currentStep = 0;
function loadResources()
{
if(currentStep<urls.length){
var url = urls[currentStep];
var req = GetXmlHttpObject();
update('loading ' + url);
req.open("GET", url, true);
req.onreadystatechange = getUpdateState(req, url);
req.send(null);
} else {
window.location = 'done.htm';
}
}
function getUpdateState(req, url) {
return function() {
var state = req.readyState;
if (state != 4) { return; }
req = null;
setTimeout('loadResources()', 0);
}
}
</script>
<!-- This will queue up to four concurrent requests. Modern browsers will request up to eight images at time -->
<body onload="javascript: loadResources(); loadResources(); loadResources(); loadResources();">
Why not use text and replace the text with a picture code (works in php really nice with ajax up to 500 pictures and more)?
Related
I retrieve about 15,000 rows from my database every time I visit this page.
The page might take about 8-10 seconds to finish load everything - I currently, use DataTable.
I think it would be nice to show user any kind of loading feedback during that time.
I want to create my own loading animations, and chose my own color, style, and size.
I'm not if I use any Ajax call.
I am just retrieving a lot of data out of my database.
What is the most efficient way to show loading animation while retrieving data from database ?
To begin with, the most simple solution is to use ajax call to retrieve the table rows populated by php.
JSFiddle
SIMPLE:
main.html / main.php
/*This makes the timeout variable global so all functions can access it.*/
var timeout;
/*This is an example function and can be disregarded
This function sets the loading div to a given string.*/
function loaded() {
$('#loading').html('The Ajax Call Data');
}
function startLoad() {
/*This is the loading gif, It will popup as soon as startLoad is called*/
$('#loading').html('<img src="http://rpg.drivethrustuff.com/shared_images/ajax-loader.gif"/>');
/*
This is an example of the ajax get method,
You would retrieve the html then use the results
to populate the container.
$.get('example.php', function (results) {
$('#loading').html(results);
});
*/
/*This is an example and can be disregarded
The clearTimeout makes sure you don't overload the timeout variable
with multiple timout sessions.*/
clearTimeout(timeout);
/*Set timeout delays a given function for given milliseconds*/
timeout = setTimeout(loaded, 1500);
}
/*This binds a click event to the refresh button*/
$('#start_call').click(startLoad);
/*This starts the load on page load, so you don't have to click the button*/
startLoad();
img {
width: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id='start_call'>Refresh</button>
<div id='loading'></div>
An example of the php would look something like this
example.php
/*Database call to get list*/
foreach($list as $li){
echo "<tr><td>$li[var1]</td><td>$li[var2]</td></tr>";
}
ADVANCED:
A more advanced way to load your content is to use webworkers and multiple database calls segregated into small chunks.
You would set up web-workers to do small 100 row results and use LIMIT in your sql statements to page the results into small chunks. Then you can page through the first 100 results while the other results are loading.
This process is more difficult and takes longer to implement, but leads to seamless and quick loading.
EDIT:
If you want to change the loading animation just change the URL. and if you want the URL to be loaded on page load put it in the div itself.
/*This will make the img load on page load rather than DOM execution.*/
<div id='loading'>
<img src="http://rpg.drivethrustuff.com/shared_images/ajax-loader.gif"/>
</div>
The Image doesn't have to be an image. It can be any loading icon you want. A gif was quick and dirty. You could use something like font-awesome spinner
data.php to check out the DB and build the table's HTML
function getData(){
//div contains the loader
$('#loader').show();
$.get('clients/data.php', function(data) {
//
$('#content').html(data);
//hide the loader
$('#loader').hide();
//build DataTable
$('#content table').dataTable();
});
}
getData();
This depends on what language you use, but the fundamentals are the same. You load the page with just the animation while the query completes, and then replace the animation with the content.
In jQuery this probably means linking the animation in plain HTML, then separately calling the database with AJAX. When you get the result, you can use jQuery append to target the content area, and write into that in real time.
I include PHP since you say that you are not using AJAX, but in PHP the structure is the same: You would need to link the image, flush the page so that it displays, and then execute your query. Cover the animation with negative CSS margin-top on the search results, and Bob is your uncle.
Your question :
"I want to create my own loading animations, and chose my own color, style, and size."
You should visit http://www.ajaxload.info/ there you can chose,customize and download loading gif really fast.
I am trying to load a static street view image, where the various parameters are stored in a mysql database. After trying lots of alternatives, I'm now passing the database data to a javascript variable and then trying to build the relevant URL (taking into account the page width along the way).
The page loads as restaurant.php?r=xyz where xyz is looked up on MySQL to return a line of data $r that is passed into a javascript array. Some of the array fields are used to create the URL of a Google Street view static image, which should then be loaded into the page.
This works fine if I enter the get to this page having started elsewhere on the site (or after a page refresh).
But if I start from this page and navigate around all future links to restaurant.php?r=abc do not load the image (it is downloaded and can be seen in the Chrome sources box). The pageinit event fires but the .html() fails to change the content (but reports no error).
I suspect I am breaking several laws of javascript, and jquery mobile....
Declared in header
var resto = {};
function insertSVPhoto() {
console.log("insertSVPhoto: Loaded data for: "+resto['rname']);
if ( Math.round(resto['heading']) != 0) {
var width = Math.round( $(document).width() * .9);
var s= "x250&location="+resto['lat']+",%20"+resto['lng']+"&fov=60&heading="+resto['heading']+"&pitch="+resto['pitch']+"&sensor=false";
var photo = "<img src='http://maps.googleapis.com/maps/api/streetview?size="+width+s+"'>";
console.log("Loading photo: "+photo);
$('#svphoto').html(photo);
} else {
console.log('No photo available');
$('#svphoto').html("<img src=''>");
}
}
And then below I have
<div data-role="page" data-add-back-btn="true">
<script type="text/javascript" >
<?php
echo "resto = ".json_encode($r).";";
?>
$( document ).on("pageinit", insertSVPhoto );
</script>
<div id='svphoto'></div>
I have to confess i'm no expert here but the way you're doing this doesn't seem quite right to me, i'd do the following:
window.onload = function () {
if(! window.device)
deviceReady()
}
document.addEventListener("deviceReady", deviceReady, false);
function deviceReady() {
$(document).delegate('#YOUR_PAGE_ID', 'pageshow', function () {
// Add your stuff here for doing the photo....
}
Again I only started using JQM a while ago but I know this works for an app i've done(and for a phonegap build too!)
EDIT: Also I would seriously consider putting everything all in one HTML document the way you've developed this is going to cause you a massive nose bleed if you try and build this as a mobile app, JQM is not designed to be used in the same way as Jquery, all of your "pages" should exist in one single html document and then use the navigation functions to move between pages.
Thanks
Marc
add data-ajax="false" or rel="external" to your links.. that should make it load properly
hello
OR
hello
I got myself in some kind of chicken-egg situation here.
I have a page with a lot of images to load and i programmed a load on scroll script, like Facebook or Google images does, so when the user gets to the bottom of the page, the next set of images is loaded.
Because the server side images loading is kinda heavy and would probably slow down the website, i just load and store all images in a cache file, load it into the page and then with javascript, i remove all of them keeping only the first few and then gradually load the rest of them.
Now the first problem i ran into is that the browser keeps loading images even if they have been deleted using javascript. To get around it, i added a css class to the images i don't wan't to load and set them as display none, which i then remove using javascript.
But i still wan't the page to be non-javascript users and crawslers to be able to see the full page. And can't figure out a way to remove this "display none" without javascript.
Thank's in advance.
Why don't you simply use ajax to load the next batch?
That way it gets loaded into segments, load is spread and you don't need to do difficult markups...
My own jquery example of what I use in these kind of cases.
I have a php file that decides what needs to be rendering on basis of the "pagenumber" which gets translated in my mysql select ..... limit $pagenumber,15
<script type="text/javascript">
alreadyloading = false;
nextpage = 1;
$(window).scroll(function()
{
if ($('body').height() <= ($(window).height() + $(window).scrollTop()))
{
if (alreadyloading == false)
{
var url = document.location.href + "/ajaxload/" + (nextpage * 15);
alreadyloading = true;
$.ajax(url).done(function(data)
{
obj = document.getElementById('images');
obj.innerHTML += data;
alreadyloading = false;
nextpage++;
});
}
}
});
</script>
I'm using jQuery to load content dynamically when the user clicks a link. The content is just a bunch of images that are then set to display in a slideshow of sorts. My problem is, I can't seem to figure out a way to show the loaded content only AFTER the images have fully loaded. I've tried several different solutions and all of them seem to either break the script or just not work the way I want. Here's the code I'm using now:
$(document).ready(function() {
$("a#item").click( function() {
var projectName = $(this).attr('class');
$("div.slideshow").css("display", "block");
$("div.slideshow").load(projectName+".php", function() {
var slideshow = new Array();
$("div.slideshow img").each(function() {
slideshow.push($(this));
});
startSlideshow(slideshow.shift());
function startSlideshow(image) {
image.delay(400).fadeIn(150, function() {
if(slideshow.length > 0) {startSlideshow(slideshow.shift());}
else { $("div.slideshow").delay(400).fadeOut(200, function() {$("div.slideshow img").css("display", "none")}); }
});
}
});
return false;
});
});
You can also see the full demo site here: http://publicprofileproject.com/
Any input would be greatly appreciated!
You could create an array of image objects in your JavaScript, loading each image into an element of the array. Attach an event handler to the onLoad event of the images.
In the event handler, increment a count of loaded images. When your counter reaches the length of your array, the browser will have all of the images. This is the point at which you can show your slideshow.
If you do this in your page load, it will have the added advantage of pre-loading the images ready for when the user clicks your link.
I believe this question has already been answered here.
The general idea is that you specify a load event handler to display it prior to specifying the source attribute.
Alternatively, if your projects+".php" file is specifying the images in ready-made, html mark-up, then you should be able to capture the load event of the images in the file you are loading. Add the following pseudocode into your file that is being loaded.
$("img").load(function() {
// show the div on the page it is getting loaded into
alert("images should be loaded now");
});
You might be able to place it in your original code segment and potentially bind it using the live / on binding events. ex: $("img").on("load", function() {...
From the load documentation:
The load event is sent to an element when it and all sub-elements have been completely loaded. This event can be sent to any element associated with a URL: images, scripts, frames, iframes, and the window object.
Edit: Interesting discouragement for doing what it looks like you're doing:
Caveats of the load event when used with images
A common challenge developers attempt to solve using the .load() shortcut is to execute a function when an image (or collection of images) have completely loaded. There are several known caveats with this that should be noted. These are:
It doesn't work consistently nor reliably cross-browser
It doesn't fire correctly in WebKit if the image src is set to the same src as before
It doesn't correctly bubble up the DOM tree
Can cease to fire for images that already live in the browser's cache
I am using the following script to display big images on mouse over the small images (example photo attached in the last). I want to show the 'loading' image (like this) while the big image is being downloaded from the server. How can this be achieved?
Note: I have asked a similar question here but I was not successful in applying the append function to the following code. Please help.
<script type="text/javascript">
function showIt(imgsrc)
{
var holder = document.getElementById('imageshow');
var newpic= new Image();
newpic.src=imgsrc;
holder.src=imgsrc;
holder.width = newpic.width;
holder.height=newpic.height;
}
</script>
<body>
/***on hover, xyz.jpg will be replaced by bigA.jpg and so on***/
<img src="smallA.jpg" onMouseOver="showIt('bigA.jpg')"/>
<img src="smallB.jpg" onMouseOver="showIt('bigB.jpg')"/>
<img src="xyz.jpg" id="imageshow" />
</body>
Images have a load event. As long as you set the load handler before the image.src is set, you should get notified when the image has successfully loaded or encounters some kind of error in loading. I do that very thing in a slideshow that I wrote so I know when the next image is ready for display and I display a wait cursor (animated gif like you're wanting) if the image has been delayed more than one second beyond it's appointed display time so the user knows what's going on.
In general, you can do something like this:
function loadImage(url, successHandler, errorHandler) {
var myImg = new Image();
myImg.onload = myLoadHandler; // universally supported
myImg.onabort = myErrorHandler; // only supported in some browsers, but no harm in listening for it
myImg.onerror = myErrorHandler;
myImg.src = url;
function myLoadHandler() {
successHandler(myImg, url);
}
function myErrorHandler() {
if (errorHandler) {
errorHandler(url);
}
}
}
Using code like this, you can display the wait cursor when you initiate the image load and hide it when the successHandler gets called.
If there were any other listeners to these events, then you should use addEventListener or attachEvent instead of onload, onabort, onerror, but if there's only one listener, you can go either way.
If the desired images are known in advance, then it's sometimes a better user experience (less waiting) to preload images that may be used later. This gets them into the browser's memory cache so they will appear instantly when needed. One can preload images either in HTML or in JS. In HTML, just insert tags into the web page for all the desired images (but hide them with CSS). In JS, just create an image array and create the image objects:
// image URLs to preload
var preloadImageURLs = [
"http://photos.smugmug.com/935492456_5tur7-M.jpg",
"http://photos.smugmug.com/835492456_968nf-M.jpg",
"http://photos.smugmug.com/735492456_3kg86-M.jpg",
];
var preloads = []; // storage for preloaded images
function preloadImages() {
var img, i;
for (i = 0; i < preloadImageURLs.length; i++) {
img = new Image();
img.src = preloadImageURLs[i];
preloads.push(img);
}
}
This will cause all the images in the preloadImageURLs array to be preloaded and available instantly later on in the life of the web page, thus preventing any user delays while waiting for images to be loaded. Obviously, there's a short amount of time for the preloaded images to actually get loaded, but for smallish images that usually happens before the user interacts with the web page so it makes for a faster feel to dynamic parts of the web page that use images.
<img id=access src=loading.gif>
<script>
window.onload=function(){
document.getElementById('access').src='access.jpg';
}
</script>
Hope this helps.