onclickイベントとjQueryのclickイベントを併用するときの注意
利用シーンはあまりないと思いますが、onclickイベントにjQueryのclickイベントを追加するときの注意点をまとめました。
次のようなレガシーな処理があると仮定します。
onclickイベントでsendというメソッドを呼び出し、フォームのチェック処理を行ったあとsubmit()を実行しています。
<script>
function send() {
// 既存のチェック処理など
document.test.submit();
}
</script>
<form id="test" name="test" method="post" action="index.cgi" onsubmit="retrun false;">
<input name="foo" id="foo" type="text" value="$foo" />
<input id="bar" type="button" value="送信" onclick="send()" />
</form>
この処理に以下のようなjQueryのcilckイベント(赤色)を新たに追加した場合、先にonclickイベントが発動するため、jQueryの処理は実行されません。
<script>
$(function(){
$('#bar').click(function(){
$('#foo').val('');
});
});
function send() {
// 既存のチェック処理など
document.test.submit();
}
</script>
<form id="test" name="test" method="post" action="index.cgi" onsubmit="retrun false;">
<input name="foo" id="foo" type="text" value="$foo" />
<input id="bar" type="button" value="送信" onclick="send()" />
</form>
上記のような場合、次のようにonclickイベントを削除し、clickイベントの後で既存のメソッドを呼び出すように修正するといいようです。
<script>
$(function(){
$('#bar').click(function(){
$('#foo').val('');
send();
});
});
function send() {
// チェック処理など
document.test.submit();
}
</script>
<form id="test" name="test" method="post" action="index.cgi" onsubmit="retrun false;">
<input name="foo" id="foo" type="text" value="$foo" />
<input id="bar" type="button" value="送信" onclick="send()" />
</form>
ということで、「onclick属性とjQueryのclickを併用しない」となり、タイトルと違った結果になってしまってます。あしからず。
IEでzenbackとjQueryのコンフリクトによる不具合を回避する方法
IEでzenbackとjQueryのコンフリクトによる不具合を回避する方法を紹介します。
1.問題
IEでzenbackとjQueryプラグイン(例えばjQuery ligthboxプラグイン)を併用する場合、次のようなソースコードになると思います。(zenbackのコードは便宜上改行しています)。赤色がjQueryプラグイン、青色がzenbackです。
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.lightbox-0.5.js"></script>
<script type="text/javascript">
$(function() {
$('#gallery a').lightBox();
});
</script>
…中略…
<!-- X:S ZenBackWidget -->
<script type="text/javascript">
document.write(unescape("%3Cscript")+" src='http://widget.zenback.jp/?base_uri=http%3A//user-domain/&nsid=01234567890123345%3A%3A01234567890123345&rand="+Math.ceil((new Date()*1)*Math.random())+"' type='text/javascript'"+unescape("%3E%3C/script%3E"));
</script>
<!-- X:E ZenBackWidget -->
FirefoxやGoogle Chromeであれば、zenbackもligthboxプラグインも動作しますが、IEでは正常に動作しなくなるようです。
具体的には共倒れになります(全然具体的じゃないw)。
2.原因
zenback内部でもjQueryを読み込んでいるため、jQueryのコンフリクトが発生し、zenbackやjQueryプラグインが正常に動作しなくなるようです。
ということで、対処方法をいくつか紹介します。
3.対処1
zenbackの公式サイトにコンフリクトを解消する方法が記載されています。
具体的には下記の2点です。
- jQueryの関数名を'$'で利用するのではなく、'jQuery'で開始するようにする。
- jQuery lightBox pluginなどのプラグインでは、プラグイン内部で利用するjQueryのバージョンを、コンフリクトしないようなバージョンのjQueryに変更
4.対処2
対処1のひとつめと同じかもしれませんが、noConflict()を使って、次のように修正を行うことで動作するようになります。
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.lightbox-0.5.js"></script>
<script type="text/javascript">
var $j = jQuery.noConflict();
$j(function() {
$j('#gallery a').lightBox();
});
</script>
…中略…
<!-- X:S ZenBackWidget -->
<script type="text/javascript">
document.write(unescape("%3Cscript")+" src='http://widget.zenback.jp/?base_uri=http%3A//user-domain/&nsid=01234567890123345%3A%3A01234567890123345&rand="+Math.ceil((new Date()*1)*Math.random())+"' type='text/javascript'"+unescape("%3E%3C/script%3E"));
</script>
<!-- X:E ZenBackWidget -->
5.対処3
さらに対処方法がないかネットで調べたところありましたので、紹介します。
まず、zenbackのコードの後方(body終了タグの直前など)に、jQueryのコードをまるっと移動します。
<!-- X:S ZenBackWidget -->
<script type="text/javascript">
document.write(unescape("%3Cscript")+" src='http://widget.zenback.jp/?base_uri=http%3A//user-domain/&nsid=01234567890123345%3A%3A01234567890123345&rand="+Math.ceil((new Date()*1)*Math.random())+"' type='text/javascript'"+unescape("%3E%3C/script%3E"));
</script>
<!-- X:E ZenBackWidget -->
…中略…
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.lightbox-0.5.js"></script>
<script type="text/javascript">
$(function() {
$('#gallery a').lightBox();
});
</script>
そして、jQueryを読み込んだ直後に、異なるバージョンのjQueryを結合するための内容(赤色部分)を追加します。
<!-- X:S ZenBackWidget -->
<script type="text/javascript">
document.write(unescape("%3Cscript")+" src='http://widget.zenback.jp/?base_uri=http%3A//user-domain/&nsid=01234567890123345%3A%3A01234567890123345&rand="+Math.ceil((new Date()*1)*Math.random())+"' type='text/javascript'"+unescape("%3E%3C/script%3E"));
</script>
<!-- X:E ZenBackWidget -->
…中略…
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script type="text/javascript">
var $ = jQuery = jQuery.noConflict().extend(true, $);
</script>
<script type="text/javascript" src="js/jquery.lightbox-0.5.js"></script>
<script type="text/javascript">
$(function() {
$('#gallery a').lightBox();
});
</script>
これでjQueryの結合が行われるようです。共通するメソッドは、先に読み込んだ方が優先されるようです。
6.対処4
5項と似ていますが、jQueryのコードをzenbackの後方に移動したあと、読み込むjQueryをzenbackのものに依存させるという手です。
<!-- X:S ZenBackWidget -->
<script type="text/javascript">
document.write(unescape("%3Cscript")+" src='http://widget.zenback.jp/?base_uri=http%3A//user-domain/&nsid=01234567890123345%3A%3A01234567890123345&rand="+Math.ceil((new Date()*1)*Math.random())+"' type='text/javascript'"+unescape("%3E%3C/script%3E"));
</script>
<!-- X:E ZenBackWidget -->
…中略…
<script type="text/javascript" src="js/jquery.lightbox-0.5.js"></script>
<script type="text/javascript">
$(function() {
$('#gallery a').lightBox();
});
</script>
サンプルでは分かりませんが、zenbackがページに表示されていない状態でもjQueryプラグインは正常に動作します。
7.その他
本件とは関係ありませんが、Ajaxで読み込ませたコンテンツに対してjQueryプラグインを適用させる場合にも、IEではzenbackとコンフリクトするようです。
具体的には当ブログのサイドバーの各リストをAjaxで読み込ませたあと、jQueryプラグインで折りたたみさせているのですが、折りたたみ用のjQueryプラグインが認識されません。
zenbackは正常に表示されます。
8.参考
参考サイトは下記です。ありがとうございました。
jQueryによる要素の存在チェックまとめ
jQueryによる要素の存在チェックまとめです。
jQueryを実行する際、「$(selector)」が成功してjQueryオブジェクトが生成されたことを判断したいケースがあるかと思います。なかったらすいません。
ということで、jQueryで要素(jQueryオブジェクト)が1つでも存在することをチェックする方法を調べてみました。実際に動かした結果でまとめてます。
サンプルはscript要素で括ってますが、必要に応じて「$(function(){ ... });」などで括ってください。間違った情報・表現等がありましたら適宜修正しますのでご指摘ください。
1.$(selector)[0]
「$(selector)」で生成されるjQueryオブジェクトは配列のように扱える(配列の基本メソッドが使える訳ではない)ので、0番目の要素をチェックすることで存在チェックを行えます。
<script>
if ($('div')[0]) {
alert('Exist');
} else {
alert('No exist');
}
</script>
2.$(selector).get(0)
get()は、パラメータで指定したインデックスのjQueryオブジェクトに格納されているDOMを取得するメソッドです。パラメータに「0」を指定しないとうまくチェックできないようです。
<script>
if (jQuery('div').get(0)) {
alert('Exist');
} else {
alert('No exist');
}
</script>
3.$(selector).length
lenghtは、jQueryオブジェクトのインデックス数を保持しています。インデックス数が「0」の場合は要素が存在しないと判断できます。
<script>
if ($('div').length) {
alert('Exist');
} else {
alert('No exist');
}
</script>
4.$(selector).size()
size()はjQueryオブジェクトのインデックス数を返却するメソッドです。インデックス数が「0」の場合は要素が存在しないと判断できます。
<script>
if ($('div').size()) {
alert('Exist');
} else {
alert('No exist');
}
</script>
5.$(selector).is('*')
is()は、要素集合のうち、1つでも条件式に合致する要素があればtrueを返すメソッドです。ワイルドカードの「*」を設定することで、指定要素のすべてに合致するかを判定できるようです。
<script>
if ($('div').is('*')) {
alert('Exist');
} else {
alert('No exist');
}
</script>
リロードしたときにjQueryでページの先頭にスクロールさせる方法
ページをリロードしたときに、jQueryでページの先頭にスクロールさせる方法を紹介します。
リンクをクリックしてページの先頭にスクロールさせる方法はネット色々出てきますが、リロードのタイミングでスクロール(=要はページの先頭を表示)させる手段がみつかりませんでした。
別の実験を行っていてこのような動作を行いたいケースが発生したため、少し調べてみました。認識誤りな点がありましたらご指摘ください。
1.JavaScriptのscrollTo()を使ったスクロール
まず、JavaScriptのscrollTo()を使って次のようなコードを記述してみましたが、正常に動作しませんでした。
window.onload = function(){
window.scrollTo(0,0);
}
動作結果は次の通りです。
- Firefox:ページトップに移動するが、スクロールバーは戻らない
- Chrome:ページトップに移動しない(挙動としては一旦トップに戻って、またもとの位置にスクロールされる)
- IE9:ページトップに移動しない(〃)
2.jQueryのscrollTop()を使ったスクロール
次に、jQueryのscrollTop()を使って次のようなコードを記述してみましたが、こちらも正常に動作しませんでした。
$(function() {
var pos = $('html,body').scrollTop();
$('html,body').scrollTop(-pos);
});
- Firefox:ページトップに移動するが、スクロールバーは戻らない
- Chrome:ページトップに移動しない(少し戻るがトップまで戻らない」)
- IE9:ページトップに移動しない
3.jQueryのanimate()を使ったスクロール
最後にjQueryのanimate()で次のようなコードを書いてみたところ、とりあえずどのブラウザでもトップに戻ることができました。
$(function() {
$('html,body').animate({ scrollTop: 0 }, '1');
});
animateの第2パラメータ(duration)を「'1'」としている理由は、「0」では動作しない(jQueryの仕様?)ということと、クォーテーションで括らないとIE9で正常に動作しないためです。また、firefoxはスクロール動作が遅いようです。
以上です。スクロールにこだわった実験ですが、観点がそもそも間違っていて「こうすればリロード前のスクロール状態がクリアできる」という方法があるかもしれません。あしからず。
フォームに設置した複数のsubmitボタン(送信ボタン)をjQueryで制御する
1つのフォームに複数設置したsubmitボタン(送信ボタン)の挙動をjQueryで操作・変更する方法を紹介します。
1.用途
このエントリーでは次の2つのケースを紹介します。
- 1つのフォームに同じ動作を行う送信ボタンを複数設置する
- 1つのフォームに異なる動作を行う送信ボタンを設置する
2.1つのフォームに同じ動作を行う送信ボタンを複数設置する
たとえばページに表示されたフォームなどの上下に送信ボタンがあった方が、スクロール量が減るなどの利便性が高い場合があります。これをHTMLだけで実現するには、form要素(赤色)内にtype属性値「submit」のinput要素(青色)を設置すれば可能です。
<form name="foo" method="post" action="foo.cgi">
<input type="submit" value="送信" />
…中略…
<input type="submit" value="送信" />
</form>
ただし、HTMLだけで実現する場合、form要素内にinput要素を記述しないといけないという制約があるようです。次のマークアップでは送信ボタンをクリックしても動作しません。
<input type="button" value="送信" />
<form id="foo" name="foo" method="post" action="foo.cgi">
…中略…
</form>
<input type="button" value="送信" />
かといってform要素の開始タグと終了タグの記述位置を、送信ボタンを表示したい位置に移動するのもどうかと思われます。
ということで、input要素とjQueryと組み合わせれば送信ボタンを好きな位置に設置する例を示します。ちなみに、input要素は「XHTMLタグ一覧表示ツール」をご覧になればお分かりの通り、div要素やp要素、span要素などの子要素であれば、form要素だけでなく、任意の位置に記述することができます。
具体的には、次のようなjQueryを実装します。HTMLマークアップは動作に必要な要素以外は省略しているのでツッコミなしで。
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script>
$(function(){
$('input[type=button]').click(function() {
$('#foo').submit();
});
});
</script>
<input type="button" value="送信" />
<form id="foo" name="foo" method="post" action="foo.cgi">
…中略…
</form>
<input type="button" value="送信" />
送信ボタン用のinput要素はform要素の外側にあります。送信ボタンをクリックすれば、jQueryのclickイベントでform要素を検索し、submitイベントを実行します。
あるいは、送信ボタンによって動作を変更したい場合があると思います。
2.1つのフォームに異なる動作を行う送信ボタンを設置する
1項で設置したボタンに対し、それぞれ異なる動作を行わせる方法を紹介します。
まず、フォームから起動するCGI(action属性)などを変更するには、次のようにします。input要素にid属性値(赤色)を追加し、それぞれにclickイベントを実装します。clickイベントの中では、form要素のaction属性値を書き換えてからsubmitイベントを実行するようにします。どちらか一方が書き換え不要な場合はform要素のaction属性をそのまま利用しても構いません。
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script>
$(function(){
$('#button1').click(function() {
$('#foo').attr('action', 'bar.cgi');
$('#foo').submit();
});
$('#button2').click(function() {
$('#foo').attr('action', 'hoge.cgi');
$('#foo').submit();
});
});
</script>
<input id="button1" type="button" value="送信" />
<form id="foo" name="foo" method="post" action="foo.cgi">
…中略…
</form>
<input id="button2" type="button" value="送信" />
次に、同じCGIを起動し、クリックされた送信ボタンによってPOSTデータを変更したい場合は、次のようにします。type属性「hidden」のinput要素(赤色)を追加し、clickイベントの中でform要素のinput要素の値を設定してからsubmitイベントを実行します。
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script>
$(function(){
$('#button1').click(function() {
$('input[type=hidden]').val('bar');
$('#foo').submit();
});
$('#button2').click(function() {
$('input[type=hidden]').val('hoge');
$('#foo').submit();
});
});
</script>
<input id="button1" type="button" value="送信" />
<form id="foo" name="foo" method="post" action="foo.cgi">
<input type="hidden" name="data1" value="" />
…中略…
</form>
<input id="button2" type="button" value="送信" />
CGIでは(上の例では)POSTデータの「data1」から値を取得できます。さらに異なるCGIを起動したい場合は、上記の2つのサンプルを組み合わせてください。
以上です。他にも実現方法はあると思いますので色々試してみてください。
フォームの<input type="file" />の値をjQueryでリセット(クリア)する方法
フォームの<input type="file" />の値をjQueryでリセット(クリア)する方法を紹介します。
![]()
1.問題点
フォームの値をリセット(クリア)する場合、通常はtype属性が「reset」のボタンですべてクリアできます。<input type="file" />の値も同様にリセットされます。
HTML
<form id="bar" action="foo.cgi">
<input type="file" />
<input type="reset" value="リセット" />
</form>
JavaScript(jQuery)でリセットしたい場合、次のように記述すればいいように思われます。
HTML
<form id="bar" action="foo.cgi">
<input type="file" id="file" />
<input type="button" value="リセット" />
</form>
jQuery
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script>
$('input[type=button]').click(function(){
$('#file').val('');
});
</script>
Firefoxやchromeでは期待する動作になるようですが、IEではブラウザの仕様(セキュリティ?)で、type属性「file」の値を書き換えることができないようです。
2.値をクリアする方法1
クロスブラウザでtype属性「file」の値をクリアするには、次の方法で実現できます。厳密にはクリアではなく、replaceWith()で要素を置き換えています。
HTML
<form id="bar" action="foo.cgi">
<input type="file" id="file" />
<input type="button" value="リセット" />
</form>
jQuery
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script>
$('input[type=button]').click(function(){
$('#file').replaceWith('<input type="file" id="file" />');
});
</script>
3.値をクリアする方法2
2項よりHTMLマークアップがやや冗長になりますが、次の方法でもクリアできます。
HTML
<form id="bar" action="foo.cgi">
<span id="file"><input type="file" /></span>
<input type="button" value="リセット" />
</form>
jQuery
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script>
$('input[type=button]').click(function(){
$('#file').html($('#file').html());
// または $('#file').html('<input type="file" />');
});
</script>
4.resetボタンでクリアする
本題からそれますが、type属性「reset」のボタンでファイルアップロードフィールドのみをリセットする場合は次のようにします。
HTML
<form id="bar" action="foo.cgi">
<input type="file" id="file" />
<input type="text" id="text" />
<input type="reset" value="リセット" />
</form>
jQuery
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script>
$('input[type=reset]').click(function(){
// resetボタンのデフォルト動作(フォーム全体のクリア)を抑止
e.preventDefault();
$('#file').replaceWith('<input type="file" id="file" />');
});
</script>
preventDefault()を利用して、リセットボタンのデフォルト動作(=全フィールドのリセット)を無効にして、ファイルアップロードフィールドのみをリセットします。
onsubmitの戻り値をfalseにしてsubmitを実行しない(中断させる)方法
JavaScriptで、onsubmitの戻り値をfalseにしてフォームのsubmitを中断させる(実行しない)方法を紹介します。
1.onsubmitイベントとは
onsubmitイベントは、フォームの送信ボタン(type属性がsubmitのボタン)がクリックされた時に発生するイベントです。
<form method="post" action="foo.cgi" onsubmit="foo();">
<input type="text" value="" />
<input type="submit" value="送信" />
</form>
2.submitを中断する(=フォームを送信しない)方法
onsubmitイベントを使ってsubmitを中断するケースとして、送信時にJavaScriptでフォームのチェックをして、フォームデータに未入力の項目がある場合、「return false;」で送信を中止するというパターンがあると思いますが、中止したはずのに送信が実行されてしまうということがあります。
次のソースコードはその例で、未入力の項目がある場合に「return false」を行ってますが、送信は中断されません。
<script type="text/javascript">
function check() {
for(i = 0; i < document.foo.length; i++) {
if (document.foo.elements[i].type == "text") {
if (document.foo.elements[i].value == '') {
alert("未入力の項目があります。");
return false;
}
}
}
}
</script>
<form name="foo" action="foo.cgi" onsubmit="check();">
<input type="text" id="a" value="" />
<input type="text" id="b" value="" />
<input type="submit" value="送信" />
</form>
原因は、赤色で示したform要素のonsubmit属性の記述が誤っているためです。
送信を中止するためには、onsubmit属性で起動した関数の返却値(false)をさらに返却する必要があります。つまり、
onsubmit="関数名"
ではなく、
onsubmit="return 関数名"
としなければなりません。
また、常に送信を中止したい場合は、
onsubmit="関数名; return false;"
と書けばよいでしょう。
先程のサンプルでは、次の青色部分のように修正すれば送信を中止します。
<script type="text/javascript">
function check() {
for(i = 0; i < document.foo.length; i++) {
if (document.foo.elements[i].type == "text") {
if (document.foo.elements[i].value == '') {
alert("未入力の項目があります。");
return false;
}
}
}
}
</script>
<form name="foo" action="foo.cgi" onsubmit="return check();">
<input type="text" id="a" value="" />
<input type="text" id="b" value="" />
<input type="submit" value="送信" />
</form>
「true」はonsubmitイベントのデフォルト返却値なので、OKの場合に「return true;」を明示的に記述する必要はないと思います。
3.jQueryでの記述
jQueryで記述する場合は、次のようになるみたいです。
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script>
$(function(){
$('#foo').submit(function(){
var flag = 0;
// フォームチェック
$(this).find('input[type=text]').each(function(){
if ($(this).val() == '') {
// NGの場合
flag = 1;
return false; // break
}
});
if (flag) {
return false; // return
}
});
});
</script>
<form id="foo" action="foo.cgi">
<input type="text" id="a" value="" />
<input type="text" id="b" value="" />
<input type="submit" value="送信" />
</form>
青色で示した、submit()ブロック内で「return false;」をすればフォームの送信を中止するようです。
each()ブロック内の赤色で示した「return false;」は、each()のループを脱出しているだけなので、間違えないように注意しましょう。
jQueryでセレクタを再指定する方法
jQueryでセレクタ指定で取得したjQueryオブジェクトを使って、さらにセレクタ指定を行う方法です。
追記:to-Rの西畑さんに添削して頂きました。ありがとうございます。
1.問題
次のように、チェックボックスを階層状に並べたマークアップを例に説明します。
注:マークアップが階層状になっていませんが、操作対象のページのマークアップ(CMSから出力されたもの)がそのようになっているのでそのまま掲載しています。
サンプル

