Why can't i access the x variable of the bitmap? (javascript) - javascript

I'm trying to loop through 3 images in my array and add it to the stage (using easelJS). I want to position it as well. When I try to access the images in the array i get an error saying that the I can't set x of undefined. Why can't the x variable of the easeljs Bitmap be accessed?
function displayPosters() {
getPosters(); //get all images and assign it to designated array
console.log(frontPosters);
console.log(frontPosters.length);
if(currentCat == Category.HOME) { //if current category is HOME
for(var i = 0; i < frontPosters.length; i++) { //loop through posters
frontPosters[i].x = 40; //set x position for testing, also where error occurs
stage.addChild(frontPosters[i]); //add poster to stage
}
}
}
here is the code for loading and pushing those images into the frontPosters arrray.
var frontPosters = new Array(3);
function getPosters() {
var games = new Image(); //create 3 images
var apps = new Image();
var aboutme = new Image();
games.onload = function() { //add image to frontImages array on load
var gamesPost = new createjs.Bitmap(games);
frontPosters[0] = gamesPost;
};
apps.onload = function() {
var appPost = new createjs.Bitmap(apps);
frontPosters[1] = appPost;
};
aboutme.onload = function() {
var amPost = new createjs.Bitmap(aboutme);
frontPosters[2] = amPost;
};
games.src = "images/assets/posters/games_poster.jpg";
apps.src = "images/assets/posters/apps_poster.jpg";
aboutme.src = "images/assets/posters/aboutme_poster.jpg";
}

Using for(poster in frontPosters) is bad practice, because you're actually iterating over the Array Object and not the values (a.k.a. the Array itself). Use for(var i=0; i<frontPosters.length; i++) instead. It's the easiest solution, IMO.
for(var i = 0; i < frontPosters.length; i++) { //loop through posters
frontPosters[i].x = 40; //set x position for testing, also where error occurs
stage.addChild(frontPosters[i]); //add poster to stage
}
Edit
I think you are dealing with a race-condition. You are going over your array before all images were loaded. By setting var frontPosters = new Array(3); you automatically set three values to undefined which are pushed into the new array.
You should check that all images were loaded before proceeding with the script.
Here's an idea for you. Set a callback that will run only after the third image was loaded.
var frontPosters = new Array(3);
function getPosters(callback) {
var games = new Image(),
apps = new Image(),
aboutme = new Image(),
loaded = 0;
games.onload = function() {
frontPosters[0] = new createjs.Bitmap(this);
if (++loaded === 3) callback();
};
apps.onload = function() {
frontPosters[1] = new createjs.Bitmap(this);
if (++loaded === 3) callback();
};
aboutme.onload = function() {
frontPosters[2] = new createjs.Bitmap(this);
if (++loaded === 3) callback();
};
games.src = "images/assets/posters/games_poster.jpg";
apps.src = "images/assets/posters/apps_poster.jpg";
aboutme.src = "images/assets/posters/aboutme_poster.jpg";
}
function displayPosters() {
getPosters(function() {
if(currentCat == Category.HOME) { //if current category is HOME
for(var i = 0; i < frontPosters.length; i++) { //loop through posters
frontPosters[i].x = 40; //set x position for testing, also where error occurs
stage.addChild(frontPosters[i]); //add poster to stage
}
}
}); //get all images and assign it to designated array, only after all images were loaded
}

Related

Why can't I get my images to appear in table cells/nodes.. maybe I can get some closure?

