dポイントプレゼントキャンペーン実施中!

リストボックス間で値をコピーしたいと思い、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を付加しなければできるのかなと思いましたが、具体的にどう記述すればよいかわかりませんでした。


以上、よろしくお願いします。

A 回答 (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;
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

ご教示いただいたソースを試した所、意図した動作になりました。
まだソース自体は見れていませんが、時間が取れ次第ソースの中身を確認させていただくようにします。

このたびはどうもありがとうございました。

以上、よろしくお願いします。

お礼日時:2011/01/16 04:20

#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>
    • good
    • 0

リストボックス間で!て言ってるので、<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>
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

それと大変申し訳ないのですが、リストボックス間と発言させていただいたのは、リンク先がそう書いてある為、それが一般的なのかと思っておりました。
今回の要望はselectとなります。

以上、よろしくお願いします。

お礼日時:2011/01/14 23:52

もう回答が出てますがせっかく記述したのでおまけ程度に・・・


共通処理になってないのでかっこわるいです。

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で比較するように変更させていただきました。

なお、上記現象の解消にまだ着手していない為、私のほうでも動かせていませんが、クラスの付け方などを参考にさせていただきます。

以上、よろしくお願いします。

補足日時:2011/01/14 22:17
    • good
    • 0

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のスタイルを元に戻せばいいですね。
(ここはループするしかないのでしょうかね・・)
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
ご回答を読んだ所、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>

以上、よろしくお願いします。

お礼日時:2011/01/14 23:49

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!