マークアップ
<div class="list-item">
<div style="margin-left:0px">
<input type="checkbox" class="foo" id="id_1"> a
</div>
</div>
<div class="list-item">
<div style="margin-left:10px">
<input type="checkbox" class="foo" id="id_2"> b
</div>
</div>
<div class="list-item">
<div style="margin-left:20px">
<input type="checkbox" class="foo" id="id_3"> c
</div>
</div>
やりたいことは、一番下にあるチェックボックスをチェックしたとき、そのひとつ上にある(=上から2つめの)チェックボックスをチェックする、というものです。同様に、真ん中のチェックボックスをチェックすれば一番上のチェックボックスをチェックします。
ちなみに、チェックボックスをチェックしたときのイベント受け取りは次のように記述します。
jQuery(function(){
jQuery(".foo").change(function(){
// ...
});
});
changeイベントのコールバック関数内で「jQuery(this)」を使えば、チェック対象のinput要素のjQueryオブジェクトが取得できます。そこを基点にしてひとつ上にあるinput要素を特定します。
2.解決方法1
一般的な方法として、find()を利用します。
jQuery(function(){
jQuery(".foo").change(function(){
jQuery(this)
.parent().parent().prev().find(".foo")
.attr('checked', 'checked');
});
});
parent()やprev()で要素を移動したあとに赤色で示すfind()を利用すればセレクタで指定できます。
3.解決方法2
こちらはネットで調べてもあまりみつからなかったのですが、セレクタ指定の第2パラメータ(赤色部分)に「コンテキスト」を与える方法があります。
jQuery(function(){
jQuery(".foo").change(function(){
jQuery(".foo",
jQuery(this).parent().parent().prev())
.attr('checked', 'checked');
});
});
コンテキストを指定することで、セレクタで検索する範囲を絞り込むことができます。
以上です。jQueryな方々の添削をお待ちしています。
jQueryでテーブルに行を追加する方法
jQueryでテーブル(table要素)に行を追加する方法を紹介します。
テーブル操作は、テーブル系のjQueryプラグインで色々なことが実現できると思いますが、業務で使っているツールでこの機能がピンポイントで必要になったため自力で作りました。
単に追加するだけであれば後述するappend()とprepend()で大丈夫です。ただアニメーション表示する方法についてはネットで色々探しましたが同様の情報がなかったので試行錯誤して作りました。テーブルを操作する場合の参考になれば幸いです。
1.サンプル
まずはサンプルで動作をご確認ください。
サンプルでは行の追加・削除・全削除が行えます。
2.テーブルの先頭に行を追加する
行をtable要素の先頭に追加するには次のように記述します。
$('tbody').prepend('<tr><td>~</td></tr>');
当初、次のような実装をしていましたが、prepend()で問題ありません。
$('tbody tr:first').before('<tr><td>~</td></tr>');
「tbody tr:first」は、tbody要素の子要素であるtr要素の先頭の要素を指します。「before」はその直前にデータを追加するメソッドです。
3.テーブルの最後に行を追加する
行をtable要素の最後に追加するには、次のように記述します。
$('tbody').append('<tr><td>~</td></tr>');
当初、次のような実装をしていましたが、append()で問題ありません。
$('tbody tr:last').after('<tr><td>~</td></tr>');
「tbody tr:last」は、tbody要素の子要素であるtr要素の最後の要素を指します。「after」はその直後にデータを追加するメソッドです。
4.tr要素の有無を判定する
2項・3項で「tbody tr:first」や「tbody tr:last」を利用する場合、tbodyにtr要素がひとつもない場合は正常に動作しないため、tr要素の有無を判定して挿入するコードを切り替える必要があります。tr要素の有無を判定するには、例えば次の方法があります。
if (jQuery('tbody tr').length) {
// tr要素がある場合の処理
} else {
// tr要素がない場合の処理
}
append()とprepend()を利用すればこのような判定は不要です。
5.アニメーションで行を追加する
一番苦労したのがこの部分です。先頭に追加する場合のjQueryは次のように記述します。
jQuery('tbody').prepend(data);
jQuery('td div').slideDown("fast");
挿入するHTML(上記サンプルの「data」の部分)がキモで、次のようにtd要素の中にdiv要素を仕込みます。
<tr>
<td><div style="display:none">テキスト1</div></td>
<td><div style="display:none">テキスト2</div></td>
<td><div style="display:none">テキスト3</div></td>
</tr>
そして、div要素に対してslideDown()を実行することで、アニメーションを実現します。これはtr要素やtd要素に対してslideDown()を実行しても期待通りの動作にならないためです。
アニメーション表示する場合は、さらにdiv要素に「display:none」を与えておきます。ここではstyle属性で記述していますが、実際にはdiv要素セレクタにCSSを設定しておけばよいでしょう。displayプロパティは、slideDown()を実行したときに自動的に「block」になるようです。
2011.11.02
2項と3項の内容を修正しました。
jQueryでセレクトボックスの複数選択と単一選択を切り替える
jQueryでセレクトボックスの複数選択と単一選択を切り替える方法を紹介します。
1.サンプル
サンプルを用意しましたので動作を確認してください。
以下、サンプルの動作を説明します。次のセレクトボックスがあります。

