ということで、「IEさん、頼むよ...」っていう話。
JavaScriptのIE用イベントハンドラ「attachEvent/detachEvent」。これを使って呼び出したイベント内では、thisがwindowと解釈される落とし穴が。
下記のイベントをIEで実行すると、どうなるか、さっそく検証。
ボタンのラベル「送信する」がalertで返される、かと思いきや、結果は「undefined」。
これが、IEでattachEventした関数内では、「this」がwindowオブジェクトとなってしまうってこと。
つまり、detachEventもできず、はまるので注意。
じゃあ、どう書けばいいのか。
thisの代わりに「evt.srcElement」で、イベント発生元を取得すればよい。
と、ここまでがIEの話。
IE以外は、「addEventListener/removeEventListener」でイベントを制御するから、その振り分けをすればよい。クロスブラウザで動作する、最終的なコードは下記。
今回、ブラウザ依存の問題に結構はまってしまったけど、イベントのバブリングフェーズとかキャプチャフェーズについて勉強できたから、許す。(←何を?)
たまにネイティブのJavaScriptを書くと、ブラウザの差異を意識しなくていい「jQuery」のありがたみが身にしみますね。。。
thisを意図通り扱うため、上記のようにcallを使う方法もある。けど、この場合、無名関数でattachするから、detachEventできないので要注意です。
(参考サイト)
JavaScript のイベントハンドラ - daily dayflower
JavaScript メモ / チップス attachEvent() と addEventListener() [ ARTEMIS ]

