Baccho Log

No Image

Sponsored Link

[jQuery]onとoff

  • 投稿日:
  • 更新日:
Tags:
JavaScript jQuery
Categories:
プログラミング

on()メソッド

構文

  1. $(セレクタ).on( イベント名 [,object], function(event){})
  2. $(調査範囲).on( イベント名, セレクタ [,object], function(event){})
  3. $(調査範囲).on( object, セレクタ [,object] )
  4. $(セレクタ).on( object )

何が出来るのか

基本的には下記の事が出来ます。

  1. 後から要素を追加した場合もイベント発火させる
  2. 複数のイベントを発火させる

詳しく見てみましょう。

1. 後から要素を追加した場合もイベント発火させる

例えば、下記のソースがあったとします。

共通ソース

<body>
    <div>Example Message!!</div>
    <script>
    $(function(){
        var button = $("<button>").text("button");
        $("div").append(button);
    });
    </script>
</body>

まずは、htmlファイル上に始めからある要素に対して、イベントを発火するケースです。
今回の場合、div要素に対してクリックイベントを発動させます。

構文1 $(セレクタ).on( イベント名 [,object], function(event){})

$('div').on("click", function(){
    alert("Hello Work!!");
});
$('div').on("click", {test: 100}, function(event){
    alert(event.data.test); // =>100
});

// これでも可能
var obj = {
    test: 100,
    fuga: 500,
    hoge: "お腹すいた"
};
$('div').on("click", obj, function(event){
    alert(event.data.test); // =>100
    alert(event.data.fuga); // =>500
    alert(event.data.hoge); // =>お腹すいた
});

これでclickイベントが発火します。
objectのプロパティを取得することも出来ます。

次に、後から要素を追加した場合です。
今回の場合、button要素に対してクリックイベントを発動させます。

後から要素を追加する場合、最初の例のような

$('button').on("click", function(){
    alert("Hello Work!!");
});

と、いう書き方では発火しません。
これは最初にページを読み込んだ際に、button 要素が存在していなかった為にイベントが発火出来ないようです。
これをイベント発火させる為には下記のように書きます。

構文2 $(調査範囲).on( イベント名, セレクタ [,object], function(event){})

$(document).on("click", "button", function() {
    alert("Hello Work!!");
});
$(document).on("click", "button", {test: 100}, function(event){
    alert(event.data.test); // =>100
});

これでbuttonをクリックした際にアラートが立ちます。
ちなみに、$(document)とありますが、囲まれている部分が対象となりますので
$('body').on("click", 'button', fn);
$('div').on("click", 'button', fn);
でもイベント発火します。

2. 複数のイベントを発火させる

onメソッドは複数のイベントを指定することが出来ます。
例えば、

$(document).on("click mouseenter", "button", function() {
    alert("Hello Work!!");
});

これでボタンをクリックした時と、マウスカーソルがボタン要素に入ったときにアラートが立ちます。
半角スペースで区切って複数のイベントを書くことで、複数のイベントにも対応させる事が出来ます。

また、objectでイベントを指定することも出来ます。

Ex.1)構文3 $(調査範囲).on( object, セレクタ [,object] )

var obj{};
obj.mouseenter = function(event) {
    $(this).css('color', '#f00');
};
obj.mouseleave = function(event) {
    $(this).css('color', '#000');
};
obj.click = function(event) {
    $(this).css('color', '#0f0');
};
$(document).on(obj, 'button');

// この書き方も可能
$(document).on({
    'mouseenter': function(event) {
        $(this).css('color', '#f00');
    },
    'mouseleave': function(event) {
        $(this).css('color', '#000');
    },
    'click': function(event) {
        $(this).css('color', '#0f0');
    }
}, 'button');

これで、

  • ボタンにカーソルが入ったら文字色が赤
  • ボタンからカーソルが離れたら文字色が黒
  • ボタンをクリックしたら文字色が緑

になります。

また、第二引数にセレクタを記載せず、
頭にセレクタを記載する方法でも同じイベントが発生します。
構文1では動的に追加した要素には反応しませんが、構文4では動的に追加した要素にも反応します。(理由は分かりません・・・)

