スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

jQueryのSELECT操作とIEをちょっとだけ仲良くさせる方法

例えばjQueryプラグインを作ってる時、任意のdivの直後にセレクトボックスを挿入して、他のアクションをキーに$.getでセレクトボックスの値を動的に変えたいよーなんて思う時がある。

書いてみるとこんな感じ


<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(
function() {
$('#body').append('<select id="aaa"></select>');
$('.button').click(function(){
$('#aaa').append('<option>unko</option>');
});
}
);
</script>
<body>
<div id="body">
<input type="button" class="button" id="button" value="add unko" /><br/>
</div>
</body>


実際に動くやつ
サンプル1

このサンプルではボタンを押すたびにセレクトボックスに「unko」が追加される。実際にはクリック時のアクションでajax通信してoptionを動的に変えたりするんだけど、実はこのJS、IEだと動かない。

どうやらappendで追加した空のセレクトボックスにoptionをさらにaddすることが出来ないようだ。

ではid="aaa"のselectをulに変更したらどうか。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(
function() {
$('#body').append('<ul id="aaa"></ul>');
$('.button').click(function(){
$('#aaa').append('<li>tinko</li>');
});
}
);
</script>
<body>
<div id="body">
<input type="button" class="button" id="button" value="change text" /><br/>
</div>
</body>

ulに変えたよ

こちらはちゃんと動く。どうやらセレクトボックス特有の挙動みたい。

色々やってみたがjQueryではどうしようもなく、結局appendの部分だけピュアJSに書き換えることに。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(
function() {
var i=0;
$('#body').append('<select id="aaa"></select>');
$('.button').click(function(){
sBox = window.document.getElementById("aaa");
sBox.options[i] = new Option("unko","unko");
i++;
});
}
);
</script>
<body>
<div id="body">
<input type="button" class="button" id="button" value="add unko" /><br/>
</div>
</body>

変えたのがこっち
これはちゃんと動く



せっかくjQueryでプラグイン作ってるのに一部だけJSとかいけてねえなあ。なんて思っていたら、友人から思わぬ解決策を聞いた。名づけて空のselectを作るときに、ダミーのoptionを入れておく作戦だ!

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(
function() {
$('#body').append('<select id="aaa"><option>dummy</option></select>');
$('.button').click(function(){
$('#aaa').append('<option>unko</option>');
});
}
);
</script>
<body>
<div id="body">
<input type="button" class="button" id="button" value="add unko" /><br/>
</div>
</body>

ダミーoptionを追加したやつ
たしかにIEでも問題なく動くネ!

optionをapendする直前でダミーのoptionを消す処理を入れてやれば一部ピュアJSという不恰好なソースを書かないで済む。また一つIEとjQueryの仲が良くなったよね~。

スポンサーサイト

JQueryを使ってTABLEのを増減する方法【続き】

前回TABLEのTRの増減がJQueryで簡単にできたので、これをプラグイン化すれば汎用的に使えてなおグッドですよネ!というところで話が終わっていたので、その続きを。

とりあえずテーブルのHTMLを用意します。


<table style="table-layout: auto;" border="1" id="tbl">
<tr><td>No.</td><td>入力値</td></tr>
<tr><td>1</td><td><input name="input[]" value="1" type="text"></td></tr>
<tr><td>2</td><td><select><option>A</option><option>B</option></select></td></tr>
</table>
<br><br><input name="add" value="+" type="button"><input name="sub" value="-" type="button"><br>
<input value="登録" type="button">


プラグインにするに当たり、汎用的な動きを定義します。

  • 「+」ボタンを押したら直前の行がコピーされる

  • 「-」ボタンを押したら末尾の行が削除される



つまりテーブル、「+」ボタン、「-」ボタンの3つがワンセットで動作することが前提条件になります。
そこで、テーブル及びボタンには下記の規則があることにします。

  • 「+」ボタンのIDはTABLEのID-add
  • 「-」ボタンのIDはTABLEのID-del


この例ではTABELのIDがtblなので

  • TABLEのID → tbl
  • 「+」ボタンのID → tbl-add
  • 「-」ボタンのID → tbl-del



ソースに反映するとこうなります。

<table style="table-layout: auto;" border="1" id="tbl">
<tr><td>No.</td><td>入力値</td></tr>
<tr><td>1</td><td><input name="input[]" value="1" type="text"></td></tr>
<tr><td>2</td><td><select><option>A</option><option>B</option></select></td></tr>
</table>
<br><br><input name="add" id="tbl-add" value="+" type="button">
<input name="sub" id="tbl-del" value="-" type="button"><br>
<input value="登録" type="button">


