具体性に欠けるタイトルで申し訳ありません。
現在、Ruby on Railsを用いたアプリケーションの作成を行っております。
例えば、選択できる要素に
- りんご
- みかん
- いちご
- バナナ
- もも
の5つの要素があるとして、
またセレクトボックスは3つあるとします。
(セレクトボックス1、2、3とします)
この時、セレクトボックス1で「りんご」を選択した場合、
セレクトボックス2と3では「みかん」、「いちご」、「バナナ」、「もも」しか選べないようになり、
またセレクトボックス1と2でそれぞれ「りんご」と「みかん」を選んだ場合、
セレクトボックス3では「いちご」、「バナナ」、「もも」しか選べなくなる、といった実装を行いたいです。
どのセレクトボックスから選ぶのかは、順不同としたいです。
このような場合、どのようなコードを書けば良いのでしょうか?
おそらくJavaScriptを使うのだろうと言うことはわかるのですが、そこから手がつけられない状況です・・・。
どなたかわかる方がいらっしゃいましたら、よろしくお願いいたします。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+2
ざっくり書いてみました。どうだろー
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<script>
$(function() {
// class="test-list" が選択された時のイベント
$(".test-list").on("change", function() {
// 「.test-list に属するoptionで」「valueが空でない」「現在選択中」の value を取得して
// 配列に溜めておく
var selectedValues = [];
$(".test-list option:not([value='']):selected").each(function() {
var $opt = $(this);
selectedValues.push($opt.val());
});
// 「.test-list に属するoptionで」「valueが空でない」「現在選択中ではない」ものをloopで回す
$(".test-list option:not([value='']):not(:selected)").each(function() {
var $opt = $(this);
var val = $opt.val();
// チェック対象のoptionのvalueが、selectedValuesに存在するものならdisabledにする
// そうでないならdisabled解除
if ($.inArray(val, selectedValues) >= 0) {
$opt.prop("disabled", true);
} else {
$opt.prop("disabled", false);
}
});
});
});
</script>
</head>
<body>
<div>
選択1:
<select class="test-list">
<option value="">未選択</option>
<option value="red">あか</option>
<option value="blue">青</option>
<option value="yellow">YELLOW</option>
</select>
</div>
<div>
選択2:
<select class="test-list">
<option value="">未選択</option>
<option value="red">あか</option>
<option value="blue">青</option>
<option value="yellow">YELLOW</option>
</select>
</div>
<div>
選択3:
<select class="test-list">
<option value="">未選択</option>
<option value="red">あか</option>
<option value="blue">青</option>
<option value="yellow">YELLOW</option>
</select>
</div>
</body>
</html>
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+2
順不同で選択だけしたいのなら、<select multiple>
を使えば何も考えずに実装できます(参考)。
ただし、使い勝手は良くないので、別なGUIライブラリを入れるほうがいいでしょう。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+2
もっと効率的な処理があるような気がしますが、とりあえず動くバージョン
window.addEventListener('DOMContentLoaded', function(e){
var nodes=document.querySelectorAll('.s');
Array.prototype.forEach.call(nodes,function(n){
n.addEventListener('change',function(){
Array.prototype.forEach.call(nodes,function(n){
Array.prototype.forEach.call(n.querySelectorAll('option:disabled'),function(n){
n.disabled=false;
});
});
Array.prototype.map.call(nodes,function(n){
return n.selectedIndex;
}).filter(function(idx){
return idx>0;
}).forEach(function(idx){
Array.prototype.forEach.call(nodes,function(n){
if(n.selectedIndex!==idx) n.querySelectorAll('option')[idx].disabled=true;
});
});
});
});
});
<select name="s1" class="s">
<option value="">------</option>
<option value="りんご">りんご</option>
<option value="みかん">みかん</option>
<option value="いちご">いちご</option>
<option value="バナナ">バナナ</option>
<option value="もも">もも</option>
</select>
<select name="s2" class="s">
<option value="">------</option>
<option value="りんご">りんご</option>
<option value="みかん">みかん</option>
<option value="いちご">いちご</option>
<option value="バナナ">バナナ</option>
<option value="もも">もも</option>
</select>
<select name="s3" class="s">
<option value="">------</option>
<option value="りんご">りんご</option>
<option value="みかん">みかん</option>
<option value="いちご">いちご</option>
<option value="バナナ">バナナ</option>
<option value="もも">もも</option>
</select>
valueの比較バージョン
window.addEventListener('DOMContentLoaded', function(e){
var nodes=document.querySelectorAll('.s');
Array.prototype.forEach.call(nodes,function(n){
n.addEventListener('change',function(){
Array.prototype.forEach.call(nodes,function(n){
Array.prototype.forEach.call(n.querySelectorAll('option:disabled'),function(n){
n.disabled=false;
});
});
Array.prototype.map.call(nodes,function(n){
return n.value;
}).filter(function(v){
return v!=="";
}).forEach(function(v){
Array.prototype.forEach.call(nodes,function(n){
if(n.value!==v) n.querySelector('option[value='+v+']').disabled=true;
});
});
});
});
});
<select name="s1" class="s">
<option value="">------</option>
<option value="りんご">りんご</option>
<option value="みかん">みかん</option>
<option value="いちご">いちご</option>
<option value="バナナ">バナナ</option>
<option value="もも">もも</option>
</select>
<select name="s2" class="s">
<option value="">------</option>
<option value="もも">もも</option>
<option value="みかん">みかん</option>
<option value="バナナ">バナナ</option>
<option value="いちご">いちご</option>
<option value="りんご">りんご</option>
</select>
<select name="s3" class="s">
<option value="">------</option>
<option value="いちご">いちご</option>
<option value="みかん">みかん</option>
<option value="りんご">りんご</option>
<option value="もも">もも</option>
<option value="バナナ">バナナ</option>
</select>
補足
デフォルト値がある場合の処理
<script>
window.addEventListener('DOMContentLoaded', function(e){
var nodes=document.querySelectorAll('.s');
Array.prototype.forEach.call(nodes,function(n){
n.trigger=function(eventStr){
if (document.createEvent) {
var e = document.createEvent("HTMLEvents");
e.initEvent(eventStr, true, true );
return this.dispatchEvent(e);
} else {
var e = document.createEventObject();
return this.fireEvent("on"+eventStr, e);
}
};
n.addEventListener('change',function(){
Array.prototype.forEach.call(nodes,function(n){
Array.prototype.forEach.call(n.querySelectorAll('option:disabled'),function(n){
n.disabled=false;
});
});
Array.prototype.map.call(nodes,function(n){
return n.value;
}).filter(function(v){
return v!=="";
}).forEach(function(v){
Array.prototype.forEach.call(nodes,function(n){
if(n.value!==v) n.querySelector('option[value='+v+']').disabled=true;
});
});
});
});
nodes[0].trigger('change');
});
</script>
<select name="s1" class="s">
<option value="">------</option>
<option value="りんご">りんご</option>
<option value="みかん">みかん</option>
<option value="いちご" selected>いちご</option>
<option value="バナナ">バナナ</option>
<option value="もも">もも</option>
</select>
<select name="s2" class="s">
<option value="">------</option>
<option value="もも">もも</option>
<option value="みかん">みかん</option>
<option value="バナナ">バナナ</option>
<option value="いちご">いちご</option>
<option value="りんご" selected>りんご</option>
</select>
<select name="s3" class="s">
<option value="">------</option>
<option value="いちご">いちご</option>
<option value="みかん" selected>みかん</option>
<option value="りんご">りんご</option>
<option value="もも">もも</option>
<option value="バナナ">バナナ</option>
</select>
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.10%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
defghi1977
2018/03/29 17:20
順序選択ってこと?
yomigi
2018/03/29 17:27
順序選択という言葉の意味がよくわかってはいないのですが・・・。おそらく私が行いたいのはその実装だと思います。
defghi1977
2018/03/29 17:28
ああ、すみません 「りんご・みかん・いちご」の並び替えをしたいということですかね
yomigi
2018/03/29 17:34 編集
申し訳ありません、私の認識が間違っておりました。いえ、そういうことではございません。本文に追記を行いました。
defghi1977
2018/03/29 17:39
目的が、「複数の選択肢から順不同で幾つかを選ぶ」ということですね
yomigi
2018/03/29 17:59
はい、そのような実装を行いたいです。