Psionman
Psionman

Reputation: 3677

how to get the image name on click in javascript

I am creating a grid of images and I would like to return the image name when the user clicks on the image. My code always returns the name of the last image

(I can work around this using the index but I would like to know what is going on)

last_image = -1
var next_button = document.getElementById('next-image');
var all_button = document.getElementById('all-images');
document.addEventListener("DOMContentLoaded", (event) => {
  allImages()
});

function allImages() {
  for (let index = 0; index < 5; index++) {
    var canvas_name = "display-" + index
    var image_name = 'image_' + index + '.png'
    drawImage(canvas_name, image_name)
    var cell = document.getElementById('display-' + index)
    cell.onclick = function() {
      cellClick(index, image_name)
    };
  }
}

function drawImage(canvas_name, image) {
  let imageObj = new Image();
  imageObj.name = canvas_name;
  imageObj.onload = function() {
    let canvas = document.getElementById(this.name);
    let ctx = canvas.getContext('2d');
    ctx.drawImage(this, 0, 0);
  };
  imageObj.src = image;
}

function cellClick(index, image_name) {
  console.log(index, image_name)
}
<div class="display-grid">
  <span><canvas class="canvas" id="display-0"></canvas></span>
  <span><canvas class="canvas" id="display-1"></canvas></span>
  <span><canvas class="canvas" id="display-2"></canvas></span>
  <span><canvas class="canvas" id="display-3"></canvas></span>
  <span><canvas class="canvas" id="display-4"></canvas></span>
</div>

Upvotes: 2

Views: 659

Answers (2)

Roko C. Buljan
Roko C. Buljan

Reputation: 206058

  • Store the src into the Canvas EL data-* attribute
  • Get all your canvas elements using Element.querySelectorAll()
  • Iterate your Canvas Elements using Nodelist.prototype.forEach()
  • PS: instead of using DOMContentLoaded just make sure to always use <script> tags right before the closing </body> tag (so not in HEAD or disseminated around your document).

const canvases = document.querySelectorAll('.display-grid canvas');

document.addEventListener("DOMContentLoaded", allImages);

function allImages() {
  canvases.forEach((EL, i) => {
    EL.dataset.src = `https://via.placeholder.com/100/?text=Image-${i}`;
    drawImage(EL, i);
    EL.addEventListener("click", () => canvasClick(EL, i));
  });
}

function drawImage(EL, i) {
  const img = new Image();
  img.addEventListener("load", () => {
    const ctx = EL.getContext('2d');
    ctx.canvas.width = img.naturalWidth;
    ctx.canvas.height = img.naturalHeight;
    ctx.drawImage(img, 0, 0);
  })
  img.src = EL.dataset.src
}

function canvasClick(EL, i) {
  console.log(i, EL.dataset.src);
}
canvas {
  border: 3px solid red;
}
<div class="display-grid">
  <span><canvas class="canvas"></canvas></span>
  <span><canvas class="canvas"></canvas></span>
  <span><canvas class="canvas"></canvas></span>
  <span><canvas class="canvas"></canvas></span>
  <span><canvas class="canvas"></canvas></span>
</div>

Upvotes: 0

Professor Abronsius
Professor Abronsius

Reputation: 33813

Unless you really need to add numerically indexed IDs to each of the canvas elements you can remove them. They will have an index when processed using querySelectorAll which can then be used, if you wish, to build the image src (ie: image_0.png etc

By passing the canvas as an argument to drawImage and returning the canvas you can assign the event listener within allImages and access the newly assigned name of the canvas - effectively the src of the image passed to the drawImage` method.

For ease of viewing rather than blank images I used a placeholder but you'll see the commented out original. In the original code the clickhandler, when invoked, used the last index because the loop had already been run rather than picking an index from the current clicked item.

document.addEventListener("DOMContentLoaded", ()=>{
    const next_button=document.getElementById('next-image');
    const all_button=document.getElementById('all-images');
    const col=document.querySelectorAll('.display-grid span canvas');
    
    const allImages=function(){
        col.forEach((cnvs,i)=>{
            //let src='image_'+i+'.png';
            let src='http://placekitten.com/452/450?image='+i;
            cnvs=drawImage( cnvs, src );
            cnvs.addEventListener('click',function(e){
                alert(this.name)
            })
        })
    }
    
    function drawImage( canvas, src ) {
        let oImg = new Image();
        oImg.onload = function() {
            canvas.name=src;
            let ctx = canvas.getContext('2d');
            ctx.drawImage( this, 0, 0 );
        };
        oImg.src = src;
        return canvas;
    }
    
    allImages()
});
span{display:block;border:1px solid red;padding:1rem;margin:0.25rem auto;}
canvas{border:1px solid black;margin:1rem;}
img{border:1px solid blue;}
<div class="display-grid">
  <span><canvas></canvas></span>
  <span><canvas></canvas></span>
  <span><canvas></canvas></span>
  <span><canvas></canvas></span>
  <span><canvas></canvas></span>
</div>

<input type='button' id='next-image' value='Next' />
<input type='button' id='all-images' value='All' />

Upvotes: 2

Related Questions