いよいよ動作を行うプラグインを作ります。JQueryのプラグインには関数型とメソッド型があり、DOMを変更する場合はメソッド型が推奨されているようなので、今回はメソッド型で作ります。

まずプラグインを定義

$.fn.colCopy = function(){
};

名前は何でもいいですが、今回はcolCopyという名前で作ります。

行の増減を行う対象(今回はtbl)は自由に決めたいので、オプション引数にテーブルのIDを渡すように作り替えます。

$.fn.colCopy = function(options){
options = $.extend({
actItem:'tbl'
},
options);
};

options.actItemにID名を渡すように作ります。上記ではactItemが指定されていなければtblが入ります。

アクションのトリガとなる「+」「-」ボタンのID名もプラグインの中で定義してしまいます。

$.fn.colCopy = function(options){
options = $.extend({
actItem:'tbl'
},
options);

var actId = '#'+options.actItem;
var actAdd = actId+'-add';
var actDel = actId+'-del';
};

セレクタとして使うことを意図しているので、それぞれ先頭に#が入ります。

これでひと通りの準備ができましたので、「+」ボタンクリック時の動作部分を作ります。

$(actAdd).bind('click',function(){
act = $(actId)[0];
if(typeof act != undefined){
nowRow = act.rows.length;
afRow = nowRow + 1;
cloned = $(actId+" tr:nth-child("+nowRow+")" );
$(cloned).clone(true).insertAfter(cloned);
$(actId+" tr:nth-child("+afRow+") input,"+ actId+" tr:nth-child("+afRow+") select").val("");
$(actId+" tr:nth-child("+afRow+") td:nth-child(1)" ).text(nowRow);
}
});

前回はclickイベントを使っていましたが、今回はbindを使います。何となくです。
最初にTABLEのJQueryオブジェクトを変数actに代入してます。どうもこの書き方でないとちゃんとtableオブジェクトを取ってくれないぽい。
次にTABLEオブジェクトが存在したら行数を数えて一番末尾にcloneを追加し、初期化してます。ほぼ前回のコピーですが、ちょっと頭を良くしてinputまたはselectのどっちも初期化してます。

「-」ボタンクリック時の動作部分を作ります。

$(actDel).bind('click',function(){
act = $(actId)[0];
if(typeof act != undefined){
nowRow = act.rows.length;
if(nowRow > 2){
act.deleteRow(nowRow - 1);
}
}
});

完全に前回のコピーです。これでほとんど出来上がりですが、これだとif(nowRow > 2)固定になっていて、TABLEの見出し行が2行だと正しく動かないので、見出し行の行数をオプションで渡すように変更します。

$.fn.colCopy = function(options){
options = $.extend({
actItem:'tbl',
minCol:2
},
options);

var actId = '#'+options.actItem;
var actAdd = actId+'-add';
var actDel = actId+'-del';
var minCol = options.minCol;

--- 中略 ---

$(actDel).bind('click',function(){
act = $(actId)[0];
if(typeof act != undefined){
nowRow = act.rows.length;
if(nowRow > minCol){
act.deleteRow(nowRow - 1);
}
}
});
};


あとはDOM読み込み時にこのプラグインを使うように指定するだけ!

$().ready(function(){
$().colCopy({actItem:'tbl',
minCol:2
});
});


全部まとめたサンプルがこちら
これを別ファイルにして、JQueryとセットで呼び出せばどこでもTABLEの増減ができるネ!

JQueryを使ってTABLEのを増減する方法

WEBアプリを作ってるとき、例えば↓みたいな入力フォームを作る時がある。


No.入力値
1
2



ソースにするとこんな感じ


<table border="1">
<tr><td>No.</td><td>入力値</td></tr>
<tr><td>1</td><td><input type="text" name="input[]" value="1" /></td></tr>
<tr><td>2</td><td><input type="text" name="input[]" value="2" /></td></tr>
<input type="submit" value="登録" />
</table>



こんなフォームでINPUTを動的に変動させる一番シンプルな対処方法は、「+」「-」ボタンを作って、type属性をsubmitにして毎回POSTさせる事ですね。


なのでボタンを追加。


No.入力値
1
2






<table border="1">
<tr><td>No.</td><td>入力値</td></tr>
<tr><td>1</td><td><input type="text" name="input[]" value="1" /></td></tr>
<tr><td>2</td><td><input type="text" name="input[]" value="2" /></td></tr>
<input type="submit" name="add" value="+" /> <input type="submit" name="sub" value="-" />
<input type="submit" value="登録" />
</table>


HTMLが静的なので、当然サーバ側で動的にテキストボックスを増減させる処理が必要。


<?php
$input =$_POST['input'];
$c = count($input);
$c++;
for($i=0;$i<$c;$i++){
echo('<input type="text" name="input[]" />');
}
?>