このセレクトボックスは項目をひとつしか選択できません(単一選択)。

青色のリンクをクリックすれば、複数選択可能なセレクトボックスに切り替わります。

CtrlキーやShiftキーと組み合わせてクリックすれば次のように複数選択できます。

2.コードと解説
サンプルのメインとなるコードは次の通りです。
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js"></script>
<script>
$(function(){
$('.change').click(function(){
if (!$('select').attr('multiple')) {
$('select').attr('multiple','multiple');
$('select').attr('size','20');
$(this).text('複数選択解除');
} else {
$('select').removeAttr('multiple');
$('select').attr('size','1');
$(this).text('複数選択');
}
});
$('input[type=submit]').click(function(){
var list = new Array();
var counter;
$("select option:selected").each(function(){
list[list.length] = $(this).text() + '(' + $(this).val() + ')';
counter++;
});
$("#result").text(list.join());
});
});
</script>
<div><a href="javascript:void(0)" class="change" style="outline:none">複数選択</a></div>
<select id="test">
<option value="" selected="selected">選択してください</option>
<option value="01">北海道</option>
<option value="02">青森県</option>
<option value="03">岩手県</option>
…中略…
<option value="46">鹿児島県</option>
<option value="47">沖縄県</option>
</select>
<input type="submit" value="送信" />
<div id="result"></div>
「複数選択」のリンクをクリックすると、次の部分が動作します。
$('.change').click(function(){
if (!$('select').attr('multiple')) {
$('select').attr('multiple','multiple');
$('select').attr('size','20');
$(this).text('複数選択解除');
} else {
$('select').removeAttr('multiple');
$('select').attr('size','1');
$(this).text('複数選択');
}
});
select要素のmultiple属性を確認して、falseであればmultiple属性とsize属性を指定して、セレクトボックスを複数選択に切り替えます。属性の意味は次のとおりです。
- multiple属性:複数選択を有効にする
- size属性:表示行数
multiple属性が設定されていればelse節を実行してmultiple属性を削除します。複数選択を解除する場合、size属性は最低「1」を設定する必要があるようです。
サンプルではsize属性を書き換えてますが、multiple属性の有無にかかわらず常に同じ値を設定していても問題ありません。
「送信」をクリックしたときには次の部分が動作します。
$('input[type=submit]').click(function(){
var list = new Array();
var counter;
$("select option:selected").each(function(){
list[list.length] = $(this).text() + '(' + $(this).val() + ')';
counter++;
});
$("#result").text(list.join());
});
セレクトボックスの選択項目は「$("select option:selected").each(function(){}」で取得できます。each()の中はfor文と同じ動作になるので、選択項目を配列に設定して、最後にjoinでカンマ区切りにして表示しています。
jQueryでスマホサイト向けに画像サイズを縮小する方法
jQueryでスマホサイト向けに画像サイズを縮小する方法を紹介します。
1.サンプル
次のようなPCサイト用のページがあります。この場合、Movable Typeでページを出力しています。ページで使っている記事内の画像サイズは幅470pxです。
このページをスマホサイト向けに別のページを作り、画像サイズを縮小して表示します。画像サイズは幅280pxに縮小しています。
![]()
2.カスタマイズ
サイズを変更するには、下記のスクリプトをページ内にあるhead終了タグの直前に追加します。
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js"></script>
<script type="text/javascript">
jQuery(function(){
$('img').each(function(){
var max = 280; // 最大幅
var w = $(this).width();
var h = $(this).height();
if (w > max) {
$(this).width(max).height(Math.round((max/w)*h));
}
});
});
</script>
最大幅を示す変数max(ここでは赤色で示す280px)を超える画像について、最大幅に縮小します。maxの値は適宜変更してください。
3.ページをPCサイトと共用したい/ユーザーエージェント別に振り分けたい場合
ページをPCサイトと共用したい場合や、ユーザーエージェント別に振り分けて画像サイズを変更したい場合は、次のようにnavigator.userAgentの判定文を追加し、それぞれに最大値を設定します。
<script type="text/javascript">
jQuery(function(){
$('img').each(function(){
var max = 0;
if (navigator.userAgent.indexOf('iPhone') > 0) {
max = 280; // iPhoneの最大幅
} else if (navigator.userAgent.indexOf('iPad') > 0 ) {
max = 768; // iPadの最大幅
} else if (navigator.userAgent.indexOf('iPod') > 0 ) {
max = 280; // iPodの最大幅
} else if (navigator.userAgent.indexOf('Android') > 0) {
max = 280; // Androidの最大幅
}
var w = $(this).width();
var h = $(this).height();
if (max != 0 && w > max) {
$(this).width(max).height(Math.round((max/w)*h));
}
});
});
</script>
2項と同様、maxの値は適宜修正してください。PCサイトでは画像サイズの縮小を行わないように制御しています。
jQueryのlive関数を使ってAjaxで取得したコンテンツにイベントハンドラを登録する
jQueryのlive関数について紹介します。
live関数の使用例として、コンテンツの折りたたみをサンプルに用います。
1.コンテンツの折りたたみ
h3要素をクリックしたときに、h3要素の次にあるul要素全体を折りたたむには、次のようなjQueryのコードを記述します。実際の動作は「サンプル1」のリンク先で確認できます。
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script>
$(function() {
$("h3").click(function() {
$(this).next().slideToggle(0);
});
});
</script>
<h3>最近のブログ記事</h3>
<ul>
<li>モバイルサイトオープン</li>
<li>業務提携に関するお知らせ</li>
<li>ソリューションセミナー</li>
<li>Movable Type 入門セミナー</li>
<li>オフィシャルサイトオープン</li>
</ul>
または次のようにbind関数を利用して、clickイベントに対応するイベントハンドラを登録します。
…前略…
<script>
$(function() {
$("h3").bind('click',function() {
$(this).next().slideToggle(0);
});
});
</script>
…後略…
2.Ajax+コンテンツの折りたたみ(NG)
ところが、次のようにコンテンツ部分をAjaxで読み出すようにすると、clickイベントが効かなくなります。
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script>
$(function() {
$('#foo').load('data.txt');
$("h3").click(function() {
$(this).next().slideToggle(0);
});
});
</script>
<div id="foo"></div>
Ajaxで読み出すデータ(data.txt)
<h3>最近のブログ記事</h3>
<ul>
<li>モバイルサイトオープン</li>
<li>業務提携に関するお知らせ</li>
<li>ソリューションセミナー</li>
<li>Movable Type 入門セミナー</li>
<li>オフィシャルサイトオープン</li>
</ul>
これではAjaxで取得したデータに含まれる要素に対し、イベントハンドラ登録が行えません。このような事象を回避するためにlive関数を利用します。
3.Ajax+コンテンツの折りたたみ(OK)
live関数は、イベントハンドラ登録時に存在する要素(ここではh3要素)だけでなく、新たに発生する要素に対してもイベントが適用されます。
今回のサンプルで言えば、Ajaxで取得したデータにh3要素が含まれていれば、そのh3要素に対しても、clickイベントのイベントハンドラが有効になります。
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script>
$(function() {
$('#foo').load('data.txt');
$("h3").live('click',function() {
$(this).next().slideToggle(0);
});
});
</script>
<div id="foo"></div>
live関数の第1パラメータに指定できるイベントは下記の10種類です。
- click
- dblclick
- mousedown
- mouseup
- mousemove
- mouseover
- mouseout
- keydown
- keypress
- keyup
live関数の使い方が理解できると、jQueryをさらに活用できそうです。
jQueryによるフォームデータ取得方法のまとめ
jQueryによるフォームデータ取得方法のまとめです。
フォームデータの取得で分かりにくいのは、セレクトボックス・ラジオボタン・チェックボックスの3種類ではないかと思われます。本エントリーではこの3種類にターゲットを絞り、動作サンプルを用いて解説します。「$」は「jQuery」で記述しています。
ネットで検索したところ、まとまった記事がなかったので自作しました。なお、本エントリーに掲載している方法以外にも色々なやり方があると思いますので、一例として参照して頂ければ幸いです。
1.セレクトボックスの値を変更したときに取得
セレクトボックスの値を変更したときに取得するには、changeイベントとval()を組み合わせます。changeイベント内部ではthisが使えます。
(X)HTML
<select id="foo" name="foo">
<option value="aaa">aaa</option>
<option value="bbb">bbb</option>
<option value="ccc">ccc</option>
</select>
jQuery
<script>
jQuery(function() {
jQuery('select#foo').change(function(){
var data = jQuery(this).val();
jQuery('#message').html('セレクトボックスの値は「' + data + '」です');
});
});
</script>
2.フォーム送信時にセレクトボックスの値を取得
フォーム送信時にセレクトボックスの値を取得するには、submitイベントとval()を君合わせます。submitイベント内部では「this+'option:selected'」で指定できます。
(X)HTML
<form id="bar" name="bar">
<select id="foo" name="foo">
<option value="a">a</option>
<option value="b">b</option>
<option value="c">c</option>
</select>
<input type="submit" value="submit" />
</form>
jQuery
<script>
jQuery(function() {
jQuery('form#bar').submit(function(){
var data = jQuery(this + 'option:selected').val();
jQuery('#message').html('セレクトボックスの値は「' + data + '」です');
});
});
</script>
ただし1フォーム内に複数のセレクトボックスがある場合、このコードの書き方ではthisが使えないので、次のようにselect要素のid属性値などを直接指定してください。
…前略…
var data1_1 = jQuery('#foo1 option:selected').val();
var data1_2 = jQuery('#foo2 option:selected').val();
…後略…
3.ラジオボタンを選択したときに実行
ラジオボタンの値を変更したときに取得するには、セレクトボックス同様、changeイベントとval()を組み合わせます。changeイベント内部ではthisが使えます。
(X)HTML
<input type="radio" name="number" value="1" />1
<input type="radio" name="number" value="2" />2
<input type="radio" name="number" value="3" />3
jQuery
<script>
jQuery(function() {
jQuery('input[name="number"]').change(function(){
var data = jQuery(this).val();
jQuery('#message').html('ラジオボタンの値は「' + data + '」です');
});
});
</script>
4.フォーム送信時にラジオボタンの値をチェック
フォーム送信時にセレクトボックスの値を取得するには、submitイベントとval()を君合わせます。submitイベント内部では「this+':checked'」で指定できます。
(X)HTML
<form id="bar" name="bar">
<input type="radio" name="number" value="1" />1
<input type="radio" name="number" value="2" />2
<input type="radio" name="number" value="3" />3
<input type="submit" value="submit" />
</form>
jQuery
<script>
jQuery(function() {
jQuery('form#bar').submit(function(){
var data = jQuery(this + ':checked').val();
jQuery('#message').html('ラジオボタンの値は「' + data + '」です');
});
});
</script>
ただし1フォーム内に複数のセレクトボックスがある場合、このコードの書き方ではthisが使えないので、次のようにinput要素のname属性値などを直接指定してください。
…前略…
var data2_1 = jQuery('[name="number1"]:checked').val();
var data2_2 = jQuery('[name="number2"]:checked').val();
…後略…
5.チェックボックスをチェックしたときに実行
チェックボックスの値を変更したときに取得するには、changeイベントとattr()を組み合わせます。changeイベント内部ではthisが使えます。
(X)HTML
<input type="checkbox" name="confirm" value="1" />confirm
jQuery
<script>
jQuery(function() {
jQuery('input[name="confirm"]').change(function(){
var data = jQuery(this).attr('checked');
jQuery('#message').html('チェックボックスの値は「' + data + '」です');
});
});
</script>
6.フォーム送信時にチェックボックスの状態をチェック
フォーム送信時にチェックボックスの値を取得するには、submitイベントとattr()を君合わせます。
(X)HTML
<form id="bar" name="bar">
<input type="checkbox" name="confirm" value="1" />confirm
<input type="submit" value="submit" />
</form>
jQuery
<script>
jQuery(function() {
jQuery('form#bar').submit(function(){
var data = jQuery('input[name="confirm"]').attr('checked');
jQuery('#message').html('チェックボックスの値は「' + data + '」です');
});
});
</script>
7.1項~6項のすべてを含んだサンプル
jQuery UI Tabsで作ったタブのフォーカスをはずす方法
jQuery UI Tabsで作ったタブをクリックしたときに、タブのフォーカスをはずす方法です。jQuery UI Tabsについては「jQuery UI Tabsを使ってタブを実装する」を参照してください。
1.問題点
jQuery UI Tabsで作ったタブをクリックすると、フォーカスがあたったまま(=クリックしたとき点線が表示)になる場合があり、美しくありません。
下の例では真ん中の「WordPrerssプラグイン」のタブをクリックした状態なのですが、フォーカスがあたっているのでどれが選択されているのかよく分からない状態になってしまってます。

これを次のようにフォーカスを外して、選択したタブがきれいに表示されるように修正します。

2.対処方法
jQuery UI Tabs用の(X)HTMLマークアップが次のようになっている場合、
<div id="tabs">
<ul>
<li><a href="#tabs-1">First</a></li>
<li><a href="#tabs-2">Second</a></li>
<li><a href="#tabs-3">Third</a></li>
</ul>
<div id="tabs-1">aaa</div>
<div id="tabs-2">bbb</div>
<div id="tabs-3">ccc</div>
</div>
ul要素にid属性またはclass属性を追加し、
<div id="tabs">
<ul id="tab">
<li><a href="#tabs-1">First</a></li>
<li><a href="#tabs-2">Second</a></li>
<li><a href="#tabs-3">Third</a></li>
</ul>
<div id="tabs-1">aaa</div>
<div id="tabs-2">bbb</div>
<div id="tabs-3">ccc</div>
</div>
タブを表示するページに次のJavaScriptを設定します。
<script type="text/javascript">
$('#tab a').click(function(){
this.blur();
});
</script>
この対処はjQuery UI Tabsのサンプルコードの流用です。
jQuery UI Tabsを使ってタブを実装する
jQuery UI Tabsを使ってタブを実装する方法を紹介します。
本当は4月1日は毎年エイプリルフールネタをエントリーしているのですが、今年は自粛します。
1.サンプル
以下に簡単なサンプルを用意しましたのでご覧ください。
2.jQuery UI Tabsのダウンロード
jQuery UIのページの「Download」をクリック。

「Deselect all components」をクリックして、すべてのチェックを外します。

「Widgets」の「Tabs」をチェック。

右側にある「design a custom theme」をクリック。

「Theme Roller」でテーマを選択します。「Roll Your Own」タブではすべてを自分でカスタマイズできますが、最初は「Gallery」タブから決まったデザインを選択して、jQuery UIとテーマの対応の感触をつかんだ方がいいでしょう。

ここでは「Start」を選択してみます。カレンダーの部分をクリックすると、ページ右側のサンプルにテーマが反映されます。

タブを「Roll Your Own」に戻すと、「Start」のデザインが反映された状態になっているので(「abc」という部分のデザインが変わっています)、この状態で「Download theme」をクリック。

これで前のページに戻ります。「Theme」に「Start」が選択されていることがわかります。あとはバージョン(本エントリー時点では1.8.11)を選択して「Download」をクリック。

3.jQuery UI Tabsの設定
ダウンロードしたアーカイブを展開し、展開したままのディレクトリ構成でindex.htmlにアクセスすればサンプルが表示されます。

実際に利用するのはjsフォルダと選択したテーマのCSSが入っているcssフォルダです。
head要素に次のように設定します。ダウンロードしたアーカイブにはjquery-1.5.1.min.jsが同梱されていますが、ここでは1.4.2を使ってみます。
<link rel="stylesheet" href="css/start/jquery-ui-1.8.11.custom.css" type="text/css" media="all" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.8.11.custom.min.js"></script>
<script type="text/javascript">
$(function(){
$('#tabs').tabs();
});
</script>
タブのマークアップは次のようになります。タブとコンテンツの対応は、li要素→a要素のhref属性に、対応するid属性値をフラグメント形式(#...)で設定すればOKです。
<div id="tabs">
<ul>
<li><a href="#tabs-1">First</a></li>
<li><a href="#tabs-2">Second</a></li>
<li><a href="#tabs-3">Third</a></li>
</ul>
<div id="tabs-1">aaa</div>
<div id="tabs-2">bbb</div>
<div id="tabs-3">ccc</div>
</div>
フラグメント指定以外に、通常のページリンクにすればAjaxでページを読み込んでくれるというスグレモノです。
<div id="tabs">
<ul>
<li><a href="aaa.html">First</a></li>
<li><a href="bbb.html">Second</a></li>
<li><a href="ccc.hmtl">Third</a></li>
</ul>
</div>
デザインは、一番外側のdiv要素に「id="tabs"」を記述することでテーマが反映されます。実際には次のようにclass属性が設定されます。
<div id="tabs" class="ui-tabs ui-widget ui-widget-content ui-corner-all">
<ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all">
<li class="ui-state-default ui-corner-top ui-tabs-selected ui-state-active"><a href="#tabs-1">First</a></li>
<li class="ui-state-default ui-corner-top"><a href="#tabs-2">Second</a></li>
<li class="ui-state-default ui-corner-top"><a href="#tabs-3">Third</a></li>
</ul>
<div id="tabs-1" class="ui-tabs-panel ui-widget-content ui-corner-bottom">aaa</div>
<div id="tabs-2" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide">bbb</div>
<div id="tabs-3" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide">ccc</div>
</div>
4.起動オプション
jQuery UI Tabsには豊富な起動オプションが用意されています。ここではいくつかのオプションを紹介します。
指定した番号のタブを選択状態にする(番号は0から開始)
$('#tabs').tabs({
selected: 2
});
選択状態のタブをクリックするとコンテンツを折りたたむようにする
$('#tabs').tabs({
collapsible: true
});
クッキーに保存する(jQuery Cookieプラグインとの併用が必要)
$('#tabs').tabs({
cookie: { expires: 30 }
});
タブの切り替えをアニメーションにする(「height: 'toggle'」はタブ切り替え時に縦方向もアニメーション化)
$('#tabs').tabs({
fx: { height: 'toggle', opacity: 'toggle', duration: 300 }
});
Ajaxで読み込んだページをキャッシュする
$('#tabs').tabs({
cache: true
});
タブの切り替えを禁止する
$('#tabs').tabs({
disabled: true
});
複数のオプションを指定するには、次のように設定します。
$('#tabs').tabs({
selected: 2,
fx: { height: 'toggle', opacity: 'toggle', duration: 300 }
});
5.その他
上記で紹介した以外に、jQuery UI Tabsには各種のイベントやメソッドが用意されています。詳しくはjQuery UI Tabsのドキュメントを参照してください。

