お寿司か焼き肉食べたい

まじめな事からしょーもない事まで
めにゅーを開く(投げやり)

おい、何アンタ割り込んでくるんだやめろ

改修を行う時、とあるイベントを追加することになりました。
で、元々ある処理の前に実行させたい・・・
まぁ、単純に元々の処理を書き換えたりすれば万事オッケーなのですが
諸事情によって元処理に手を付けることができない そんな場面もあったりします。
さて、そんな時どうしましょうか?

まずは普通に

単純にリンククリックイベントを付与し、別々のイベントで別々のアラートを出すようになってたとします。

$('.clickLink1').on('click',function(){
  alert('最初のアラートだよー');
});
$('.clickLink1').on('click',function(){
  alert('2番目のアラートだよー');
});
$('.clickLink1').on('click',function(){
  alert('3番目のアラートだよー');
});
$('.clickLink1').on('click',function(){
  alert('4番目のアラートだよー');
});

あーしまったー最初にalert追加したいーどうしようー(棒)
うわー元処理触れないぞーこまったこまったー(棒)

バカな茶番ですが 先に答えを出してそれから実行してみましょう。

$('.clickLink2').on('click',function(){
  alert('最初のアラートだよー');
});
$('.clickLink2').on('click',function(){
  alert('2番目のアラートだよー');
});
$('.clickLink2').on('click',function(){
  alert('3番目のアラートだよー');
});
$('.clickLink2').on('click',function(){
  alert('4番目のアラートだよー');
});

//---------------------------------------
// 割り込み処理
//---------------------------------------

var events = $._data($('.clickLink2').get(0), "events");
var originalHandler = [];

// ループさせて、配列にどんどんぶち込んでいくスタイル
for(var i=0;i<events.click.length;i++)
{
  originalHandler[i] = events.click[i].handler;
}

// 今のイベントには死んでもらう
$('.clickLink2').off('click');

// 新しくイベント付与する
$('.clickLink2').on('click',{next:originalHandler}, function(event) 
{
  //割り込み処理ここから
  alert('これよりalertが大量にでます。ご注意ください。');
  //割り込み処理ここまで

  // 元々のイベントを順番に実行していくやで
  for(var i=0;i<event.data.next.length;i++)
  {
    event.data.next[i]();
  }
});

さくっと最初に割り込みすることができましたね。
見てもらうとわかるように、割り込み処理なんてものが追加されています。 かいつまんで説明していきますね。

eventsに代入されているものはなんだ

var events = $._data($('.clickLink2').get(0), "events");

_dataってなんだよ。おい。
いきなり躓きました。うへへ。
こいつは、jQuery1.8から追加になった関数で、まぁ使い方はそのまま
指定要素のイベントを取得する
ってものになります。ちなみに使い方は

$._data($elem, "events");

ちなみに。data関数とは似て非なるものと考えてもらっていいんじゃないかって思ってます。
で、要素の所で、get(0)ってしてるのは、ここで必要なのは一つの要素だけ、つまり、get(0)なしで全要素見て回ってどうすんだよ。
ってニュアンス
第二引数はもうそのままダイレクトに書いてあるのでスルーで
結局なんなん?ってまとめると
対象DOMに対して付与されているイベント一覧を取得する呪文
でよいです

ループしてなにやってだ

for(var i=0;i<events.click.length;i++)
{
  originalHandler[i] = events.click[i].handler;
}

あからさまに怪しい赤文字
先ほどの所でとってきたeventsこの中には【全部の】イベントがねじこまれているわけです
今回はクリックイベントをなんとかしたかったので、clickイベントだけをここで抽出しています。
もちろん他のイベントも名前をあわせるだけでできるようになるんじゃねぇのとか思ってます。

え、イベント消すんかい

$('.clickLink2').off('click');

割り込みって言い方してますが、新しくイベントを設定しなおすって事をしようとしてるわけです。
なので、元々の処理は邪魔なので消します。そのためにわざわざイベントを取得したのです。

改めてイベントをつけなおしましょう

$('.clickLink2').on('click',{next:originalHandler}, function(event) 
{
  //割り込み処理ここから
  alert('これよりalertが大量にでます。ご注意ください。');
  //割り込み処理ここまで

  // 元々のイベントを順番に実行していくやで
  for(var i=0;i<event.data.next.length;i++)
  {
    event.data.next[i]();
  }
});

にょわー。
はい。オブジェクトが追加されておりますね。オブジェクトの値部分には最初に取得したイベント一覧が入っているのです。
onメソッドに中々オブジェクトを突っ込む機会が自分にはないので新鮮な感じ。
これで、event.data.nextでデータを使うことができるようになるのですね。

で、この場合だと割り込み処理がまずスタート、その後
ループで順番に取得したイベントを実行しています。
そのため、先頭に割り込むことができた。そんな寸法なのですね。

先頭じゃなくて割り込みしたい場合

そんなんアレしたらええんや

$('.clickLink3').on('click',function(){
  alert('最初のアラートだよー');
});
$('.clickLink3').on('click',function(){
  alert('2番目のアラートだよー');
});
$('.clickLink3').on('click',function(){
  alert('3番目のアラートだよー');
});
$('.clickLink3').on('click',function(){
  alert('4番目のアラートだよー');
});

//---------------------------------------
// 割り込み処理
//---------------------------------------

var events = $._data($('.clickLink3').get(0), "events");
var originalHandler = [];

// ループさせて、配列にどんどんぶち込んでいくスタイル
for(var i=0;i<events.click.length;i++)
{
  originalHandler[i] = events.click[i].handler;
}

// 今のイベントには死んでもらう
$('.clickLink3').off('click');

// 新しくイベント付与する
$('.clickLink3').on('click',{next:originalHandler}, function(event) 
{

  // 元々のイベントを順番に実行していくやで
  for(var i=0;i<event.data.next.length;i++)
  {
    if(i==3){
      //割り込み処理ここから
      alert('まだalert続くやで');
      //割り込み処理ここまで
    }
    event.data.next[i]();
  }
});

ループの中でやったらええんや!
やってみると意外に楽しいけど、正直多用することは滅多にないと思います。
知ってて遭遇した時にパパッ!と片付けるとヒーローです。かっこいいです。モテはしないやろうけど。