
リストボックス間で値をコピーしたいと思い、http://jsajax.com/Articles/listbox/339の「このサンプルを編集して試してみる」を参考に変更を行っていたのですが、どうすればできるか分からないことがあったので、アドバイスいただける方がいらっしゃいましたら、ご教示の程、よろしくお願いします。
1. →ボタン押下時、リンク先のプログラムでは移動動作をおこないますが、これを選択中のアイテムが右のリストボックスに存在しなければコピーし、右のリストボックスに存在する場合は何も動作しないようにしたいと思います。
ソース内の下記の部分で削除動作をしているようなので、removeを削除すれば消えなくなると思いますが、そうすると無限ループしてしまうと思います。
while ( fromBox.selectedIndex >= 0 ) {
// 略
fromBox.remove(fromBox.selectedIndex);
}
そのため、上記のwhileではなく、その時選択中のアイテム数を取得し、forなどでループ(その際、selectedIndexの取得方法には工夫が必要?)させるとやりたいことができるのかなと思いましたが、具体的にどう記述すればよいかわかりませんでした。
2. (出来れば)1のコピー後、左のリストボックスのアイテムの中で、
右のリストボックスに存在するアイテムのフォント色を変えたいと思います。
3. ←ボタン押下時、右のリストボックスからアイテムを消去したいと思います。
これは←ボタン押下時のみtoBox.options[toBox.length] = newOption;を実行しなければできるのかなと思いましたが、1番のコピー動作ができていないため、あくまで想像となります。
4. (出来れば)右から左へ移動時、2番の動作が実現できていてフォント色が変更されている場合、基に戻したいと思います。
なお、2と4については、あらかじめスタイルシートにスタイルを定義しておき、
toBox.options.length分、toBox.options[i].valueの値を得た上で、fromBox.options[fromBox.selectedIndex].valueと一致するものがあれば、classを付加し、fromBox.options[fromBox.selectedIndex].valueと一致するものがなければclassを付加しなければできるのかなと思いましたが、具体的にどう記述すればよいかわかりませんでした。
以上、よろしくお願いします。
No.5ベストアンサー
- 回答日時:
#4の内容で間違いがありました。
valueが一致した際のcontinueはwhileに戻らなければいけないのに
forに戻るようになってます。
javascriptで2個上のループに戻る記述を残念ながら私は知らないので
フラグを作って不恰好に修正しました。
何度もすみません><
while ( leftBox.selectedIndex >= 0 ) {
continueflg=false;
if(rightBox.length > 0) {
for(index=0;index<rightBox.length;index++) {
if(leftBox.options[leftBox.selectedIndex].value==rightBox.options[index].value) {
leftBox.options[leftBox.selectedIndex].selected = false;
continueflg=true;
break;
}
}
}
if(continueflg==true){
continue;
}
var newOption = new Option();
newOption.text = leftBox.options[leftBox.selectedIndex].text;
newOption.value = leftBox.options[leftBox.selectedIndex].value;
rightBox.options[rightBox.length] = newOption;
leftBox.options[leftBox.selectedIndex].className="copy";
leftBox.options[leftBox.selectedIndex].selected = false;
ご回答ありがとうございます。
ご教示いただいたソースを試した所、意図した動作になりました。
まだソース自体は見れていませんが、時間が取れ次第ソースの中身を確認させていただくようにします。
このたびはどうもありがとうございました。
以上、よろしくお願いします。
No.4
- 回答日時:
#2です。
複数選択のことを忘れててwhileをばっさり切り落としてしまいました。
修正してみたので時間がありましたら確認してみてください。
<script type="text/javascript">
window.onload = function() {
document.getElementById("btnMoveRight").onclick = moveItems;
document.getElementById("btnMoveLeft").onclick = moveItems;
}
function moveItems() {
var leftBox = document.getElementById("ListBox1");
var rightBox = document.getElementById("ListBox2");
if (this.value == "→") {
if ((leftBox != null) && (rightBox != null)) {
if(leftBox.length < 1) {
alert("リストボックスにアイテムがありません!");
return false;
}
if(leftBox.selectedIndex == -1) {
alert("移動するアイテムを選択してください!");
return false;
}
while ( leftBox.selectedIndex >= 0 ) {
if(rightBox.length > 0) {
for(index=0;index<rightBox.length;index++) {
if(leftBox.options[leftBox.selectedIndex].value==rightBox.options[index].value) {
leftBox.options[leftBox.selectedIndex].selected = false;
continue;
}
}
}
var newOption = new Option();
newOption.text = leftBox.options[leftBox.selectedIndex].text;
newOption.value = leftBox.options[leftBox.selectedIndex].value;
rightBox.options[rightBox.length] = newOption;
leftBox.options[leftBox.selectedIndex].className="copy";
leftBox.options[leftBox.selectedIndex].selected = false;
}
}
}
else if (this.value == "←") {
if ((rightBox != null) && (leftBox != null)) {
if(rightBox.length < 1) {
alert("リストボックスにアイテムがありません!");
return false;
}
if(rightBox.selectedIndex == -1) {
alert("削除するアイテムを選択してください!");
return false;
}
while ( rightBox.selectedIndex >= 0 ) {
if(leftBox.length > 0) {
for(index=0;index<leftBox.length;index++) {
if(rightBox.options[rightBox.selectedIndex].value==leftBox.options[index].value) {
leftBox.options[index].className="none";
break;
}
}
}
rightBox.remove(rightBox.selectedIndex);
}
}
}
return false;
}
</script>
<style TYPE="text/css">
<!--
.copy { color:red;}
.none { color:black;}
-->
</style>
No.3
- 回答日時:
リストボックス間で!て言ってるので、<select>でなく、リスト要素(li)をコピーするやつを作ったぞ。
たったこんだけの機能でもやたらと長くなったので、本体JS「ListItemMove.js」は↓に置いた。https://gist.github.com/779432#comments
HTMLマークアップサンプルは↓なかんじ。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>List Item Move</title>
<style type="text/css">
ul {margin:0px;padding:5px;list-style:none;border:1px solid black;width:50px;height:90px;overflow:auto;}
</style>
<script type="text/javascript" src="ListItemMove.js" charset="UTF-8"></script>
</head>
<body>
<h1>List Item Move</h1>
<table></tbody><tr>
<td>
<ul id="LeftList">
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
<li>Item4</li>
<li>Item5</li>
</ul>
</td>
<td>
<button type="button" id="btnMoveRight" onclick="move1.rightmove();">>></button><br>
<button type="button" id="btnMoveLeft" onclick="move1.leftmove();"><<</button>
</td>
<td>
<ul id="RightList"></ul>
</td>
</tr></tbody></table>
<script type="text/javascript">
var move1 = new ListItemMove(
document.getElementById("LeftList"),
document.getElementById("RightList"),
{selectcolor:"yellow"}
);
</script>
</body>
</html>
ご回答ありがとうございます。
それと大変申し訳ないのですが、リストボックス間と発言させていただいたのは、リンク先がそう書いてある為、それが一般的なのかと思っておりました。
今回の要望はselectとなります。
以上、よろしくお願いします。
No.2
- 回答日時:
もう回答が出てますがせっかく記述したのでおまけ程度に・・・
共通処理になってないのでかっこわるいです。
1.右リストに同じ名称があるかチェックしてあればalert出してます
2.コピーしたらclass:copyを設定してます
3.4.左リストに削除する項目と同じ名称があるかチェックしてあればclass;noneを設定し
右リストからは削除します
※左リストの各optionは最初class:noneを指定しておきます
(<option value="1" class="none">Item1</option>というように)
--スクリプトココカラ--
<script type="text/javascript">
window.onload = function() {
document.getElementById("btnMoveRight").onclick = moveItems;
document.getElementById("btnMoveLeft").onclick = moveItems;
}
function moveItems() {
var leftBox = document.getElementById("ListBox1");
var rightBox = document.getElementById("ListBox2");
if (this.value == "→") {
if ((leftBox != null) && (rightBox != null)) {
if(leftBox.length < 1) {
alert("リストボックスにアイテムがありません!");
return false;
}
if(leftBox.selectedIndex == -1) {
alert("移動するアイテムを選択してください!");
return false;
}
if(rightBox.length > 0) {
for(index=0;index<rightBox.length;index++) {
if(leftBox.options[leftBox.selectedIndex].text==rightBox.options[index].text) {
alert("すでにコピーされています!");
return false;
}
}
}
if ( leftBox.selectedIndex >= 0 ) {
var newOption = new Option();
newOption.text = leftBox.options[leftBox.selectedIndex].text;
newOption.value = leftBox.options[leftBox.selectedIndex].value;
rightBox.options[rightBox.length] = newOption;
leftBox.options[leftBox.selectedIndex].className="copy";
}
}
}
else if (this.value == "←") {
if ((rightBox != null) && (leftBox != null)) {
if(rightBox.length < 1) {
alert("リストボックスにアイテムがありません!");
return false;
}
if(rightBox.selectedIndex == -1) {
alert("削除するアイテムを選択してください!");
return false;
}
if ( rightBox.selectedIndex >= 0 ) {
if(leftBox.length > 0) {
for(index=0;index<leftBox.length;index++) {
if(rightBox.options[rightBox.selectedIndex].text==leftBox.options[index].text) {
leftBox.options[index].className="none";
break;
}
}
}
rightBox.remove(rightBox.selectedIndex);
}
}
}
return false;
}
</script>
<style TYPE="text/css">
<!--
.copy { color:red;}
.none { color:black;}
-->
</style>
--スクリプトココマデ--
この回答への補足
ご回答ありがとうございます。
取り急ぎ動作確認をさせて頂いたところ、下記の現象が見受けられました。
1. 複数を選択して移動しても1件しかコピーしなくなってしまっています(whileを削られているのが原因のようです)。
2. これは私の説明不足ですが、textは一意では、valueは一意のため、valueで比較するように変更させていただきました。
なお、上記現象の解消にまだ着手していない為、私のほうでも動かせていませんが、クラスの付け方などを参考にさせていただきます。
以上、よろしくお願いします。
No.1
- 回答日時:
1.
まず、右側に追加した値を保持するための変数を用意します。
var selectedValue = []; //functionの外側に
whileループの最初に、
if(!selectedValue[fromBox.options[fromBox.selectedIndex].value]) {
で追加済かを判断し、追加していないない場合のみ右側への追加処理を行います。
その際、
selectedValue[fromBox.options[fromBox.selectedIndex].value] = true;
で追加した値を保持しておきます。
削除ではなくコピーするようにするには、
>fromBox.remove(fromBox.selectedIndex);
を
fromBox.options[fromBox.selectedIndex].selected = false;
として、選択状態を解除するだけにすればよさそうです。
これは上記の判断に関係なく必ず行うようにします。
2.
上記の判定を行って、コピーする際にはスタイルを設定する処理を追加すればいいですね。
3.
delete selectedValue[fromBox.options[fromBox.selectedIndex].value];
で配列から値を削除してから
fromBox.remove(fromBox.selectedIndex);
でリストから削除します。
4.
3.で削除する際に左側のリストをループして削除する値と一致するoptionのスタイルを元に戻せばいいですね。
(ここはループするしかないのでしょうかね・・)
ご回答ありがとうございます。
ご回答を読んだ所、selectedValueの使い方が分からなかったので、別の方法で対応しました。
1については、ご教示いただいた下記の記述で大丈夫そうでした。
fromBox.options[fromBox.selectedIndex].selected = false;
2については、duronさんの回答を基に下記の記述を追加する事で大丈夫そうでした。
fromBox.options[fromBox.selectedIndex].className="copy";
3については、←ボタン押下時のみ下記を実行しない事で大丈夫そうでした。
toBox.options[toBox.length] = newOption;
ただ、4については確かにループする必要がありそうですが、
これは今の所どう記述すればよいか分からなかったので、引き続き検討してみたいと思います。
<script type="text/javascript">
window.onload = function() {
document.getElementById("btnMoveRight").onclick = moveItems;
document.getElementById("btnMoveLeft").onclick = moveItems;
}
function moveItems() {
var leftBox = document.getElementById("ListBox1");
var rightBox = document.getElementById("ListBox2");
var fromBox, toBox;
if (this.value == "→") {
fromBox = leftBox; toBox = rightBox;
}
else if (this.value == "←") {
fromBox = rightBox; toBox = leftBox;
}
if ((fromBox != null) && (toBox != null)) {
if(fromBox.length < 1) {
alert("リストボックスにアイテムがありません!");
return false;
}
if(fromBox.selectedIndex == -1) {
alert("移動するアイテムを選択してください!");
return false;
}
var toBoxArray = new Array;
for(i=0; i<toBox.options.length; i=i+1) {
toBoxArray.push(toBox.options[i].value);
}
while ( fromBox.selectedIndex >= 0 ) {
var newOption = new Option();
newOption.text = fromBox.options[fromBox.selectedIndex].text;
newOption.value = fromBox.options[fromBox.selectedIndex].value;
move_ng = false;
for(i=0; i<toBoxArray.length; i=i+1) {
if(toBox.options[i].value == newOption.value) {
move_ng = true;
break;
}
}
if(this.value == "→" && move_ng == false) {
toBox.options[toBox.length] = newOption;
}
if (this.value == "→") {
fromBox.options[fromBox.selectedIndex].className="copy";
fromBox.options[fromBox.selectedIndex].selected = false;
} else if (this.value == "←") {
fromBox.remove(fromBox.selectedIndex);
}
}
}
return false;
}
</script>
<style TYPE="text/css">
<!--
.copy { color:red;}
-->
</style>
以上、よろしくお願いします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Selectボックスの幅を自動で広...
-
コンボボックスに連動するテキ...
-
Selectの中身をfor文で入れる
-
リストボックスの項目の順番を...
-
<input>の選択肢をプルダウンメ...
-
javaScriptの変数をJavaの変数...
-
JavaScriptのfileオブジェクト...
-
<JavaScript>tableタグを入力不...
-
ASP.NETでNAME属性を固定にしたい
-
RegularExpressionValidatorの...
-
クリックされた罫表セルの行番...
-
同じ名前のセレクトがある場合...
-
onchangeイベントを強制的に発...
-
プルダウンで選択された値を別...
-
二次元配列に数字をランダムに...
-
sessionの値でボタンを活性・非...
-
JQueryで2つのテキストフィー...
-
cookie使用時にundefinedと表示...
-
doPostBack 関数について
-
【FORM】 リンク文字で submit...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
CSVファイルを読みこみ、プルダ...
-
Selectボックスの幅を自動で広...
-
セレクトを全て選択されていな...
-
プルダウン 項目が多いので先頭...
-
Selectの中身をfor文で入れる
-
【javascript・PHP】プルダウン...
-
onFocusOutが複数回呼ばれる!
-
jQuery セレクトボックスで選択...
-
JQuery selectが反映されない
-
javascriptでselectボックスの<...
-
onchange等のイベントハンドラ...
-
現在時刻を取得してフォームのs...
-
selectメニューのselectedの位...
-
フォームで開始時間と終了時間...
-
JavaScriptで特定csvファイルを...
-
ブラウザの戻るボタンを押した...
-
UWSCのIE操作でプルダウンを選...
-
リストボックスの項目の順番を...
-
<textarea>にプルダウンを表示...
-
JavaScriptでプルダウンのサイ...
おすすめ情報