I made this code to take images from the page, convert them into data:url (what was it again... base64 encoded string), and save into localStorage. Then when the page is reloaded it should load the images from the localstorage and set the now empty image placeholders with the data:url image.
Issue now is that the images do not load and if you check the dimensions for the data:url image it is 300x150 when it was originally 40x40.
Here's the code:
var isChached, // Checks is the page's images have been chached into localStorage
isChangesd; // Checks if any images have been deleted or added to the
var img = [], // Used for loading from saved. img[] holds data:url image versions of the...
src = [], // ...images in src[]
saved = [], // All images that are to be saved are placed here
add = [], // New images are placed here
rem = []; // Images to be removed are placed here
var cnv = document.createElement("canvas");
ctx = cnv.getContext("2d");
if (window.localStorage) {
// Base Object
function Saver (width,height,path) {
this.width = width;
this.height = height;
this.src = path;
}
// These fucnctions will help you save, load, and convert the images to data:url
function save (_str) { // Saves to localStorage. _str is the key to which to save to. _path is the value that you plan on saving
var str = _str;
str += ""; // This way even if I input a none string value it is still converted into string
localStorage.setItem(str,JSON.stringify(saved));
} // Checks if this image isn't in the saved cache
function singleLoad(a,b) {
}
function loader (_str) { // Loads images from localStorage. _str is the key to be loaded
var str = _str;
str += ""; // This way even if I input a none string value it is still converted into string
var val = JSON.parse(localStorage.getItem(str)); // Save the now loaded and parsed object str into val
console.log('val '+JSON.stringify(val));
val.splice(0,1);
console.log('val2 '+JSON.stringify(val));
for (var i in val) { // Take loaded information and place it into it's proper position
img[i] = new Image(val[i].width,val[i].height);
img[i].src = val[i].src;
setTimeout(function () {
var imgs = document.getElementsByTagName("img"); // Get all images
for (var k = 0; k < imgs.length; k++) {
if (imgs[i].id == i) { // If the id is equal to the index name of the src[]
imgs[k].src = val[i].src;
imgs[k].height = img[i].height;
imgs[k].width = img[i].width;
console.log("array: "+imgs[i]+". img[i]"+img[i]);
}
}
},2000);
}
}
function addToAdd(_id,_path) { // Places on-page images into src[]
var id = _id;
id += ""; // Makes sure that the id variable is a string
var path = _path;
path += ""; // Makes sure that the path variable is a string
add[id] = new Image();
add[id].src = path;
var imgs = document.getElementsByTagName("img");
console.log(imgs);
for (var i = 0; i < imgs.length; i++) { // adds width and height attributes
if (imgs[i].id == id) {
setDim(add[id],imgs[i].width,imgs[i].height); // Send info to setDim()
}
}
}
// Not using this
function apply() { // takes images from img after being loaded and adds them to the page.
var images = document.getElementsByTagName("img");
for (var i = 0; i < images.length; i++) { // Check through the page's images
for (var k in img) { // Check through the img[] where the loaded images are now saved
if (images[i].id = k) { // Check if the id of the image on the page is
images[i].width = img[k].width;
images[i].height = img[k].height;
images[i].src = img[k].src;
console.log("source: "+images[i].src);
console.log("images: "+images[i]+". saved images "+img[k]);
}
}
}
}
function setDim(obj,w,h) { // Sets the dimension(width = w; height = h;) for obj (image object)
obj.width = w;
obj.height = h;
}
function saveToSrc(_id,_path,w,h) { // Places on-page images into src[]
var id = _id,data;
id += ""; // Makes sure that the id variable is a string
var path = _path;
path += ""; // Makes sure that the path variable is a string
src[id] = new Image();
src[id].src = path;
console.log("src image " + src[id]);
var imgs = document.getElementsByTagName("img");
console.log("page images " + imgs);
for (var i = 0; i < imgs.length; i++) { // adds width and height attributes
if (imgs[i].id == id) {
setDim(src[id],imgs[i].width,imgs[i].height); // Send info to setDim()
src[id].addEventListener("load",function() { // We convert images to data:url
console.log("saved image " + src);
ctx.drawImage(src[id],0,0,w,h);
data = cnv.toDataURL();
console.log("saved src " + data +" src width and height: "+src[id].width+","+src[id].height);
saved[id] = new Saver(src[id].width + "px",src[id].height + "px",data);
console.log("saver array: "+saved[id]);
})
}
}
}
function loadToPage(a) {
var imgs = document.getElementsByTagName("img"); // Get all images. Use this to change image src and dimensions
for (var i in a) { // Go through the a[] and load all the images inside onto page
for (var k = 0; k < imgs.length; k++) {
if (imgs[k].id == i) {
imgs[k].src = a[i].src;
imgs[k].height = a[i].height;
imgs[k].width = a[i].width;
}
}
}
}
// Here you place ID and path/location values into the src[] using the saveToSrc(). You can place the parameters in with quotation marks or without quotation marks
// **N.B** the location link will have to be changed to it's absolute form so that even if a 'scraper' gets our webpage the links still come to us \o/
if (localStorage.getItem("cached") == null) { // Check if the "cached" key exists.
// If it doesn't exist...
isCached = false;
localStorage.setItem("cached","true");
} else {
// ...If it does exist
isCached = true;
}
if (!isCached) {
// Now you take images from server and load onto page. And then save them.
window.onload = function() {
saveToSrc("1","img/1.png",40,40);
saveToSrc("2","img/2.png",40,40);
saveToSrc("3","img/3.png",40,40);
saveToSrc("4","img/4.png",40,40);
console.log("src "+src);
console.log("saved array " + saved);
loadToPage(src);
setTimeout(function() {
save('saved');
},3000)
}
}
/* Will Be Added Later. Same time as local host */
else {
window.onload = function (){
setTimeout(function() {
loader("saved");
apply
},3000)
}
}
}
I'm quite new to javascript(started using javascript this June, or was it May. anyways...) so please relax on the terminology.
To recap: Images saving correctly(-ish), not loading, and wrong image sizes saved
Related
So I have been recently developing a site, The problem is the backgrounds for each page are images, and as a result, on slower connections (which is the case of some of the target audience) the images load progressivly as they are downloaded, to resolve this I am trying to make a preloading page that does the following :
Loads the Images
Once the loading is done, redirects the user to the requested page
<script type="text/javascript">
<!--//--><![CDATA[//><!--
var images = new Array()
var count=0;
function preload() {
for (i = 0; i < preload.arguments.length; i++) {
images[i] = new Image()
images[i].src = preload.arguments[i]
}
if(count==4) {
window.location = "index.html";
}
}
preload(
"backgrounds/bg1.jpg",
"backgrounds/bg2.jpg",
"backgrounds/bg3.jpg",
"backgrounds/bg4.jpg"
)
//--><!]]>
The problem is it redirects directly (I assume that it just starts the download of the image then directly adds one to the counter variable, quickly reaching 4 and not giving the image the time to download.
Any ideas how I can either make it signal me when the images have finished downloading, or only execute the redirect after it has done downloading the images ?
You need to wait for the load event. It's quite simple:
function preload(images, timeout, cb) {
var cbFired = false,
remaining = images.length,
timer = null;
function imageDone() {
remaining--;
if(remaining === 0 && !cbFired) {
cbFired = true;
clearTimeout(timer);
cb();
}
}
function timerExpired() {
if(cbFired)
return;
cbFired = true;
cb();
}
for(var i = 0; i < images.length; i++) {
var img = new Image();
img.onload = imageDone;
img.onerror = imageDone;
img.src = images[i];
}
timer = setTimeout(timerExpired, timeout);
}
You need to check a few things so that users don't get stuck:
You need to wait for both load and error so that the page doesn't get stuck if an image fails to load.
You should set a maximum timeout.
Also, in your code, i was a global variable (no var declaration).
Here's how to use it:
var images = [ "backgrounds/bg1.jpg",
"backgrounds/bg2.jpg",
"backgrounds/bg3.jpg",
"backgrounds/bg4.jpg"];
preload(images, 10000 /* 10s */, function () {
window.location = 'next_page';
});
Modify your preloader so that it binds to the "onload" event of the Image object and when all callbacks are fired it redirects (untested sample code below):
var images = new Array()
var count = 0;
function preload() {
var numImages = preload.arguments.length
for (i = 0; i < numImages; i++) {
images[i] = new Image();
images[i].onload = doneLoading; // See function below.
images[i].src = preload.arguments[i];
}
function doneLoading() {
if (++count >= numImages) {
window.location = "index.html";
}
}
}
preload(
"backgrounds/bg1.jpg",
"backgrounds/bg2.jpg",
"backgrounds/bg3.jpg",
"backgrounds/bg4.jpg"
)
I want to draw image array with drawImage after all the images are loaded.There is a render problem with drawImage(), tried to solve with setTimeout() but its not working all the time.
Here is my code;
while(FocusItem.length>0)
{
FocusItem.pop();
}
ftx=canvas.getContext('2d');
focusImageBackground = new Image();
focusImageBackground.src = "./images/odaklanma/odaklanmaBackground.jpg";
if(RandomSoru==15)
finishSoru=true;
if(finishSoru)
{
RandomSoru = Math.floor((Math.random() * 15)+1);
tempRandomSoru=RandomSoru;
}
if(RandomSoru==tempRandomSoru)
{
RandomSoru = Math.floor((Math.random() * 15)+1);
}
var soru = new Object();
soru["image"] = new Image();
soru.image.src = './images/odaklanma/level/'+RandomSoru+'/soru.png';
soru["x"] = 341;
soru["y"] = 140;
FocusItem.push(soru);
var dogru = new Object();
dogru["image"] = new Image();
dogru.image.src = './images/odaklanma/level/'+RandomSoru+'/dogru.png';
dogru["x"] = xDogru;
dogru["y"] = 280;
FocusItem.push(dogru);
var yanlis = new Object();
yanlis["image"] = new Image();
yanlis.image.src = './images/odaklanma/level/'+RandomSoru+'/yanlis.png';
yanlis["x"] = xYanlis1;
yanlis["y"] = 280;
FocusItem.push(yanlis);
var yanlis2 = new Object();
yanlis2["image"] = new Image();
yanlis2.image.src = './images/odaklanma/level/'+RandomSoru+'/yanlis1.png';
yanlis2["x"] = xYanlis2;
yanlis2["y"] = 280;
FocusItem.push(yanlis2);
}
if(focusImageBackground.complete){
if(FocusItem[0].image.complete && FocusItem[1].image.complete && FocusItem[2].image.complete && FocusItem[3].image.complete)
drawFocus();
else
setTimeout(drawFocus,600);
}
else
focusImageBackground.onload=function(){
if(FocusItem[0].image.complete && FocusItem[1].image.complete && FocusItem[2].image.complete && FocusItem[3].image.complete)
drawFocus();
else
setTimeout(drawFocus,600);
}
function drawFocus(){
ftx.drawImage(focusImageBackground,0,0);
for (var i=0; i<FocusItem.length; i++){
FocusItem[i].image.onload=function(){
ftx.drawImage (FocusItem[i].image, FocusItem[i].x, FocusItem[i].y);
}
}
}
I'd suggest loading all your images, then when they are all done, you can call the rest of your code. I don't quite follow what you're trying to do with all the rest of your code, but here's a simple way to load an array of image URLs and know when they are done.
This is the general idea (I've left out lots of your code that has nothing to do with the central issue of knowing when all the images are loaded) and I've also tried to DRY up your code:
function createImagesNotify(srcs, fn) {
var imgs = [], img;
var remaining = srcs.length;
for (var i = 0; i < srcs.length; i++) {
img = new Image();
imgs.push(img);
img.onload = function() {
--remaining;
if (remaining == 0) {
fn(srcs);
}
};
// must set .src after setting onload handler
img.src = srcs[i];
}
return(imgs);
}
// here's your starting array of filenames
var fnames = ["soru.png", "dogru.png", "yanlis.png", "yanlis1.png"];
// insert your process to create RandomSoru here
var randomSoru = ....;
// build full urls array
var urls = [];
for (var i = 0; i < fnames; i++) {
urls.push('./images/odaklanma/level/' + RandomSoru + '/' + fnames[i]);
}
// load all images and call callback function when they are all done loading
var imgs = createImagesNotify(urls, function() {
// all images have been loaded here
// do whatever you want with all the loaded images now (like draw them)
});
This code is based on an earlier answer of mine here: Cross-browser solution for a callback when loading multiple images?
I'm trying to make a slideshow of pictures and send them to an another window. But after selecting images and pressing the button for showing slideshows, nothing happens. I'm using firebug to detect bugs and when I'm going wrong. But I'm not getting any error from firebug so I gotta ask you guys. This is my code.
var infoBox;
var formTag;
var imgUrlList;
var imgTextList;
var windVar;
var urlList;
var textList;
function init() {
var i;
infoBox = document.getElementsByClassName("outerBox");
for (i=0; i<infoBox.length; i++) {
infoBox[i].onmouseover = showInfoBox;
infoBox[i].onmouseout = hideInfoBox;
}
formTag = document.getElementsByTagName("input");
for (i=0; i<formTag.length; i++) {
formTag[i].onclick = checkedBox;
}
windVar = null;
imgTextList = [];
imgUrlList = [];
}
window.onload = init;
function showInfoBox() {
var showInfo;
showInfo = this.getElementsByClassName("innerBox")[0];
showInfo.style.visibility = "visible";
}
function hideInfoBox() {
var hideInfo;
hideInfo = this.getElementsByClassName("innerBox")[0];
hideInfo.style.visibility = "hidden";
}
function checkedBox() {
var ImgNode, ImgTag;
for (i=0; i<formTag.length; i++) {
imgNode = this.parentNode.parentNode.firstChild;
imgTag = imgNode.nextSibling
if (this.checked) {
imgTag.className = "markedImg";
}
else {
imgTag.className = "unmarkedImg";
}
}
}
function slideShowBtn() {
var url, i, filename;
imgUrlList.length = 0;
imgTextList.length = 0;
for (i=0; i<formTag.length; i++) {
if (formTag.checked) {
url = infoBox.firstChild.getElementsByTagName("img")[i].src;
filename = infoBox.firstChild.getElementsByTagName("span")[i].src;
imgUrlList.push(url);
imgTextList.push(filename);
}
else break;
}
newWindow(700,600,"slideshow.htm");
}
function newWindow(width,height,fileName) {
var windProporties;
windProporties = "top=100, left=100,toolbar=no,status=no,menubar=no,scrollbars=no,resizable=no,width=" + width + ",height=" + height;
if (windVar != null) if (windVar.closed == false) windVar.close();
windVar = window.open(fileName,"bildspel",windProporties);
}
The formTag variabel is from a checkbox-input-tag. And it's from that I decide which pictures are selected and will be moved to the new page. ImgTextList and imgUrlList are global variables that'll also be in the next window. infoBox is a reference to a div class which is called OuterBox and inside it is an another div-class named innerBox, it's in the innerBox classdiv which the img and span-tags are. The code for the slideshow is already written and I'm just writing code for sending the variables to it.
Edit: I should have been a little more informative. But here's the code for the slideshow part where window.opener is present. And I've added all the remaining code that's above. How do you embed files?
// JavaScript for the slideshow page
// ----- Global variables -----
var imgUrlList = window.opener.imgUrlList; // Array with filenames of selected images. Initialized to an empty array.
var imgTextList = window.opener.imgTextList; // Array with image texts of selected images. Initialized to an empty array.
var slideshowMenu = null; // Reference to the image menu.
var slideshowImg = null; // Reference to the slideshow img tag.
var slideshowText = null; // Reference to the tag for the image text.
// ---- Create the image menu and show the first image. Also attach event handlers. ----
function initSlideshow() {
// Create a image list from the content of the variable imgUrlList
var HTMLcode = "<select id='imgMenu'>";
for (var i=0; i<imgTextList.length; i++) {
HTMLcode += "<option>" + imgTextList[i] + "</option>";
} // End for
HTMLcode += "</select>";
document.getElementById("iMenu").innerHTML = HTMLcode; // Add the select and option tags to the HTML code
slideshowMenu = document.getElementById("imgMenu"); // Save a reference to the menu's select tag
slideshowMenu.selectedIndex = 0; // Select the first option in the menu
slideshowImg = document.getElementById("slideshowBox").getElementsByTagName("img")[0];
slideshowText = document.getElementById("slideshowBox").getElementsByTagName("div")[0];
// Show the first image
slideshowImg.src = imgUrlList[0];
slideshowText.innerHTML = imgTextList[0];
// Attach event handlers
var slideshowButtons = document.getElementById("slideshowForm").getElementsByTagName("input");
slideshowButtons[0].onclick = showPrevImage;
slideshowButtons[1].onclick = showNextImage;
slideshowMenu.onchange = showSelectedImage;
} // End initSlideshow
window.onload = initSlideshow;
// ---- Show previous image in the list (menu) ----
function showPrevImage() {
var ix = slideshowMenu.selectedIndex; // Index for the current image
if (ix > 0) { // If it's not already the first image
slideshowMenu.selectedIndex = ix-1;
slideshowImg.src = imgUrlList[ix-1];
slideshowText.innerHTML = imgTextList[ix-1];
}
} // End showPrevImage
// ---- Show next image in the list (menu) ----
function showNextImage() {
var ix = slideshowMenu.selectedIndex; // Index for the current image
if (ix < slideshowMenu.length-1) { // If it's not already the last image
slideshowMenu.selectedIndex = ix+1;
slideshowImg.src = imgUrlList[ix+1];
slideshowText.innerHTML = imgTextList[ix+1];
}
} // End showNextImage
// ---- Show selected image in the list (menu) ----
function showSelectedImage() {
var ix = slideshowMenu.selectedIndex; // Index for the selected image
slideshowImg.src = imgUrlList[ix];
slideshowText.innerHTML = imgTextList[ix];
} // End showSelectedImage
Um, you never do anything to send it. Either pass it as a querystring parameter or have the child reference a global variable in the opener.
var foo = window.opener.imgUrlList;
I'm trying to create a lightbox for my site, and I want it to load all the images from a given directory with a filename like image#.jpg.
This is the code I have:
for(var i=0; i<1000; i++)
{
var filename = "images/image"+i+".jpg";
$.get(filename)
.done(function() {
$('#lightbox').append('<img src="placeholder.gif">');
})
.fail(function() {
i=1000; //ugh
});
}
It kind of works, but only tries to load image1000.jpg.
Also, is there a better way to do something like this? I'm sure saying 'do this a ton of times and stop when I manually change the for loop counter' is frowned on.
If your image names are sequential like your said, you can create a loop for the names, checking at every iteration if image exists - and if it doesn't - break the loop:
var bCheckEnabled = true;
var bFinishCheck = false;
var img;
var imgArray = new Array();
var i = 0;
var myInterval = setInterval(loadImage, 1);
function loadImage() {
if (bFinishCheck) {
clearInterval(myInterval);
alert('Loaded ' + i + ' image(s)!)');
return;
}
if (bCheckEnabled) {
bCheckEnabled = false;
img = new Image();
img.onload = fExists;
img.onerror = fDoesntExist;
img.src = 'images/myFolder/' + i + '.png';
}
}
function fExists() {
imgArray.push(img);
i++;
bCheckEnabled = true;
}
I'm studying javascript for the first time and I've some doubt: I have two arrays; the first one contain the image of a person, the second one his personal informations (the arrays' length is the same because they contain the same number of people). I'd like to write the content in my page so print the image and the infos of the first user, then the image and the infos of the second and so on...
How can I do it?
this is the code:
function jsonCard()
{
var richiestaCard = new XMLHttpRequest();
richiestaCard.onreadystatechange = function()
{
if(richiestaCard.readyState == 4)
{
var objectcardjson = {};
window.arrayCard= []; //creazione dell'array che conterrĂ le cards
objectcardjson = JSON.parse(richiestaCard.responseText);
arrayCard = objectcardjson.cards; //the first array
}
}
richiestaCard.open("GET", "longanocard.json", true);
richiestaCard.send(null);
}
function jsonEntity()
{
var richiestaEntity = new XMLHttpRequest();
richiestaEntity.onreadystatechange = function()
{
if(richiestaEntity.readyState == 4)
{
var objectentityjson = {};
window.arrayEntity= []; //creazione dell'array che conterrĂ le entity
objectentityjson = JSON.parse(richiestaEntity.responseText);
arrayEntity = objectentityjson.cards; //the second array
}
}
richiestaEntity.open("GET", "longano.json", true);
richiestaEntity.send(null);
}
function displayArrayCards()
{
jsonCard();
jsonEntity();
var inizioTag = "<img src=";
var fineTag = "\>";
for(i = 0; i < arrayCard.length; i++)
{
...
}
}
I'd like to have the image and then the infos (for the first user), the image and the infos for the second and so on all included in a div.
Try something along the lines of
function displayArrayCards()
{
jsonCard();
jsonEntity();
var wrapper = document.getElementById('div you want to put all of these users into');
for(i = 0; i < arrayCard.length; i++)
{
var userDiv = document.createElement('div');
var cardImg = document.createElement('img');
img.src = arrayCard[i];
/** Set other attributes for img **/
var entityDiv = document.createElement('div');
entityImg.innerHTML = arrayEntity[i];
/** Set other attributes for div **/
userDiv.appendChild(cardImg);
userDiv.appendChild(entityDiv);
wrapper.appendChild(userDiv);
}
}
Honestly there are a lot of ways to do this. Above is simply what I would do.