I want to add a new image in each cell of the new table and give it the same source as the old table, and then make it clickable. Firstly, I did this:
function showData() {
if (localStorage.getItem(name) !== null) {
var showme = localStorage.getItem(name);
alert("I got the table");
var newTable = document.createElement('table');
newTable.innerHTML = showme;
newTable.id = "newTable";
newNumRows = newTable.getElementsByTagName('tr').length;
newNumCells = newTable.getElementsByTagName('td').length;
newNumCols = newNumCells / newNumRows;
alert(newNumRows);
alert(newNumCells);
alert(newNumCols);
var newImages = newTable.getElementsByTagName('img');
for (var i = 0; i < newImages.length; i += 1) {
var picSource = newImages[i]['src'];
console.log(picSource);
}
function addNewImage(newNumCols) {
var newImg = new Image();
newImg.src = picSource;
col.appendChild(newImg);
newImg.onclick = function() {
alert("WOW");
};
}
for (r = 0; r < newNumRows; r++) {
row = newTable.insertRow(-1);
for (c = 0; c < newNumCols; c++) {
col = row.insertCell(-1);
addNewImage(newNumCols);
}
}
var showIt = document.getElementById('holdTable');
showIt.appendChild(newTable);
}
}
This works to a certain extent, but, unfortunately, only the last image was displaying. So, I did a bit of looking around and I think it has to do with closure (apologies for any duplication), but it's a concept I am really struggling to understand. So then I tried this:
function showData() {
if (localStorage.getItem(name) !== null) {
hideTaskForm();
var showme = localStorage.getItem(name);
var oldTable = document.createElement('table');
oldTable.innerHTML = showme;
newTable = document.createElement('table');
newTable.id = "newTable";
var i, r, c, j;
newNumRows = oldTable.getElementsByTagName('tr').length;
newNumCells = oldTable.getElementsByTagName('td').length;
newNumCols = newNumCells / newNumRows;
var newTableCells = newTable.getElementsByTagName('td');
var getImages = oldTable.getElementsByTagName('img');
for (r = 0; r < newNumRows; r++) {
row = newTable.insertRow(-1);
for (c = 0; c < newNumCols; c++) {
makeNodes = row.insertCell(-1);
}
}
for (var j = 0; j < newTableCells.length; j++) {
var theNodeImage = document.createElement("img");
newTableCells[j].appendChild(theNodeImage);
alert(newTableCells[j].innerHTML); //This gives me img tags
}
for (i = 0; i < getImages.length; i += 1) {
var oldSource = getImages[i]['src']; //gets the src of the images from the saved table
console.log(oldSource);
//alert(oldSource);//successfully alerts the image paths
var newPic = new Image(); //creates a new image
(function(newPic, oldSource) {
newPic.src = oldSource;
alert(newPic.src); //gives the same image paths
newTable.getElementsByTagName('img').src = newPic.src; //This doesn't work - table is blank???
})(newPic, oldSource);
}
var showIt = document.getElementById('holdTable');
showIt.appendChild(newTable);
}
}
Now, this doesn't throw any errors. However, nor does it fill the table. It does give me the source and I think I have created the new image objects to attach to the img tags in the newTableCells, but the table is showing up blank. I don't know where I am going wrong. All help really welcome.
Note: Even as a hobbyist, even I know there are probably tons of more efficient ways to do this, but I purposely did it this way to try and help me understand the logic of each step I was taking.
In your code you have:
var newImages = newTable.getElementsByTagName('img');
for (var i = 0; i < newImages.length; i += 1) {
var picSource = newImages[i]['src'];
console.log(picSource);
}
At the end of this, picSource has the value of the last image's src attribute. Then there is:
function addNewImage(newNumCols) {
var newImg = new Image();
newImg.src = picSource;
col.appendChild(newImg);
newImg.onclick = function() {
alert("WOW");
};
}
A value is passed to newNumCols but not used in the function. The value of picSource comes from the outer execution context and is not changed, so it's still the last image src from the previous for loop.
for (r = 0; r < newNumRows; r++) {
row = newTable.insertRow(-1);
for (c = 0; c < newNumCols; c++) {
col = row.insertCell(-1);
addNewImage(newNumCols);
}
}
This loop just keeps calling addNewImage with a single parameter that isn't used in the function, so you get the same image over and over.
For the record, the addNewImage function does have a closure to picSource, but it also has a closure to all the variables of the outer execution contexts. This isn't the issue, though it perhaps masks the fact that you aren't setting a value for picSource on each call, so you get the left over value from the previous section of code.
You haven't provided any indication of the content of showme, so it's impossible to determine if this approach will work at all.
Note
Where you have:
var showme = localStorage.getItem(name);
alert("I got the table");
var newTable = document.createElement('table');
newTable.innerHTML = showme;
newTable.id = "newTable";
IE does not support setting the innerHTML property of table elements, though you can create an entire table as the innerHTML of some other element and set the innerHTML of a cell (tr, th). If you want to use this approach, consider:
var div = document.createElement('div');
div.innerHTML = '<table id="newTable">' + showme + '<\/table>';
var newTable = div.firstChild;

