Yuki03280322
@Yuki03280322 (M.Y)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

JavaScriptで画像のIDを取得できない理由を知りたい

プログラミングを学び始めて、2ヶ月の初心者です。
至らない点には遠慮なくご指摘ただければ嬉しいです!

問題点・・JavaScriptでidを取得して変数に入れたいのだが、取得できない

Ruby on RailでJavaScriptを使用し、画像クリックで別の画像を表示するプログラムを作成しております。
HTMLで指定した画像のIDを取得し、その画像クリックでイベント発火させたいのですが、console.logで確認するとnullと表示されています。

発生している問題・エラー

e3473f72de4cff5c06abbd46dec0207c.jpg

consoleのnullには、左右に配置された画像に設定したidを表示させたいがnullになっている。
そのため,addEventListenerで画像クリックをイベント発火に設定することが出来ない。

該当するソースコード

index.html
<section class="section">
  <div class="content has-text-centered">
    <div class="title is-4">貴方の求める絵に近いのはどちらですか?</div>
  </div>
</section>

<div class="flex-box">
  <div class="thumnail-left-box">
  <ul class="thumnail-right-box flex-box">
  <li><div id="left-image"></div>
  <li><div id="right-image"></div>
  </ul>
</div>
matching.js
// const images = ["/assets/images/left-left.jpg", "app/assets/images/left-right.jpg", "app/assets/images/right-left.jpg", "app/assets/images/right-right.jpg"]

if(document.URL.match(/matchings/)){
  function changeImage(choice){
    if(choice == left){
      console.log("left");
    }
    if(choice == right){
      console.log("right");
    }
  };
  const leftImage = document.getElementById("left-image");
  console.log(leftImage)
  // leftImage.addEventListener("click", changeImage(left));

  const rightImage = document.getElementById("right-image");
  console.log(rightImage)
  // right.addEventListener("click", changeImage(right));
};
// document.getElementById("left").onclick = function(){
//   changeImage("left");
// };
// document.getElementById("right").onclick = function(){
//   changeImage("right");
//   };
application.js
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.

require("@rails/ujs").start()
// require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")
require("../matching")


// Uncomment to copy all static images under ../images to the output folder and reference
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
// or the `imagePath` JavaScript helper below.
//
// const images = require.context('../images', true)
// const imagePath = (name) => images(name, true)
application.scss
/*
 * This is a manifest file that'll be compiled into application.css, which will include all the files
 * listed below.
 *
 * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
 * vendor/assets/stylesheets directory can be referenced here using a relative path.
 *
 * You're free to add application-wide styles to this file and they'll appear at the bottom of the
 * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
 * files in this directory. Styles in this file should be added after the last require_* statement.
 * It is generally better to create a new file per style scope.
 *
 *= require_tree .
 *= require_self
 */

 @import "bulma";

 .main-image{
   height: 940px;
   background-image: url(home.jpg);
   background-repeat: no-repeat;
   background-size: contain;
 }

 #left-image{
   height: 400px;
   width: 500px;
   background-image: url(left-image.jpg);
   background-repeat: no-repeat;
   background-size: contain;
   text-align: center;
 }

#right-image{
  height: 400px;
  width: 500px;
  background-image: url(right-image.jpg);
  background-repeat: no-repeat;
  background-size: contain;
  text-align: center;
}

.flex-box {
  display: flex;
  justify-content: space-around;
  flex-wrap: wrap;
}

自分で試したこと

「要素取得方法にclass,selectorに変えて実行する」
結果として以下の表記がコンソールに出現しました。
matching.js:13 HTMLCollection []
と表示され様々な情報は取得できていたが、肝心のIDは取得できませんでした。
また、このままaddEventListenerを実行(matching.jsのconsole.log(leftImage)の下のコメントアウト処理)をすると、関数の引数にしたleftがreferenceErrorが発生。

matching.js:14 Uncaught ReferenceError: left is not defined
    at Object../app/javascript/matching.js (matching.js:14)
    at __webpack_require__ (bootstrap:19)
    at Object../app/javascript/packs/application.js (application.js:10)
    at __webpack_require__ (bootstrap:19)
    at bootstrap:83
    at bootstrap:83

selectorによる取得も同様の結果でした。

環境

ruby2.6.5
rails6.0.0
jquery等のJavaScriptライブラリは使用しておりません
CSSフレームワークにBulmaを採用しております

これくらいのことで質問するのは良くないと思い、昨日からやっておりましたが
解決の糸口が見えずご質問させて頂きました。
ご回答頂ければ幸いです。宜しくお願い致します。

0

1Answer

ひとつ考えられるのは「JavaScriptが実行された時にまだ要素が描画されていない」というのがあります。

こちらを参考にしてください。
【JavaScript】getElementByIdでnullが返ってきたときに確認すること

ブラウザのデベロッパーツールを使ってJavaScriptをデバッグ(ステップ実行)していくと分かりやすいと思います。
【Chrome Developer Tools】JavaScriptにブレークポイントを張ってデバッグをする方法

また、このままaddEventListenerを実行(matching.jsのconsole.log(leftImage)の下のコメントアウト処理)をすると、関数の引数にしたleftがreferenceErrorが発生。

これは「left is not defined(leftが定義されていません)」というメッセージが出ていて、少なくとも記載されているコードにはleftという変数が見当たらないので、それが原因だと思います。

1Like

Comments

  1. @Yuki03280322

    Questioner

    ご回答頂きありがとうございます!
    ブレークポイントを張って検証した結果、頂いた仮説通り「HTMLが表示される前にJavaScriptが起動」していたことがはっきり分かりました。
    changeImageを定義し、その中でid取得を行い、最後にwindow.addEventListenerで("load", changeImage)を設定することにより解決致しました。

    解決+デバッグやブレークポイントについても実際に使い使い方を知ることが出来ました!
    ありがとうございます!

Your answer might help someone💌