Ex.2)構文4 $(セレクタ).on( object [, object])

var obj{};
obj.mouseenter = function(event) {
    $(this).css('color', '#f00');
};
obj.mouseleave = function(event) {
    $(this).css('color', '#000');
};
obj.click = function(event) {
    $(this).css('color', '#0f0');
};
$('button').on(obj);

// この書き方も可能
$('button').on({
    'mouseenter': function(event) {
        $(this).css('color', '#f00');
    },
    'mouseleave': function(event) {
        $(this).css('color', '#000');
    },
    'click': function(event) {
        $(this).css('color', '#0f0');
    }
});

また、ちょっとハマったケースです。

Ex.) イベントが効かない

var obj {
    test: 100,
    fuga: 500,
    hoge: "お腹すいた"
};
obj.mouseenter = function(event) {
    $(this).text(event.data.test);
};
obj.mouseleave = function(event) {
    $(this).text(event.data.fuga);
};
obj.click = function(event) {
    $(this).text(event.data.hoge);
};

$(document).on(obj, 'button'); //=>効かない!
$('button').on(obj); //=>効かない!

これは全て効きません。効かないというと語弊がありますが・・・。
console.logで確認すると分かりますが、ちゃんとイベントは発生しています。
が、object値が渡されていないのでエラーが発生しイベントが中止されます。

あくまでも第一引数はイベントを指定するobjectであって、
その中身(今回の場合はobj.test, obj.fuga, obj.hoge)は渡しません。
イベントを発生させるには、

  • functionの中身をobject値を含ませないようにする(前例の構文4)
  • 第三引数でobject値を渡すようにする(後述のEx.3、Ex.4)

と設定するようにしましょう。

それでは次はobject値を渡すため、第三引数を指定した例を見てみましょう。

Ex.3)構文3 $(調査範囲).on( object, セレクタ [,object] )

var obj = {
    test: 100,
    fuga: 500,
    hoge: "お腹すいた"
};
var obj2 = {
    test: 101,
    fuga: 501,
    hoge: "お腹いっぱい"
};
obj.mouseenter = function(event) {
    alert(event.data.test);
};
obj.mouseleave = function(event) {
    alert(event.data.fuga);
};
obj.click = function(event) {
    alert(event.data.hoge);
};
$(document).on(obj, 'button', obj);
$(document).on(obj, 'div', obj2);

これで、

  • ボタンにカーソルが入ったら 100 のアラート
  • ボタンからカーソルが離れたら 500 のアラート
  • ボタンをクリックすると お腹すいた のアラート

になります。

divについては、

  • divにカーソルが入ったら 101 のアラート
  • divからカーソルが離れたら 501 のアラート
  • divをクリックすると お腹いっぱい のアラート

になります。

また下記の方法でも同様に動作します。

Ex.4)構文4 $(セレクタ).on( object [, object])

var obj = {
    test: 100,
    fuga: 500,
    hoge: "お腹すいた"
};
var obj2 = {
    test: 101,
    fuga: 501,
    hoge: "お腹いっぱい"
};
obj.mouseenter = function(event) {
    alert(event.data.test);
};
obj.mouseleave = function(event) {
    alert(event.data.fuga);
};
obj.click = function(event) {
    alert(event.data.hoge);
};
$('button').on(obj, obj);
$('div').on(obj, obj2);

最後の2行が変わっただけですが、objectのみで設定する事も可能です。
object値を渡したい場合は、このように設定してみて下さい。

今回は3種類のイベントしか書いてませんが、イベントはたくさんあります。
loadscrollresize等々、色んなイベントを想定して、
onと一緒に使うと新しい道が開けるかもしれません。

jQuery リファレンス:on

off()メソッド

構文

  1. $(onメソッドで指定したセレクタ).off()
  2. $(onメソッドで指定したセレクタ).off( イベント名 )
  3. $(onメソッドで指定したセレクタ).off( イベント名, セレクタ )
  4. $(onメソッドで指定したセレクタ).off( イベント名, [セレクタ,] function )
  5. $(onメソッドで指定したセレクタ).off( 複数のイベント名[, セレクタ] )