前田かおるさんサイトのお手伝いをした際に、タブを実装することになったので、昔つくったJavaScriptを元にjQueryプラグイン化してみた。
タブにしたい要素を指定するだけという、簡単実装。いやあ、jQueryって便利ですね。ってことで、さっそく解説。
指定した要素をタブ化するjQueryプラグイン。クッキーを利用して、表示するタブを記憶します。
必要なデータを上記よりダウンロード後、CSSとJavaScriptを読み込む。
JavaScript
タブを適用させたい要素のid(id-of-tabname)を指定し、cookieTabを実行。
HTML(準備用)
上記で指定したタブ内に、タブメニューとタブパネルを配置。
タブメニューには「class="tab-menu"」を、タブパネルには「class="tab-panel"」を付与してください。どちらもオプション設定で変更可能です。
HTML(js実行時)
アクティブなタブメニューに<li class="current">が適用されます。
デフォルト設定では、先頭のパネル(#some-tabA)を表示します。
| オプション項目 | デフォルト値 | 内容 | |
|---|---|---|---|
| activeTab | 0 | 初期表示しておくタブ | |
| tabMenuElm | .tab-menu | タブメニューとする要素名(#idや.class等のCSS記法にて指定) | |
| tabPanelElm | .tab-panel | タブパネルとする要素名(#idや.class等のCSS記法にて指定) | |
| cookie | 使用する | cookieを使用しない(false) | |
| cookie | name | jcookieTab | jcookieTab-(id-of-tabname) = 0 の形式で書き込み |
| expires | 7 | cookieの有効期限 [単位:日] | |
| path | (none) | cookieの有効範囲:設定したページのみ有効(none), サイト全体で有効(/)etc. | |
| secure | (none) | セキュアな通信時のみcookieを送信(true) | |
MITライセンスでの配布となります。

盆栽教室のサイトを制作した際に、画像ギャラリーを作る必要があったので、せっかくなのでjQueryプラグイン化してみた。
フェードイン・フェードアウトするだけのシンプルな動きなので、さっと設置したい時には便利かも。ということで、さっそく解説。
フェードイン・フェードアウトで画像を表示するjQueryプラグイン。画像をクリックすると次の画像へ遷移します。
必要なデータを上記よりダウンロード後、CSSとJavaScriptを読み込む。
JavaScript
ギャラリー部分のid(id-of-crossfader)を指定し、クロスフェードを実行。
HTML(画像のみの場合)
CSSを適用するため、画像の親要素(ここでは<div>)にclass="crossfader"を付与してください。
JavaScriptオフの環境では、class="active"を付与した画像が表示されます。
HTML(リンクを設定する場合)
| オプション項目 | デフォルト値 | 内容 |
|---|---|---|
| timer | 6000 | 切替までの待機時間 [単位:ミリ秒] |
| speed | 1500 | 遷移速度(待機時間timer経過時) [単位:ミリ秒] |
| changeSpd | 800 | 遷移速度(画像クリック時) [単位:ミリ秒] |
| random | false | 画像をランダム表示する(true) or しない(false) |
| loop | true | ループ表示する(true) or しない(false) |
MITライセンスでの配布となります。
≫ jQueryプラグイン化した新バージョンを作成しました。
CookieをIEからFirefoxへインポートする際、ドメイン名の解釈の違いでcookieが複数生成されるバグを修正しました。(2010.03.06)
IE6,IE7でJavaScriptが動作しないバグを修正しました。(2009.09.10)
クッキー(cookie)とJavaScriptを使って、いわゆるYahoo!トピックスのタブ表示みたいなのを作ろう!という企画。

たまに使いたくなるクッキー。でも処理がめんどくさそうなので今まで敬遠してきた。
そんな折、テレビから「START!一歩を踏み出そう」の声が・・・。なんか作らないといけないような強迫観念にさいなまれて、サンプルを作成してみた。
以下、HTMLのマークアップ。(簡略化してます)
<ul id="tabhead">
<li id="head-tab0" class="on"><a id="anchor-tab0" href="#">foo_a</a></li>
<li id="head-tab1"><a id="anchor-tab1" href="#">foo_b</a></li>
<li id="head-tab2"><a id="anchor-tab2" href="#">foo_c</a></li>
</ul>
<div id="tabbody">
<div id="body-tab0" class="current">
<h2>foo_a</h2>
<ul>
<li>hoge</li>
</ul>
</div>
<div id="body-tab1">
<h2>foo_b</h2>
<ul>
<li>hoge</li>
</ul>
</div>
<div id="body-tab2">
<h2>foo_c</h2>
<ul>
<li>hoge</li>
</ul>
</div>
</div>
肝心のJavaScript部分は以下↓
//変数設定
var CookieTab = {
cookieName: 'select', //cookieに書き込むプロパティ名
cookieExpires: 10, //cookieの有効期限(単位:日)
tabHeadId: 'tabhead', //タブheadのID名
tabBodyId: 'tabbody', //タブbodyのID名
tabHdPrefix: 'head-', //タブheadリストのID接頭語
tabBdPrefix: 'body-', //タブbodyリストのID接頭語
tabAnPrefix: 'anchor-' //タブheadアンカーのID接頭語
};
//DOM読込完了後、tab制御開始
dom.event.addEventListener(window,'load',function(){
CookieTab.setting();
});
//tabの初期制御
CookieTab.setting = function() {
this.tabValue = this.getCookie(this.cookieName);
this.domAnalysis();
if(!this.tabValue || this.tabValue==undefined){
this.tabValue = 'tab0';
}
this.tabControl();
}
//cookie書込用関数
CookieTab.setCookie = function(ckName, ckValue, ckExpires, ckDomain, ckPath, ckSecure) {
var date = new Date();
date.setTime(date.getTime() + ckExpires*24*60*60*1000);
var ckStr = escape(ckName) + '=' + escape(ckValue);//日本語使用時の文字化け対策
ckStr += '; expires=' + date.toGMTString();//有効期限をGMT値に変換
if(ckDomain) {
ckStr += '; domain=' + ckDomain;
}
if(ckPath) {
ckStr += '; path=' + ckPath;
}
if(ckSecure) {
ckStr += '; secure';
}
document.cookie = ckStr;
}
//cookie取得用関数
CookieTab.getCookie = function(ckName) {
var ckMatch = ('; ' + document.cookie + ';').match('; ' + ckName + '=(.*?);');
var ckValue;
if(ckMatch){
ckValue = ckMatch[1];
} else {
ckValue = '';
}
ckValue = unescape(ckValue);//escapeしたものを元に戻す
return ckValue;
}
//DOM解析用関数
CookieTab.domAnalysis = function() {
this.linum = this.ID(this.tabHeadId).getElementsByTagName('li').length;
this.tabBdDiv = this.ID(this.tabBodyId).getElementsByTagName('div').length;
if(this.linum != this.tabBdDiv){
throw new Error('tabHead is not equal to tabBody.');
}
}
//tabの初期設定
CookieTab.tabControl = function() {
this.tabDisplay();
for(var i=0; i<this.linum; i++){
this.tabAnchor(i);//tabクリック時の動作設定
}
}
//tabの表示制御
CookieTab.tabDisplay = function() {
for(var i=0; i<this.linum; i++){
//互換性維持のためclassの取得・設定にはhoge.className = fooを使用
this.ID(this.tabHdPrefix + 'tab' + i).className = '';
this.ID(this.tabBdPrefix + 'tab' + i).className = '';
}
this.ID(this.tabHdPrefix + CookieTab.tabValue).className = 'on';
this.ID(this.tabBdPrefix + CookieTab.tabValue).className = 'current';
}
//tabクリック時の動作制御
CookieTab.tabAnchor = function(tabnum) {
this.ID(this.tabAnPrefix + 'tab' + tabnum).onclick = function(){
CookieTab.setCookie(CookieTab.cookieName,'tab' + tabnum,CookieTab.cookieExpires,location.hostname);//Cookieを発行するドメイン名を明示的に指定
CookieTab.tabValue = CookieTab.getCookie(CookieTab.cookieName);
CookieTab.tabDisplay();
return false;
}
}
//getElementByIdの短縮形を使用
CookieTab.ID = function(id) {
var myId = document.getElementById(id);
return myId;
}
解説は時間と紙面の関係上、割愛。スクリプトに少しコメントを入れてるので、そちらを参照ください。
ちょっと前から「オライリーのサイの本」を読んで、ちょこちょこ勉強してるけど、やっぱ手を動かさないとダメ。「名前空間を汚さないようにモジュール化する」ってことの意味が、やっと少し分かった気がする。
今回は「jQuery」を使わず実装したけど、jQueryを使った場合のスクリプトは以下。
jQueryにプラスして、「jquery.cookie.js」も使用するのであしからず。
//DOM読込完了後、tab制御開始
$(document).ready(function(){
CookieTab.setting();
});
//tabの初期制御
CookieTab.setting = function() {
this.tabValue = $.cookie(this.cookieName);
if(!this.tabValue || this.tabValue==undefined){
this.tabValue = 'tab0';
}
this.tabControl();
}
//tabの初期設定
CookieTab.tabControl = function() {
this.tabDisplay();
$('#' + this.tabHeadId + ' li a').each(function(value){
$(this).click(function(){//tabクリック時の動作設定
value+='';//数値型→文字列型変換
$.cookie(CookieTab.cookieName, 'tab' + value, { expires: CookieTab.cookieExpires, domain: (location.hostname) });//Cookieを発行するドメイン名を明示的に指定
CookieTab.tabValue = $.cookie(CookieTab.cookieName);
CookieTab.tabDisplay();
return false;
});
});
}
//tabの表示制御
CookieTab.tabDisplay = function() {
$('#' + this.tabHeadId + ' li').each(function(){
$(this).removeClass('on');
});
$('#' + this.tabBodyId + ' div').each(function(){
$(this).removeClass('current');
});
$('#' + this.tabHdPrefix + this.tabValue).addClass('on');
$('#' + this.tabBdPrefix + this.tabValue).addClass('current');
}
jQueryには、jQueryの難しさがあるし、こっちの方法も結構めんどい。適材適所で使うのがよいかと。
サンプルのダウンロードもできるので、興味がある方はどうぞ。
これを使う機会、いつか来るかな。
≫CookieTab.jsサンプルファイルの一括ダウンロードはこちら
ライセンス:
「クリエイティブコモンズライセンス:帰属(Attribution, by)」での公開・配布となります。
最近、ちょこちょこお世話になってるjQuery。
便利なのはいいんだけど、読み込み時間が気になる。ってことで、jQueryの機能が必要ないページで読み込むのを控えてたら、JavaScriptエラーでつまづいたので自分用にメモ。
たとえば、ロード完了時にアラートを出す以下のコード。
このケース、jQueryが読み込まれてないと、「$ってナンデスカ?」っていうエラー「$ is not defined」が発生してしまう。
ってことで、jQueryの読み込みを判別するため、以下のif文を追加した。
( サンプルページ1 / サンプルページ2 )
これでめでたくエラーとはおさらばです。