Get id of image from canvas mouse-down event

rather than show what I’ve tried, here are some code snippets. How do I get the image id on mousedown in HTML5?
(note: don’t know why the comments are not alligned, there are no tabs in the source)


<!DOCTYPE html>
...
  <canvas id='canvas' width='600' height='300'>
    Canvas not supported
  </canvas>

  <script type="text/javascript">
// ----- Globals ----- 

  var canvas = document.getElementById('canvas'),
        context = canvas.getContext('2d');
        canvas.addEventListener("mousedown", GetSourceIndex, false);
...
  function DisplayCard(card, xPos, yPos){                 // show card on canvas
       var img = new Image();
       img,id="someid";                                                // IMAGE ID ASSIGNED HERE
       img.src = card.ordinal + card.suit + ".gif";          // build file name
       img.onload = function() {                                    // wait for image to load
          context.drawImage(img, xPos, yPos);            // place it on canvas
       } // end onload
  } // end function DisplayCard

...
  function GetSourceIndex(e) {                                  // mousedown event (card to move)
// WANT TO GET THE image's ID HERE.
...

(the img.id=“someid” is simply to show where I would build then assign an id)

I’m expecting there is an additional argument to add to the addEventListener and/or argument to the GetSourceIndex function. But so far, despite intense Googling, I’ve had no luck in finding the solution…

grNadpa

My answer is based on code provided here: http://stackoverflow.com/questions/10449890/detect-mouse-click-location-within-canvas

First you need a utility function which gets the canvas coordinates of the mouse pointer:

stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingLeft'], 10)      || 0;
stylePaddingTop  = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingTop'], 10)       || 0;
styleBorderLeft  = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderLeftWidth'], 10)  || 0;
styleBorderTop   = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderTopWidth'], 10)   || 0;
// Some pages have fixed-position bars (like the stumbleupon bar) at the top or left of the page
// They will mess up mouse coordinates and this fixes that
var html = document.body.parentNode;
htmlTop = html.offsetTop;
htmlLeft = html.offsetLeft;


function getMouse(e, canvas) {
    var element = canvas, offsetX = 0, offsetY = 0, mx, my;

    if (element.offsetParent !== undefined) {
        do {
            offsetX += element.offsetLeft;
            offsetY += element.offsetTop;
        } while ((element = element.offsetParent));
    }

    offsetX += stylePaddingLeft + styleBorderLeft + htmlLeft;
    offsetY += stylePaddingTop + styleBorderTop + htmlTop;

    mx = e.pageX - offsetX;
    my = e.pageY - offsetY;

    return {x: mx, y: my};
}

Then there is a handler for the mousedown event, which gets the mouse position (using the above function) and then loops over an array of placed cards to see if any of them are under the pointer:

canvas.addEventListener("mousedown", getCard, false);

function getCard(e) {
    var mouse = getMouse(e, canvas).
        l = cardsPlayed.length;

    for (var i = 0; i < l; i++) {
        if ((mouse.x > cardsPlayed[i].x && mouse.x < cardsPlayed[i].x + xOffset)
            && (mouse.y > cardsPlayed[i].y && mouse.y < cardsPlayed[i].y + yOffset)) {

            console.log(cardsPlayed[i].card);
            break;
        }
    }
}

and finally you need some code to create an array with the x and y coordinates of each card. For testing, I did this:

for (var i = 1; i < 6; i++) {
    var card = GetNextCard();
    DisplayCard(card, xOffset * i, yOffset);
    cardsPlayed.push({ card: card, x: xOffset * i, y: yOffset });
}

but you could just as easily store any data you want along with the coordinates.

Agree that storing the data is the better option.

Thank you for the thorough reply.

My script has a function which does calculate the proper offset (within the major browsers).However, it only works for two rows at the moment unless each row consumes an entire card height (yOffset).

	function GetPlayedCardsOffset(e, xOffset, yOffset){ // Calculate Index to playedCards[]
      if (e.x != undefined && e.y != undefined) {       // browser recognize e.x e.y?
         x = e.x;                                       //  yes: capture position
         y = e.y;
      }  else {                                         //  no: e.g. Firefox
         x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
         y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
      } // end if-else

		if(y < 2*yOffset) { 						// only draw card is 1st row
			return 0;								// draw card is in playedCards[0]
		} // end if
		return(Math.floor(x/xOffset));              // card is playedCards[quotient]
	} // end function GetPlayedCardsOffset

In planning to add rows, I plan to partially overlay each row with the next row showing only the top of the card “underneath”.That complicates how this function would convert the y coordinate. I thought rather than make this function a bit more cumbersome, I could “just” assign an id to each image and retrieve it on a mouse down event (very much as pulling the clientX and clientY).

Your reply shows the error of my musings.

Interestingly, though, as I recall, Firebug did show the id I assigned in the lower-right data panel as I stepped through.

Again, thanks.for your continued patience and instruction.

grNadpa