何が出来るのか

onメソッドで設定をしたイベントを解除します。

実際に使ってみよう

<body>
    <div>Change Message!!</div>
    <button id="alert001">Alert 1</button>
    <button id="alert002">Alert 2</button>
    <div>
        <p id="addButton"></p>
    </div>
    <span>change obj</span>
    <input type="button" id="offEvent" value="clear">
    <script>
        var count = 0;
        $(function(){
            // button要素をdiv#addButton 内に追加する
            var button = $("<button>").attr('id', 'alert003').text("Alert 3");
            $("#addButton").append(button); //=>div#addButton内にbutton要素を追加する

            var obj = {
                text: "Change Text!!!!",
                text2: "Add Text!!!!",
                text3: "変わりました!!!!!",
                text4: "change obj",
                str1: "Alert 1だよ",
                str2: "Alert 2だよ",
                str3: "Alert 3だよ",
            };
            obj.mouseenter = function(event) {
                $(this).text(event.data.text3)
                .css({
                    "font-size" : "20px",
                    "font-weight" : "bold",
                    "color" : "#f00"
                });
            };
            obj.mouseleave = function(event) {
                $(this).text(event.data.text4)
                .css({
                    "font-size" : "",
                    "color" : "",
                    "font-weight" : ""
                });
            };

            function inputText(e) {
                $(this).text(e.data.text3);
            }

            $('#alert001').on('click', obj, function(e) {
                alert(e.data.str1); //=> alert 1だよ
            });
            $('#alert001').on('click', obj, inputText);

            $('#alert002').on('click', obj, function(e) {
                alert(e.data.str2); //=> alert 2だよ
            });

            $('div').on('click', '#alert003', obj, function(e) {
                alert(e.data.str3); //=> alert 3だよ
            });
            $('div').eq(0).on('mouseenter mouseleave', obj, function(e) {
                $(this).text(e.data.text); //=> カーソルをあてるとテキストが変わる。 カーソルが離れてもテキストが変わる。(同じ文言)
                if(e.type === "mouseleave") $(this).text(++count + "回目");
            });
            $('div').on('click', '#addButton', obj, function(e) {
                $(this).append(e.data.text2); //=> クリックするとテキストを追加する
            });
            $('span').on(obj, obj);

            $('#offEvent').on('click', function(event) {
                // ここにoffメソッドを書く
            });
        });
    </script>
</body>

上記onメソッドの復習がてら、ざっと挙動を書きます。

  1. p#addButton内にbutton要素が追加される(id: alert003, value: Alert3)
  2. alert1 をクリックすると、"alert 1だよ"というアラートが立つ
  3. alert1 をクリックすると、ボタンのテキストが"変わりました!!!!!"になる
  4. alert2 をクリックすると、"alert 2だよ"というアラートが立つ
  5. alert3 をクリックすると、"alert 3だよ"というアラートが立つ
  6. Change Message!!にカーソルをあてると、"Change Text!!!!"に変わる。
    カーソルを外すとカーソルを外した回数が表示される。
  7. div#addButtonをクリックすると、"Add Text!!!!"というテキストが追加される
  8. change obj の箇所にカーソルをあてると、"変わりました!!!!!"というテキストが
    font-size: 20px, font-weight: bold, color: #f00 で変更される。
    カーソルを外すと、"change obj"というテキストでCSSが元に戻る。

さて、ここからoffメソッドの挙動を追加していきます。

Ex.1)構文1 $(onメソッドで指定したセレクタ).off()

$('#alert002').off();//=> alert2のイベントが解除される
$('div').off();      //=> divのイベントが全て解除される
$('span').off();     //=> spanのイベントが全て解除される

Ex.2)構文2 $(onメソッドで指定したセレクタ).off( イベント名 )

$('div').off('mouseenter')  //=> divのmouseeventイベントのみが解除される
$('span').off('mouseleave') //=> spanのmouseleaveイベントのみが解除される