こんな感じかな。まあ実行してないからバグるかもしれないけど理屈はあってるはず。>

さて、これからが今回の本題です。

Web2.0を追加した2011年代に、静的なHTML+サーバプログラムでいちいち入力フォームを制御ってイケテルの??


    毎    し!       -── ‐-   、  , -─-、 -‐─_ノ   ポ
  小 回    // ̄> ´  ̄    ̄  `ヽ  Y  ,  ´     )   ス え
  学 ポ    L_ /                /        ヽ   ト  |
  生 ス    / '                '           i  !? 毎
  ま ト    /                 /           く    回
  で が    l           ,ィ/!    /    /l/!,l     /厶,
  だ 許   i   ,.lrH‐|'|     /‐!-Lハ_  l    /-!'|/l   /`'メ、_iヽ
  よ さ   l  | |_|_|_|/|    / /__!__ |/!トi   i/-- 、 レ!/   / ,-- レ、⌒Y⌒ヽ
  ね れ   _ゝ|/'/⌒ヽ ヽト、|/ '/ ̄`ヾ 、ヽト、N'/⌒ヾ      ,イ ̄`ヾ,ノ!
   l  る  「  l ′ 「1       /てヽ′| | |  「L!     ' i'ひ}   リ
    の   ヽ  | ヽ__U,      、ヽ シノ ノ! ! |ヽ_、ソ,      ヾシ _ノ _ノ
-┐  は ,√   !            ̄   リ l   !  ̄        ̄   7/
  レ'⌒ヽ/ !    |   〈       _人__人ノ_  i  く            //!
人_,、ノL_,iノ!  /! ヽ   r─‐- 、   「      L_ヽ   r─‐- 、   u  ノ/
      /  / lト、 \ ヽ, -‐┤  ノ  キ    了\  ヽ, -‐┤     //
