Here's the code. When I use context.drawImage directly in the imageObject.onload function, it draws the card on the canvas. But when I capture the drawImage into an array and later context.drawImage using the array I get nothing.

This is related to the problem you were having in the previous thread with the loop. When JavaScript does I/O (such as loading an image), it does so in a non-blocking fashion. This means that the rest of the program continues executing in the meantime, and an event is fired when loading is complete to allow you to take further action. This is why your code doesn't execute linearly.

This is related to the problem you were having in the previous thread with the loop. ... This is why your code doesn't execute linearly.

Lest you think I ignored your comments in that thread, I did go through the reference on closures you provided. Obviously, I did not understand it -- at least in the context of these timing issues.

.And, of course, I trust you recognize the code you provided to me.

Though I sort of understand why javascript would, for resource utilization optimization, choose to allow code to execute while waiting for another action to complete. But I thought the onload implemented function was supposed to delay the execution of the body of that anonymous function until the load completed..

Obviousy not ... and I once again resemble the south end of a north-going horse.

So, here's what I really want to do.

I want my GetNextCard (snippet below) to return a card object consisting of the card.ordinal (a value from 1 (ace) to 13 (king), the card.suit (enum "s", "h", "d" and"c") and card.face which is the image rendered for the suit-ordinal combination . (i.e. for Ace of Spades the ordinal is "1", the suit is "s" and the face is pulled from 1s.gif)

I would then place that object into an array, so that every time I add to that array, I can clear the canvas and rebuild a new one by iterating through that array.

function GetNextCard() {
if(cardsLeft < 1) return false;
// get a number between 1 and the number of remaining cards
i = Math.floor(Math.random() * cardsLeft) + 1;
var nextCard = deck[i]; // pull that card
deck[i] = deck[cardsLeft]; // replace that card with the last in the deck
--cardsLeft;
// here is where I would like to build my card object: nextCard [ordinal, suit, face]
return nextCard;
} // end function GetNextCard

But before I do that, I was simply trying to pull the image without displaying it on the canvas.

Is there hope?

fretburner
—
2013-10-24T11:45:04Z —
#4

Apologies if anything which follows appears to be patronising or labouring the point, I'm just trying to ensure my explanations are as clear and unambiguous as possible.

Grnadpa said:

Though I sort of understand why javascript would, for resource utilization optimization, choose to allow code to execute while waiting for another action to complete. But I thought the onload implemented function was supposed to delay the execution of the body of that anonymous function until the load completed..

You're absolutely right.. any function you assign to imageObj.onload will be executed at some later time (once the load has completed) and the rest of your script will continue to execute in the meantime. That's why when you call context.drawImage(cardsPlayed[0], 69, 10) from outside of the onload function it executes immediately (before the image has loaded and been assigned to the array), and so cardsPlayed is still an empty array at this point.

Grnadpa said:

So, here's what I really want to do.

I want my GetNextCard (snippet below) to return a card object consisting of the card.ordinal (a value from 1 (ace) to 13 (king), the card.suit (enum "s", "h", "d" and"c") and card.face which is the image rendered for the suit-ordinal combination . (i.e. for Ace of Spades the ordinal is "1", the suit is "s" and the face is pulled from 1s.gif)

I would then place that object into an array, so that every time I add to that array, I can clear the canvas and rebuild a new one by iterating through that array.

One way to tackle this would be to hand off responsibility for loading an image and adding it to the canvas to a separate function (which is essentially what we ended up with in the previous thread).

The code below is very similar to what you wanted to achieve, but rather than have each card object manage its own image, that is handled by the displayCard function so it can add the image to the canvas as soon as it's loaded. We also end up with an array, cardsPlayed, which contains the card objects dealt from the deck.

BTW, I chose not to use the "cardsPlayed.push(card);" as I am not sure I could reference a middle row in the table if I'm only allowed a "pull". Not likely, I know. But obviously I haven't had much luck with my assumptions about javascript.

fretburner
—
2013-10-25T23:05:51Z —
#7

I've copied and pasted your code pretty much as is (I just changed the path to the card images to match the location on my laptop) and it seems to work fine. I'm getting all the alert dialogs, and a single card, face down, displayed on the canvas.

By the way, as a more powerful alternative to using the alert() function for debugging, you might want to try the console.log() function. This will output everything to your browser's JS console (open with ctrl+shift+J in Chrome, ctrl+shift+k in Firefox, and F12 in Internet Explorer), which is easier than having to OK a load of alert pop-ups. As well as logging strings it also allows you to log objects and arrays to the console so you can inspect their contents.

Grnadpa
—
2013-10-26T01:09:31Z —
#8

This is apparently a firefox issue -- at least as it is installed on my Windows8 system. I'm running Firefox version 24. As you experienced, it works in Chrome and Explorer. So I don't feel quite so stupid.

The console.log() function certainly seems the better option.

Finally, what may clear up my mental fog -- what kind of situation would I want code to execute while my image is loading? As a mainframer who started out with wiring boards for unit record equipment, punched card readers and tape drives I understand buffering. And in multi-user environments I can understand multiprocessing strategies in the operating systems. But what kind of situation would benefit from the parallel process at the application level within a single client?

fretburner
—
2013-10-26T15:36:08Z —
#9

Grnadpa said:

This is apparently a firefox issue -- at least as it is installed on my Windows8 system. I'm running Firefox version 24. As you experienced, it works in Chrome and Explorer. So I don't feel quite so stupid.

Interestingly, if you swap out all the alert calls for console.log it seems to work in Firefox as well.. I'm not really sure why that makes the difference, but it does.

Grnadpa said:

Finally, what may clear up my mental fog -- what kind of situation would I want code to execute while my image is loading? As a mainframer who started out with wiring boards for unit record equipment, punched card readers and tape drives I understand buffering. And in multi-user environments I can understand multiprocessing strategies in the operating systems. But what kind of situation would benefit from the parallel process at the application level within a single client?

Well, with JS the most common scenario which benefits from this is making network requests to a remote server. If the script waited for each procedure to complete before continuing with the program, a slow connection would cause a noticable delay to the end-user.

In some modern JS applications, when the user deletes a record the request is dispatched to the server. The program makes the assumption that the request will be processed OK, and so removes the item from the user's screen before it receives a reply from the server (which could come some seconds after). This makes the application feel quick and responsive.