恐らくは直感的に分かると思います。
注意点としては、onメソッドの前の調査範囲で指定したセレクタをoffメソッドで指定しなければなりません。
例えば、p#addButtonのイベントを解除したいと思って、
$('#addButton').off()
$('#addButton').off('click')
などと、記載しても解除されません。
onメソッドの調査範囲で設定しているのは div ですので、divで設定しましょう。

また、セレクタや関数を指定して設定する事も出来ます。

Ex.3)構文3 $(onメソッドで指定したセレクタ).off( イベント名, セレクタ )

$('div').off('click', '#alert003')  //=> divのidがalert003のclickイベントのみが解除される

こうする事で#alert003のクリックイベントだけを解除できます。
因みに、イベントは半角スペースで区切って複数指定することが出来ます(後述)が、
セレクタと関数については複数を選ぶ事は出来ません。
別々にoffメソッドを指定するか、classで設定するのがいいと思います。

解除する関数を指定することもできます。
第一引数に関数単体を指定して解除という方法は出来ません。
必ず第一引数にはイベントの指定が必要です。

Ex.4)構文4 $(onメソッドで指定したセレクタ).off( イベント名, [セレクタ,] function )

$('#alert001').off('click', inputText) //=>alert001のinputTextイベントのみが解除される
$('#alert001').off(inputText)          //=>これは出来ない

関数名で解除することは出来ました。
しかし無名関数の場合は、関数名がないので指定することが出来ません。
その場合は、イベントに名前を付けて、その名前空間で指定することが出来ます。

Ex.5)無名関数を名前空間で解除する

$('#alert001').on('click.inputText', obj, function(e) {
    alert(e.data.str1); //=> alert 1だよ
});
// 上記のonの解除は下記のようにする
$('#alert001').off('.inputText');

関数を指定して解除するというよりは、
イベントに名前をつけて、そのイベントを解除するという感じですね。

objectで設定されているイベントを指定することも可能です。
また、objectを丸ごと指定する事も可能です。

Ex.6)構文5 $(onメソッドで指定したセレクタ).off( object )

$('span').off('mouseleave')  //=> spanのmouselaveイベントのみが解除される。
$('span').off(obj)           //=> spanのobjectのイベントが解除される。

イベントについては、複数のイベントを半角スペースで分けて同時に記載する事が出来ます。
セレクタ箇所にobjectは指定出来ません。第二引数を指定するときは、セレクタを指定して下さい。

Ex.7)構文6 $(onメソッドで指定したセレクタ).off( 複数のイベント名[, セレクタ] )

$('div').off('mouseenter mouseleave')       //=> divのmouseenterとmouseleaveイベントが解除される。
$('div').off('mouseenter mouseleave', obj)  //=> これは出来ない

.click(fn) と .on(“click”, fn) の違い

A. ありません。
と、言うと語弊があるかもしれないですが、
この構文に限定して言えば同じ働きをします。

$('div').click(function() {
    alert("Hello Work!!");
});

と、

$('div').on("click", function() {
    alert("Hello Work!!");
});

は同じです。
appendやafter等で動的に要素を追加したとしても同じです。
この構文で書いたコードでは、追加要素を捉えることはできません。

ここで、onの本領が少し発揮されます。
前項で書いた通り、onは動的に追加した要素にも反応するようにする事が出来ます。
clickでは出来ませんので、動的に追加する要素がある場合には統一する意味でもonを使用したほうがいいと思います。

引数のeventって何なの?

jQueryのEventオブジェクトです。
Eventオブジェクトを通して、イベントハンドラに渡されます。

例えば、

$(document).on("click", 'button', function(event){
    alert(event.type);
});

とすれば、ボタンをクリックした際に、clickというアラートが立ちます。
eventのプロパティやメソッドは、target以外にも多くありますので、
詳細は下記を確認してみてください。

jQuery.Event – jQuery 日本語リファレンス
公式 | Event Object | jQuery API Documentation

« [JavaScript]幅と高さを取得 / 設定する方法[WSH]Sendkeysの文字化け対策 »

Sponsored Link

コメントする

記事の感想や修正依頼等ありましたら、コメントをお願いいたします