ハ キ  {  /   ヽ,ト、ヽ/!`hノ  )  モ    |/! 「ヽ, `ー /)   _ ‐'
ハ ャ   ヽ/   r-、‐' // / |-‐ く    |     > / / `'//-‐、    /
ハ ハ    > /\\// / /ヽ_  !   イ    (  / / //  / `ァ-‐ '
ハ ハ   / /!   ヽ    レ'/ ノ        >  ' ∠  -‐  ̄ノヽ   /
       {  i l    !    /  フ       /     -‐ / ̄/〉 〈 \ /!


なんて言われるのでは・・・?

なのでここは一段進歩させ、Javascriptで動的にテキストボックスを増減させることを考えてみましょう。
DOMを操作するため、テーブルにIDを振ります。


<table border="1" id="tbl" >
<tr><td>No.</td><td>入力値</td></tr>
<tr><td>1</td><td><input type="text" name="input[]" value="1" /></td></tr>
<tr><td>2</td><td><input type="text" name="input[]" value="2" /></td></tr>
<input type="submit" name="add" value="+" /> <input type="submit" name="sub" value="-" />
<input type="submit" value="登録" />
</table>



Javasciptでテーブルの行を追加するにはinsertRow()メソッドを、削除するにはdeleteRow()メソッドを使用します。
今回の場合は「+」ボタンで追加、「-」ボタンで削除するので、それぞれのボタンのonClick属性に追加、削除のアクションを追加します。


<input name="add" value="+" type="submit" onclick="addRow()"><input name="sub" value="-" type="submit" onclick="delRow()">



それぞれaddRow()、delRow()が追加、削除ボタンを押したときに呼び出される関数です。


<script>
function addRow(){
var newRow = document.getElementById('tbl');
var i = newRow.rows.length;
var row = newRow.insertRow(i);
var newCell = row.insertCell(0);
newCell.innerHTML = i;
var newCell = row.insertCell(1);
newCell.innerHTML = '<input name="input[]" value="" type="text">';
}

function delRow(){
var delRow = document.getElementById('tbl');
var i = delRow.rows.length;
delRow.deleteRow(i-1);
}
</script>



全部合わせるとこうなる


<script>
function addRow(){
var newRow = document.getElementById('tbl');
var i = newRow.rows.length;
var row = newRow.insertRow(i);
var newCell = row.insertCell(0);
newCell.innerHTML = i;
var newCell = row.insertCell(1);
newCell.innerHTML = '<input name="input[]" value="" type="text">';
}

function delRow(){
var delRow = document.getElementById('tbl');
var i = delRow.rows.length;
delRow.deleteRow(i-1);
}
</script>
<table style="table-layout: auto;" border="1" id="tbl">
<tr><td>No.</td><td>入力値</td></tr>
<tr><td>1</td><td><input name="input[]" value="1" type="text"></td></tr>
<tr><td>2</td><td><input name="input[]" value="2" type="text"></td></tr>
</table>
<br><br><input name="add" value="+" type="submit" onclick="addRow()"><input name="sub" value="-" type="submit" onclick="delRow()"><br>
<input value="登録" type="button">


配列の下限チェックをしてないので、「-」を連打するとオブジェクトが全部消えちゃうけどその辺は割愛するとして、まあこれで一応に増減するフォームがDHTMLで出来ました。

こういうタイプのフォームが他にないのであれば、ひとまずこれで完成と言ってもいいと思いますが、動的にインプットを増減させるっていう需要って意外とあるもので、じゃあこいつを使い回せばいいじゃないと思ってみても

var row = newRow.insertRow(i);
var newCell = row.insertCell(0);
newCell.innerHTML = i;
var newCell = row.insertCell(1);
newCell.innerHTML = '<input name="input[]" value="" type="text">';


部分は、チェックボックスだったり、リストだったりその時々で変わることが多い。
のでもうすこし汎用的にできないものか考えてみる。

動的にTRオブジェクトを生成するわけではなく、必ず1コ前のTRをコピーするという仕様で考えた場合、JQueryにはcloneという大変素敵なメソッドがあるので、それを使えば超楽に出来きますね。

とりあえずJQueryを使うようにソースを修正

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<table style="table-layout: auto;" border="1" id="tbl">
<tr><td>No.</td><td>入力値</td></tr>
<tr><td>1</td><td><input name="input[]" value="1" type="text"></td></tr>
<tr><td>2</td><td><input name="input[]" value="2" type="text"></td></tr>
</table>
<br><br><input name="add" class="add" value="+" type="button"><input name="sub" class="del" value="-" type="button"><br>
<input value="登録" type="button">



先頭でGoogleにホストされてるJQueryを呼び出すように1行追加し、「+」「-」が余計なポストしないようにtypeをボタンに変えます。
操作するテーブルを特定するためにテーブルにIDを指定し、ボタンを押したら追加、削除するアクションのためにボタンにもCLASSを追加しておきます。

スクリプト部を作成

$().ready(function(){
$(".add").click(function(){
var n = document.getElementById("tbl");
var nowRow = n.rows.length;
var cloned = $("#tbl tr:nth-child("+nowRow+")");
afRow = nowRow + 1;
$(cloned).clone(true).insertAfter(cloned);
$("#tbl tr:nth-child("+afRow+") input").val("");
$("#tbl tr:nth-child("+afRow+") td:nth-child(1)").text(nowRow);
});

$(".del").click(function(){
var n = document.getElementById("tbl");
var m = n.rows.length;
if (m <= 2) {
return;
}
n.deleteRow(m-1);
});
});



$().readyは説明不要として(DOMの準備ができたら実行の意)、

$(".add").clickで「+」ボタンが押されたら発生するアクションを記述します。
最初の2行でテーブルの行数を数えます。
nowRowに入るのは末尾の行なので、clonedに末尾の行のJQueryオブジェクトを格納します。

$(cloned).clone(true).insertAfter(cloned);


で末尾のTRオブジェクトの後ろに複製したTRオブジェクトを追加してます。
このときのtrueが結構大事で、これがついてると既存のイベントもコピーできます。
最後の2行は連番と追加したINPUTのクリアを行ってます。

$(".del").clickはクリックされたらTRを削除するイベントです。
余計に消さないようにIF文が入ってます。

全部合わせたのがこちら

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script>
$().ready(function(){
$(".add").click(function(){
var n = document.getElementById("tbl");
var nowRow = n.rows.length;
var cloned = $("#tbl tr:nth-child("+nowRow+")");
afRow = nowRow + 1;
$(cloned).clone(true).insertAfter(cloned);
$("#tbl tr:nth-child("+afRow+") input").val("");
$("#tbl tr:nth-child("+afRow+") td:nth-child(1)").text(nowRow);
});

$(".del").click(function(){
var n = document.getElementById("tbl");
var m = n.rows.length;
if (m <= 2) {
return;
}
n.deleteRow(m-1);
});
});
</script>
<table style="table-layout: auto;" border="1" id="tbl">
<tr><td>No.</td><td>入力値</td></tr>
<tr><td>1</td><td><input name="input[]" value="1" type="text"></td></tr>
<tr><td>2</td><td><input name="input[]" value="2" type="text"></td></tr>
</table>
<br><br><input name="add" class="add" value="+" type="button"><input name="sub" class="del" value="-" type="button"><br>
<input value="登録" type="button">



さらにこれをプラグイン化したらどこでも呼び出せて便利なんだけど、時間の関係で今日はここまで。
プラグイン化はまた後日~。

このカテゴリーに該当する記事はありません。
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。