Having trouble with image preload code

I have this object constructor function that has a preload method for preloading
rollover images pairs.
So, I have two questions:
1: why is the alert dialog just doing 'STR: ' with no data attached? (this type of problem is generally due to my blindness.
2: is it possible to treat the this.buttons_on and this.buttons_off as objects in that instead of
a numerical index, use a sting index so the rollover event handler does not need to loop through
the buttons_on and buttons_off arrays to get the one that should be swapped out;
function _NAV()
{
this.list_off = [];
this.list_on = [];
this.buttons_on = [];
this.buttons_off = [];
this.buttons_all = {}; // .on and .off
this.button_events = {};
this.img = true;
this.img_ids = {}
this.preLoad = function()
{
if(document.images) //creates image object array for preload.
{
var STR = '';
for(var i = 0; i < list_off.length; i++)
{
var lab_on = list_on[i].replace('\.jpg', '');
var lab_off = list_off[i].replace('\.jpg', '');
STR += lab_on+'||'+lab_off+"\n";
this.buttons_on[i] = new Image();
this.buttons_on[i].src = srcPath+list_on[i];
this.bottons_on[i].id = img_ids[i];
this.buttons_off[i] = new Image();
this.buttons_off[i].src = srcPath+list_off[i];
this.buttons_off[i].id = img_ids[i];
}
alert("STR: "+STR);
}
else
{
this.img = false
}
}
//// ...etc...
Here is the call before the onload event fires
var rollover = new _NAV();
rollover.preLoad();
Here are the arrays used
var srcPath = '../nav_buttons/';
var list_off = new Array(); // not new Object;
list_off[0] = "bio_off.jpg";
list_off[1] = "cd_off.jpg";
list_off[2] = "home_off.jpg";
list_off[3] = "inst_off.jpg";
list_off[4] = "photo_off.jpg";
list_off[5] = "rev_off.jpg";
list_off[6] = "samp_off.jpg";
var list_on = new Array();
list_on[0] = "bio_on.jpg";
list_on[1] = "cd_on.jpg";
list_on[2] = "home_on.jpg";
list_on[3] = "inst_on.jpg";
list_on[4] = "photo_on.jpg";
list_on[5] = "rev_on.jpg";
list_on[6] = "samp_on.jpg";
var img_ids = new Array();
Thanks for time and attention.
1:
Try PHPGlue's suggestion and add this. in front of all your member variables (this.list_on, this.list_off, this.img_ids)
You also have a typo on one line. bottons_on is misspelled.
this.bottons_on[i].id = img_ids[i];
2:
Yes, you can use a string as an index. Just make buttons_on and buttons_off objects instead of arrays.
function _NAV()
{
this.buttons_on = {};
this.buttons_off = {};
// For example:
this.buttons_off[lab_off] = new Image();
}

How to get symbol layer on paperjs?

This code draws 30 led image to canvas.How can i select and change source of led symbol onMouseDown event?
var raster = new Raster();
raster.source="/PNG/Red.png";
var sembol = new Symbol(raster);
for (var i = 0; i < 30; i++) {
var bura = sembol.place();
bura.position = Point.random() * view.size;
bura.scale(0.5);
};
Assuming that you have a set of raster objects in your view, like a row of buttons, the following should work:
function onMouseDown(event) {
if (event.item && event.item.type === 'raster') {
sembol.definition = event.item.clone();
}
}
Since an item is removed from the view when defined as a symbol, a clone is passed instead.
You can add onMouseDown handler directly to a PlacedSymbol, in this case bura:
for (var i = 0; i < 30; i++) {
var bura = sembol.place();
bura.position = Point.random() * view.size;
bura.scale(0.5);
bura.onMouseDown = function () {
// you can use the closure variable `raster`
raster.source = "/PNG/Blue.png";
// or, if you don't have acces to `raster`:
this.symbol.definition.source = "/PNG/Blue.png";
}
}
Hope that this does what you expected.

How do I empty global arrays used in a pop up slideshow?

I've created a program where you can choose a set of images by checking checkboxes. The image URL's and the alt-texts are stored in two arrays. When clicking av button on the HTML-page you open a new window that calls on the arrays with window.opener.
When closing the new window I would like to empty the arrays. Otherwise the pictures chosen in the first round are displayed in the slideshow when opening it the second time. I understand you can empty arrays by this method: array.length= 0;
But where do I add the code? I'm quite lost. I'm pasting the code, perhaps someone can give me a hand.
var imgUrlList = [], imgTextList = [], //These arrays need to be emptied
windVar = null;
function init() {
var tags, i, openWindow;
tags = document.getElementsByClassName("unmarkedImg");
openWindow = document.getElementById("slideShowBtn");
openWindow.onclick = savePicsForSlideshow;
for (i = 0; i < tags.length; i++) {
tags[i].parentNode.onmouseover = showLargePict;
tags[i].parentNode.onmouseout = hideLargePict;
}
}
window.onload = init;
function showLargePict() {
var largePictTagDiv = this.getElementsByClassName("innerBox")[0];
var largePictTagParentDiv = largePictTagDiv.parentNode;
var imgTag = largePictTagParentDiv.getElementsByTagName('img')[0];
var checkBoxlargePict = largePictTagDiv.getElementsByTagName('input')[0];
if (checkBoxlargePict.checked)
imgTag.className = "markedImg";
else imgTag.className = "unmarkedImg";
largePictTagDiv.style.visibility = "visible";
} // End showLargePict
function hideLargePict() {
var largePictTag;
largePictTag = this.getElementsByClassName("innerBox")[0];
largePictTag.style.visibility = "hidden";
}
function savePicsForSlideshow() {
var innerBoxes = document.getElementsByClassName("innerBox");
for (i = 0; i < innerBoxes.length; i++) {
checkBoxlargePict = innerBoxes[i].getElementsByTagName('input')[0];
if (checkBoxlargePict.checked) {
var imgTagSrc = innerBoxes[i].getElementsByTagName('img')[0].src;
imgUrlList.push(imgTagSrc);
var spanTagText = innerBoxes[i].getElementsByTagName('span')[0].innerHTML;
imgTextList.push(spanTagText);
}
}
if (imgTextList.length > 0) {
newWindow(500, 600, "slideshow.htm");
}
}
function newWindow(width, height, filename) {
var windowProperties;
windowProperties = "top=100,left=100,toolbar=no,location=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, "", windowProperties);
}
Please excuse my programming and English grammar shortcomings. I'm new to javascript.
//Henrik, Göteborg, Sweden.
At the beginning of the savePicsForSlideshow function, empty out each array.
imgUrlList.length = 0;
imgTextList.length = 0;
You can check if thw window is close with the property closed of the object window
if(window.closed)
{
array.length = 0;
}

Showing an image from an array of images - Javascript

I have a large image which is shown on my homepage, and when the user clicks the "next_img" button the large image on the homepage should change to the next image in the array.
However, the next arrow when clicked does nothing, and the main image on the homepage does not change.
I need to do this in javascript.
In the HTML:
<!--Main Content of the page -->
<div id="splash">
<img src="images/img/Splash_image1.jpg" alt="" id="mainImg">
</div>
<div id="imglist">
<img src="images/next_img.png" alt="">
And then in the javascript file:
var imgArray = new Array();
imgArray[0] = new Image();
imgArray[0].src = 'images/img/Splash_image1.jpg';
imgArray[1] = new Image();
imgArray[1].src = 'images/img/Splash_image2.jpg';
imgArray[2] = new Image();
imgArray[2].src = 'images/img/Splash_image3.jpg';
imgArray[3] = new Image();
imgArray[3].src = 'images/img/Splash_image4.jpg';
imgArray[4] = new Image();
imgArray[4].src = 'images/img/Splash_image5.jpg';
imgArray[5] = new Image();
imgArray[5].src = 'images/img/Splash_image6.jpg';
/*------------------------------------*/
function nextImage(element)
{
var img = document.getElementById(element);
for(var i = 0;i<imgArray.length;i++)
{
if(imgArray[i] == img)
{
if(i == imgArray.length)
{
var j = 0;
document.getElementById(element).src = imgArray[j].src;
break;
}
else
var j = i + 1;
document.getElementById(element).src = imgArray[j].src;
break;
}
}
}
Any help would be appreciated. Thanks.
Just as Diodeus said, you're comparing an Image to a HTMLDomObject. Instead compare their .src attribute:
var imgArray = new Array();
imgArray[0] = new Image();
imgArray[0].src = 'images/img/Splash_image1.jpg';
imgArray[1] = new Image();
imgArray[1].src = 'images/img/Splash_image2.jpg';
/* ... more images ... */
imgArray[5] = new Image();
imgArray[5].src = 'images/img/Splash_image6.jpg';
/*------------------------------------*/
function nextImage(element)
{
var img = document.getElementById(element);
for(var i = 0; i < imgArray.length;i++)
{
if(imgArray[i].src == img.src) // << check this
{
if(i === imgArray.length){
document.getElementById(element).src = imgArray[0].src;
break;
}
document.getElementById(element).src = imgArray[i+1].src;
break;
}
}
}
Here's a somewhat cleaner way of implementing this. This makes the following changes:
The code is DRYed up a bit to remove redundant and repeated code and strings.
The code is made more generic/reusable.
We make the cache into an object so it has a self-contained interface and there are fewer globals.
We compare .src attributes instead of DOM elements to make it work properly.
Code:
function imageCache(base, firstNum, lastNum) {
this.cache = [];
var img;
for (var i = firstNum; i <= lastnum; i++) {
img = new Image();
img.src = base + i + ".jpg";
this.cache.push(img);
}
}
imageCache.prototype.nextImage(id) {
var element = document.getElementById(id);
var targetSrc = element.src;
var cache = this.cache;
for (var i = 0; i < cache.length; i++) {
if (cache[i].src) === targetSrc) {
i++;
if (i >= cache.length) {
i = 0;
}
element.src = cache[i].src;
return;
}
}
}
// sample usage
var myCache = new imageCache('images/img/Splash_image', 1, 6);
myCache.nextImage("foo");
Some advantages of this more object oriented and DRYed approach:
You can add more images by just creating the images in the numeric sequences and changing one numeric value in the constructor rather than copying lots more lines of array declarations.
You can use this more than one place in your app by just creating more than one imageCache object.
You can change the base URL by changing one string rather than N strings.
The code size is smaller (because of the removal of repeated code).
The cache object could easily be extended to offer more capabilities such as first, last, skip, etc...
You could add centralize error handling in one place so if one image doesn't exist and doesn't load successfully, it's automatically removed from the cache.
You can reuse this in other web pages you develop by only change the arguments to the constructor and not actually changing the implementation code.
P.S. If you don't know what DRY stands for, it's "Don't Repeat Yourself" and basically means that you should never have many copies of similar looking code. Anytime you have that, it should be reduced somehow to a loop or function or something that removes the need for lots of similarly looking copies of code. The end result will be smaller, usually easier to maintain and often more reusable.
Also, when checking for the last image, you must compare with imgArray.length-1 because, for example, when array length is 2 then I will take the values 0 and 1, it won't reach the value 2, so you must compare with length-1 not with length, here is the fixed line:
if(i == imgArray.length-1)
This is a simple example and try to combine it with yours using some modifications. I prefer you set all the images in one array in order to make your code easier to read and shorter:
var myImage = document.getElementById("mainImage");
var imageArray = ["_images/image1.jpg","_images/image2.jpg","_images/image3.jpg",
"_images/image4.jpg","_images/image5.jpg","_images/image6.jpg"];
var imageIndex = 0;
function changeImage() {
myImage.setAttribute("src",imageArray[imageIndex]);
imageIndex = (imageIndex + 1) % imageArray.length;
}
setInterval(changeImage, 5000);
Here's your problem:
if(imgArray[i] == img)
You're comparing an array element to a DOM object.
<script type="text/javascript">
function bike()
{
var data=
["b1.jpg", "b2.jpg", "b3.jpg", "b4.jpg", "b5.jpg", "b6.jpg", "b7.jpg", "b8.jpg"];
var a;
for(a=0; a<data.length; a++)
{
document.write("<center><fieldset style='height:200px; float:left; border-radius:15px; border-width:6px;")<img src='"+data[a]+"' height='200px' width='300px'/></fieldset></center>
}
}

Categories

Resources