I was dynamically adding the scripts and link tags to the page from another page through ajax call response value, some time its not adding to page, some times its not working, occurs conflict with each other while loading.
$(document).ready(function () {
siteResponse();
$(window).error(function (e) {
e.preventDefault();
});
});
function siteResponse() {
var protocol = "http://IP/";
var server = "Site/";
var accessPage = "Home.aspx";
var url = protocol + server + accessPage;
var res = "";
$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
options.async = true;
});
$.ajax({
url: url,
success: function (result) {
res = result;
var str = res;
var scrpt = /<(?:SCRIPT|script \b[^>]*)>([\s\S]*?)<\/(?:SCRIPT|script)>/gm;
var lnk = /<link([\s\S]*?)\b[^>]*\/>/g;
while (res3 = lnk.exec(str)) {
$("#footerSection").append(res3[0]);
}
while (res2 = scrpt.exec(res)) {
$("#footerSection").append(res2[0]);
}
}
});
}
links added properly to the page but scripts not working properly, sometime its conflicting with each other, some times its not loading to the page
I've searched high and low for a solution to this problem, extremely grateful to anyone who can shed some light.
Below is a simplified version of a function used to preload 25 images. It works fantastically well in IE9-10 and in Chrome.
In IE8 it gets partway through loading the images (e.g. 10/25) then just stops. If I then refresh the browser it will continue to load images, taking ~3 refreshes to complete. This should not be necessary!
On the odd occasion it does succeed in loading all images in one go. I tried to avoid using .load() as I've read it can be problematic in IE yet here I am just the same! I also tried using different images to rule out the image format as the cause.
I'm looking for either a fix to the below code or a better solution if someone has one.
Many thanks.
function loadAllImages() {
var imgArray = [ //image SRCs stored in array
'imgsrc01.jpg',
'imgsrc02.jpg',
'imgsrc03.jpg',
...
'imgsrc25.jpg'];
var noFinalImg = imgArray.length - 1;
var i = -1;
var waitTime = 10000;
if (imgArray.length === 0) {
return;
} else {
loadImage();
};
function loadImage() {
i++;
var url = imgArray[i];
var img = new Image();
var timer;
img.src = url;
img.id = "thumb" + i;
// image loaded
if (img.complete || img.readyState === 4) {
//Call image loaded function
console.log(i + "/" + noFinalImg);
//equivalent to loop next
if (i !== noFinalImg) {
loadImage();
};
// image not loaded
} else {
// handle 404 using setTimeout set at waitTime
timer = setTimeout(function () {
if (i !== noFinalImg) {
loadImage();
};
$(img).unbind('error load onreadystate');
}, waitTime);
$(img).bind('error load onreadystatechange', function (e) {
clearTimeout(timer);
if (e.type !== 'error') {
//Call image loaded function
console.log(i + "/" + noFinalImg);
};
if (i !== noFinalImg) {
loadImage();
};
});
};
};
};
I receive images using an Ajax fonction after clicking on a link, so I don't know their widths.. I want to change the css of the images if they are bigger than 650 px. All the images have the same class name .popup_pics so I did :
$(document).ready(function (e) {
$('a[class*="popup"]').click(function(){
showPics(current); //Ajax call
if ($(".popup_pics").clientWidth > 649) {
alert($("img.popup_pics").width());
}
else {
alert($("img.popup_pics").width());
}
}
}
But it gives me undefined so I think that's because the image isn't loaded yet.
How can I do this ?
Thank you
Wait for the image to load, and then get its width. Something like this should work:
$("img.popup_pics").each(function() {
var img = $(this),
src = img.attr('src'),
image = new Image();
image.onload = function() {
// detect width here
alert(img.width());
};
image.src = src;
});
Don't forget to execute this code only after the AJAX has returned successfully and changed the HTML.
.width (http://api.jquery.com/width/) and .height (http://api.jquery.com/height/) are no properties but jquery functions, so this code works:
http://jsfiddle.net/nQvK3/1/
$(".popup_pics").each(function(index, domElement) {
if (domElement.clientWidth > 649) {
alert(domElement.id + ' is bigger then 649: ' + $("img.popup_pics").width());
}
else {
alert(domElement.id + ' is smaller then 649: ' + $("img.popup_pics").width());
}
});
I have added some more code, here is the new fiddle: http://jsfiddle.net/nQvK3/4/
first do the ajax call to your images source (i commented it out in the fiddle as i can not do an ajax call to your source)
when the ajax call is a success we call the showImages function and pass the response object as first parameter
this function uses jquery each to go through the images array
for each image we create an image tag and then add the image to the dom
we finally measure its width and if it is bigger we apply a class to it to resize it
//-- updated code
$(document).ready(function() {
/*
var request = $.ajax({
url: "images.php?gallery_id=1",
type: "GET",
data: {id : menuId},
dataType: "json"
});
request.done(function(ajaxImagesResultObject) {*/
// this is what ajax returns to you, probably an array of objects
// to test it in your code uncomment the ajax call and comment out the following object
var ajaxImagesResultObject = { imagesArray:
[
{
name: 'stackoverflow small',
url: 'http://blog.stackoverflow.com/wp-content/uploads/stackoverflow-logo-300.png'
},
{
name: 'stackoverflow big',
url: 'http://cdn.sstatic.net/stackexchange/img/logos/careers/careers-logo.png'
}
]
};
console.log(ajaxImagesResultObject);
showPics(ajaxImagesResultObject);
/*});
request.fail(function(jqXHR, textStatus) {
alert( "Request failed: " + textStatus );
});
*/
});
var showPics = function(ajaxImagesResultObject) {
// foreach image that is contained in the result array
$.each(ajaxImagesResultObject.imagesArray, function(index, imageData) {
var imageElement = $('<img src="' + imageData.url + '" id="' + index+1 + '" title="' + imageData.name + '" />');
// now we add (append) the image inside of the imagesBox element
$('#imagesBox').append(imageElement);
// now we check its width and if it is bigger then 649 we add a resize class
// to save bandwidth images that are too big should get resized on the server not the client
if ($('#' + index+1).width() > 649) {
$('#' + index+1).addClass('imageResizer');
} else {
// do nothing
}
});
};
I am reading images from an sd card and displaying it in the gallery in my phonegap application.
I have two folders from which I am reading the contents. One is a synched folder and an unsynched folder.
The code is as follows:
listGalleryContents(synchedsdcardfolder, function() {
listGalleryContents(unsynchedsdcardfolder, function() {
showGalleryPage();
});
});
function listGalleryContents(directoryEntry, onComplete) {
var directoryReader = directoryEntry.createReader();
directoryReader.readEntries(function(entries) { // success get files and folders
for(var i=0; i<entries.length; ++i) {
if(entries[i].name.indexOf(".") > 0 && entries[i].isFile) {
imagesArray.push(entries[i].fullPath);
}
}
onComplete();
} , function(error){
alert("Error: = " + error.code);
});
}
The problem comes when I have too many images to read from the sd card.
When i click on gallery view, it takes a lot of time to load the images.
Is there any way to make it more responsive and improve the performance please?
Javascript is single threaded and hence callbacks will fire in the same main thread which blocks the UI. Try changing your code to this:
listGalleryContents(synchedsdcardfolder, loadUnSyncedFolder);
function loadUnSynchedFolder() {
setTimeout(function() {
listGalleryContents(unsynchedsdcardfolder, allFoldersLoaded);
}, 0);
}
function allFoldersLoaded() {
setTimeout(showGalleryPage, 0);
}
function listGalleryContents(directoryEntry, onComplete) {
var successCallback = onComplete;
var directoryReader = directoryEntry.createReader();
directoryReader.readEntries(
function(entries) { readSuccess(entries, successCallback); } ,
function(error){
alert("Error: = " + error.code);
});
}
function readSuccess(entries, onComplete) { // success get files and folders
var i = 0, length = entries.length;
for(; i < length ; ++i) { // why are you using ++i and not i++ ??
if(entries[i].name.indexOf(".") > 0 && entries[i].isFile) {
imagesArray.push(entries[i].fullPath);
}
}
onComplete();
}
}
I have not tested this code. You may have to make minor modifications to it if you see errors.
I want to know when an image has finished loading. Is there a way to do it with a callback?
If not, is there a way to do it at all?
.complete + callback
This is a standards compliant method without extra dependencies, and waits no longer than necessary:
var img = document.querySelector('img')
function loaded() {
alert('loaded')
}
if (img.complete) {
loaded()
} else {
img.addEventListener('load', loaded)
img.addEventListener('error', function() {
alert('error')
})
}
Source: http://www.html5rocks.com/en/tutorials/es6/promises/
Image.onload() will often work.
To use it, you'll need to be sure to bind the event handler before you set the src attribute.
Related Links:
Mozilla on Image.onload()
Example Usage:
window.onload = function () {
var logo = document.getElementById('sologo');
logo.onload = function () {
alert ("The image has loaded!");
};
setTimeout(function(){
logo.src = 'https://edmullen.net/test/rc.jpg';
}, 5000);
};
<html>
<head>
<title>Image onload()</title>
</head>
<body>
<img src="#" alt="This image is going to load" id="sologo"/>
<script type="text/javascript">
</script>
</body>
</html>
You can use the .complete property of the Javascript image class.
I have an application where I store a number of Image objects in an array, that will be dynamically added to the screen, and as they're loading I write updates to another div on the page. Here's a code snippet:
var gAllImages = [];
function makeThumbDivs(thumbnailsBegin, thumbnailsEnd)
{
gAllImages = [];
for (var i = thumbnailsBegin; i < thumbnailsEnd; i++)
{
var theImage = new Image();
theImage.src = "thumbs/" + getFilename(globals.gAllPageGUIDs[i]);
gAllImages.push(theImage);
setTimeout('checkForAllImagesLoaded()', 5);
window.status="Creating thumbnail "+(i+1)+" of " + thumbnailsEnd;
// make a new div containing that image
makeASingleThumbDiv(globals.gAllPageGUIDs[i]);
}
}
function checkForAllImagesLoaded()
{
for (var i = 0; i < gAllImages.length; i++) {
if (!gAllImages[i].complete) {
var percentage = i * 100.0 / (gAllImages.length);
percentage = percentage.toFixed(0).toString() + ' %';
userMessagesController.setMessage("loading... " + percentage);
setTimeout('checkForAllImagesLoaded()', 20);
return;
}
}
userMessagesController.setMessage(globals.defaultTitle);
}
Life is too short for jquery.
function waitForImageToLoad(imageElement){
return new Promise(resolve=>{imageElement.onload = resolve})
}
var myImage = document.getElementById('myImage');
var newImageSrc = "https://pmchollywoodlife.files.wordpress.com/2011/12/justin-bieber-bio-photo1.jpg?w=620"
myImage.src = newImageSrc;
waitForImageToLoad(myImage).then(()=>{
// Image have loaded.
console.log('Loaded lol')
});
<img id="myImage" src="">
You could use the load()-event in jQuery but it won't always fire if the image is loaded from the browser cache. This plugin https://github.com/peol/jquery.imgloaded/raw/master/ahpi.imgload.js can be used to remedy that problem.
If the goal is to style the img after browser has rendered image, you should:
const img = new Image();
img.src = 'path/to/img.jpg';
img.decode().then(() => {
/* set styles */
/* add img to DOM */
});
because the browser first loads the compressed version of image, then decodes it, finally paints it. since there is no event for paint you should run your logic after browser has decoded the img tag.
Here is jQuery equivalent:
var $img = $('img');
if ($img.length > 0 && !$img.get(0).complete) {
$img.on('load', triggerAction);
}
function triggerAction() {
alert('img has been loaded');
}
Not suitable for 2008 when the question was asked, but these days this works well for me:
async function newImageSrc(src) {
// Get a reference to the image in whatever way suits.
let image = document.getElementById('image-id');
// Update the source.
img.src = src;
// Wait for it to load.
await new Promise((resolve) => { image.onload = resolve; });
// Done!
console.log('image loaded! do something...');
}
these functions will solve the problem, you need to implement the DrawThumbnails function and have a global variable to store the images. I love to get this to work with a class object that has the ThumbnailImageArray as a member variable, but am struggling!
called as in addThumbnailImages(10);
var ThumbnailImageArray = [];
function addThumbnailImages(MaxNumberOfImages)
{
var imgs = [];
for (var i=1; i<MaxNumberOfImages; i++)
{
imgs.push(i+".jpeg");
}
preloadimages(imgs).done(function (images){
var c=0;
for(var i=0; i<images.length; i++)
{
if(images[i].width >0)
{
if(c != i)
images[c] = images[i];
c++;
}
}
images.length = c;
DrawThumbnails();
});
}
function preloadimages(arr)
{
var loadedimages=0
var postaction=function(){}
var arr=(typeof arr!="object")? [arr] : arr
function imageloadpost()
{
loadedimages++;
if (loadedimages==arr.length)
{
postaction(ThumbnailImageArray); //call postaction and pass in newimages array as parameter
}
};
for (var i=0; i<arr.length; i++)
{
ThumbnailImageArray[i]=new Image();
ThumbnailImageArray[i].src=arr[i];
ThumbnailImageArray[i].onload=function(){ imageloadpost();};
ThumbnailImageArray[i].onerror=function(){ imageloadpost();};
}
//return blank object with done() method
//remember user defined callback functions to be called when images load
return { done:function(f){ postaction=f || postaction } };
}
This worked for me:
// Usage
let img = await image_on_load(parent_element_to_put_img, image_url);
img.hidden = true;
// Functions
async function image_on_load(parent, url) {
let img = element(parent, 'img');
img.src = url;
await new Promise((resolve, reject) => {
element_on(img, 'load', () => {
resolve();
});
element_on(img, 'error', () => {
reject();
});
});
return img;
}
function element(parent, tag_name, text = '') {
let result = document.createElement(tag_name);
element_child_append(parent, result);
element_html_inner(result, text);
return result;
}
function element_child_append(parent, result) {
parent.appendChild(result);
}
function element_html_inner(result, text) {
result.innerHTML = text;
}
function element_on(e, event, on_event) {
e.addEventListener(event, async () => {
await on_event();
});
}
If you are using React.js, you could do this:
render() {
// ...
<img
onLoad={() => this.onImgLoad({ item })}
onError={() => this.onImgLoad({ item })}
src={item.src} key={item.key}
ref={item.key} />
// ...
}
Where:
- onLoad (...) now will called with something like this:
{ src: "https://......png", key:"1" }
you can use this as "key" to know which images is loaded correctly and which not.
- onError(...) it is the same but for errors.
- the object "item" is something like this { key:"..", src:".."}
you can use to store the images' URL and key in order to use in a list of images.