初級 jQuery イベント DOM操作

マウスを乗せて出るボタンで、入力欄に文字を挿入する

マウスを乗せると小さなボタン一覧が出て、クリックした記号が入力欄に入る仕組みを作ります。あわせて、行の追加・削除と「イベントの委譲」も学びます。

このサンプルは2017〜2018年ごろに作成したものです。PHPのバージョンが上がり、そのままでは動かなくなっていたため、2026年に PHP 8.3 で動くように書き直し、解説も新しくしました。

DEMO 実際に動かしてみよう

英単語帳の入力画面です。「▲」にマウスを乗せると品詞のボタンが出てきます。ボタンをクリックすると、その行の「意味」の欄に [動] などの記号が入ります。

No品詞意味単語
1
▲
  • 動
  • 形
  • 名
  • 副
  • 接
  • 前

解説コードを読んでみよう

このサンプルでわかること

  • マウスが乗った・離れたときの処理(mouseenter / mouseleave)
  • クリックした場所から、同じ行の入力欄を探す方法(closest() と find())
  • あとから追加した行でもボタンが効く「イベントの委譲」

使っているファイル

  • index.phpデモのページ(HTML・CSS・JavaScript をすべてこの1ファイルに記述)
  • jqueryjQuery 本体(サイト共通で読み込み済み)

1. HTML:1行分の部品を用意する

表の1行が「品詞ボタン」「意味」「単語」「削除」のセットです。品詞ボタンは ul のリストで、最初は CSS で隠しておきます。挿入する文字は data-char 属性に書いておくと、JavaScript から取り出しやすくなります。

index.php(18〜36行目) PHP
    <tr>
      <td class="no">1</td>
      <td>
        <div class="insert">
          <span class="insert__open">▲</span>
          <ul class="insert__list">
            <li data-char="[動]">動</li>
            <li data-char="[形]">形</li>
            <li data-char="[名]">名</li>
            <li data-char="[副]">副</li>
            <li data-char="[接]">接</li>
            <li data-char="[前]">前</li>
          </ul>
        </div>
      </td>
      <td><input type="text" class="meaning" placeholder="例: [動] 走る"></td>
      <td><input type="text" class="word" placeholder="例: run"></td>
      <td><button type="button" class="btn row-del">削除</button></td>
    </tr>

data-〇〇="…" は、HTML の要素に自由なデータを持たせるための書き方です。jQuery では $(this).data('char') で data-char の値を取り出せます。

2. CSS:ボタン一覧を最初は隠しておく

.insert__list に display: none; を指定して、最初は見えないようにします。position: absolute; で「▲」の真下に重ねて表示します。

index.php(41〜48行目) CSS
<style>
.word-table input { width: 100%; }
.insert { position: relative; display: inline-block; }
.insert__open { display: inline-block; padding: 4px 8px; border: 1px solid #d8d3c7; border-radius: 6px; cursor: pointer; background: #fff; }
.insert__list { display: none; position: absolute; left: 0; top: 100%; z-index: 5; margin: 0; padding: 4px; list-style: none; white-space: nowrap; background: #1d2433; border-radius: 8px; }
.insert__list li { display: inline-block; width: 30px; margin: 2px; padding: 4px 0; text-align: center; font-size: 13px; color: #fff; border-radius: 5px; cursor: pointer; background: #3c4557; }
.insert__list li:hover { background: #ffd866; color: #1d2433; }
</style>

3. マウスを乗せたら表示、離れたら隠す

mouseenter はマウスが要素に入ったとき、mouseleave は出たときに起きるイベントです。.show() と .hide() で表示を切り替えます。スマホにはマウスがないので、「▲」をタップしたときにも開閉できるように click も用意しています。

index.php(53〜60行目) PHP
    // ① マウスが乗ったらボタン一覧を出し、離れたら隠す
    $('.word-table').on('mouseenter', '.insert', function() {
        $(this).children('ul').show();
    }).on('mouseleave', '.insert', function() {
        $(this).children('ul').hide();
    }).on('click', '.insert__open', function() {
        $(this).next('ul').toggle();   // スマホ用: タップでも開閉できるように
    });

4. クリックした記号を、同じ行の入力欄に足す

ここがこのサンプルの中心です。クリックされた li($(this))から、closest('tr') で一番近い親の行までさかのぼり、find('.meaning') でその行の中の入力欄を探します。

index.php(62〜66行目) PHP
    // ② 品詞ボタンをクリックしたら、同じ行の「意味」欄の後ろに記号を足す
    $('.word-table').on('click', '.insert__list li', function() {
        var input = $(this).closest('tr').find('.meaning');   // 同じ行の入力欄を探す
        input.val(input.val() + $(this).data('char')).focus();
    });
書き方意味
$(this)今クリックされた要素
.closest('tr')自分から親の方向へたどり、最初に見つかった tr(行)
.find('.meaning')その中にある class="meaning" の要素
input.val()入力欄の今の文字(引数なし=取得)
input.val(文字)入力欄に文字をセット(引数あり=設定)

以前のバージョンでは $(this).parent().parent().parent().next().children() のように親を何段もたどって入力欄を探していました。これだと HTML を少し変えただけで動かなくなります。closest() と find() を使うと、HTML の形が多少変わっても壊れにくくなります。

5. 行の追加と削除(イベントの委譲)

「行を追加」は1行目を .clone() でコピーし、入力欄を空にしてから表の最後に足しています。

index.php(68〜90行目) PHP
    // ③ 行を追加する(1行目をコピーして中身を空にする)
    $('.row-add').on('click', function() {
        var row = $('.word-table tbody tr:first').clone();
        row.find('input').val('');
        row.find('ul').hide();
        $('.word-table tbody').append(row);
        renumber();
    });

    // ④ 行を削除する(最後の1行は残す)
    $('.word-table').on('click', '.row-del', function() {
        if ($('.word-table tbody tr').length > 1) {
            $(this).closest('tr').remove();
            renumber();
        }
    });

    // 行番号をふり直す
    function renumber() {
        $('.word-table tbody tr').each(function(i) {
            $(this).find('.no').text(i + 1);
        });
    }

3〜5の処理はすべて $('.word-table').on('click', '.row-del', …) のように、表全体にイベントを登録して、対象を2番目の引数で指定しています。これを「イベントの委譲」といいます。$('.row-del').on('click', …) と書くと、ページを開いた時点の行にしか効かず、あとから追加した行のボタンは反応しません。

品詞ボタンの li を1つ増やして、data-char="[代]"(代名詞)を追加してみましょう。JavaScript は1行も変えずに動くはずです。

↑