javascript の getElementById で悩んでいます。

それぞれ違ったID箇所(かなりの量)を、リストボックスで選択するたびに、
「何たら」を違うものに表示させています。

<span id="1">何たら</span>
<span id="2">何たら</span>
<span id="3">何たら</span>
かなりの量で続く↓

if(document.hoge.list.value=1){
document.getElementById('1').innerHTML = 'こうたら';
}else if(document.hoge.list.value=2){
document.getElementById('2').innerHTML = 'こうたら';
}else if ....

リストボックスを選択(例えばID1)したときに変更するところまでは出来ている(ID1は”こうたら”になった)のですが、
再び違うID箇所が選択(ID2)されたときには、以前の変更箇所は初期に戻したい(ID2は”こうたら”に変更、ID1は”何たら”に戻したい)のです。

document.getElementById('1').innerHTML = '何たら';

ID2に上記を追加すればいいことはわかりますが、
リストの何を選ばれるか分かりませんので、現状ではIDの数だけ書かなければなりません。

やりたいことは上書きされるのではなく、選択するたびに新規の動作がほしい。

説明が悪いですが、よろしくお願いしますm(_)m

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2010/12/12 04:19:04
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答7件)

id:HowAreYou No.1

回答回数91ベストアンサー獲得回数17

ポイント10pt

一度に変更されているのが一か所だけなら

  1. 前に変更されたところがあれば元に戻す
  2. 今回変更される箇所の ID と innerHTML を保存
  3. 内容を変更

みたいな処理にしたらどうですか

id:tontonpokopoko

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

参考になりました。

2010/12/12 03:43:25
id:deflation No.2

回答回数1036ベストアンサー獲得回数126

ポイント50pt

idに配列を使ってはいかがでしょうか。

下に例示します。

<span id="span[1]">どーたら</span>
<span id="span[2]">こーたら</span>
<span id="span[3]">あーたら</span>
....
id = document.hoge.list.value;
document.getElementById('span[' + i + ']').innerHTML = 'ふんがー';
id:tontonpokopoko

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

今回は違う方法をとりまししたが、IDの中に配列を入れる方法は使わないので参考になりました。

2010/12/12 03:43:23
id:a-kuma3 No.3

回答回数4973ベストアンサー獲得回数2154

ポイント80pt

こういうこと?

<html>
<style>
</style>
<script>
var values = {
		1: "あ",
		2: "い",
		3: "う",
		"END": "end"
	}

function xxx(sel) {

	var id = sel.options[sel.selectedIndex].value
	var e = document.getElementById(id)
	if (sel.old) {
		sel.old.e.innerHTML = sel.old.value
	} else {
		sel.old = {}
	}
	sel.old.e = e
	sel.old.value = e.innerHTML
	e.innerHTML = values[id]
}
</script>

<body>
<select id="list" onchange="xxx(this)">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<br>

<span id="1">A</span><br>
<span id="2">B</span><br>
<span id="3">C</span><br>

</body>
</html>

id:tontonpokopoko

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

1番シンプルで、勉強になりました。

2010/12/12 03:45:17
id:ymch No.4

回答回数36ベストアンサー獲得回数5

ポイント100pt

出端をくじくようで申し訳ありませんが、IDの値を数字から開始してはいけません。

アルファベットから始まらなければHTML文法違反になります。


なので、次のHTMLを前提として簡単なソースコードにて回答いたします。

<span id="ID1">なんたら1</span><br />
<span id="ID2">なんたら2</span><br />
<span id="ID3">なんたら3</span><br />
<span id="ID4">なんたら4</span><br />
<span id="ID5">なんたら5</span><br />
<span id="ID6">なんたら6</span><br />
<span id="ID7">なんたら7</span><br />
<span id="ID8">なんたら8</span><br />
<span id="ID9">なんたら9</span><br />

<form action="#">
<select size="9" id="listbox" onchange="changeValue();">
    <option value="1">かんたら1</option>
    <option value="2">かんたら2</option>
    <option value="3">かんたら3</option>
    <option value="4">かんたら4</option>
    <option value="5">かんたら5</option>
    <option value="6">かんたら6</option>
    <option value="7">かんたら7</option>
    <option value="8">かんたら8</option>
    <option value="9">かんたら9</option>
</select>
<br />
<input type="button" value="リセット" onclick="reset(); changeValue();" />
</form>

要件としては「選択したもののみ、それに対応するID要素を書き換える。ただし、それ以外はデフォルト文字列にしたい。」

…というものですね。配列を用いれば至極簡単に実装できます。

要素数が増えても長くなるのは文字列を指定する初期化部分だけです。


<script type="text/javascript">
<!--

/*
 * 変数初期化
 */
var idCount = 9; // 該当ID要素の個数を指定する
var defaltValues = new Array(); // 書き換え前の文字列を格納する配列
var newValues = new Array(  // 書き換え後の文字列を配列に格納しておく
    "", // ここは空値にしておく※
    "かんたら1",    // listboxのオプション1つ目が選択された時の変更文字列。
    "かんたら2",    // …以下同様。
    "かんたら3",
    "かんたら4",
    "かんたら5",
    "かんたら6",
    "かんたら7",
    "かんたら8",
    "かんたら9"
);

// 書き換え前の文字列(デフォルト文字列)を取得して配列に格納しておく
for (var i = 1; i <= idCount; i++) {
    defaltValues[i] = document.getElementById("ID" + i).innerHTML;
    // 配列の添字は「0」からだが、紐付けしやすいように「添字1=ID1」とする。
    // つまり、配列先頭のdefaltValues[0]は空値とする。※
}

/*
 * 書き換え実行
 */
function changeValue() {
    selectedItem = document.getElementById("listbox").selectedIndex + 1;
    for (var i = 1; i <= idCount; i++) {
        // listboxで選択されたものに対応するIDの文字列を書き換える
        if (i == selectedItem) {
            document.getElementById("ID" + i).innerHTML = newValues[i];
        }
        // それ以外はデフォルト文字列に戻す
        else {
            document.getElementById("ID" + i).innerHTML = defaltValues[i];
        }
    }
}

//-->
</script>
id:tontonpokopoko

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

わかりやすい説明で時間をかけていただき恐縮です。

今回はinputのhiddenに、IDなどを保存する方法を取らせていただきましたが、

機会があればまたよろしくお願いいたします。

2010/12/12 03:48:26
id:tama213 No.5

回答回数486ベストアンサー獲得回数30

ポイント10pt

この場合なら、2つリストボックスを作って

表示、非表示を切り替えて

入れ替えればよいのでは?

id:tontonpokopoko

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

2010/12/12 03:48:28
id:HowAreYou No.6

回答回数91ベストアンサー獲得回数17

ポイント100pt

ページ遷移を伴わないならクッキーを使う必要は無いと思います。

<html>
  <head>
    <script type="text/javascript">
      // document.getElementById のエイリアス
      function $(id) { return document.getElementById(id) ; }

      // 変更内容
      var a = [
        "タカ",
        "トラ",
        "バッタ"
      ] ;

      // 変更処理
      function onSelect() {
        // listbox の内容を取得
        var i = document.hoge.list.value ;

        // 変更前の内容に戻す
        if (typeof(pi) != 'undefined') $('i' + pi).innerHTML = pc ;

        // 変更する id の内容を退避
        pi = i ;
        pc = $('i' + i).innerHTML ;

        // 変更
        $('i' + i).innerHTML = a[i-1] ;
      }
    </script>
  </head>

  <body>
    <span id="i1">なんたら 1</span><br />
    <span id="i2">なんたら 2</span><br />
    <span id="i3">なんたら 3</span>

    <form name="hoge">
      <select onChange="onSelect();" name="list">
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
      </select>
    </form>
  </body>
</html>

a-kuma3 さんのほうが余計な広域変数使わないのでいいですね。

あと、質問に有るように if 文を並べるよりは、 switch 文の方がいいでしょう。

id:tontonpokopoko

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

わかりやすくてとても参考になりました。

ただエイリアスを扱ったことがほとんどないので、

今後の変更もあるかもしれないと考えて、hidden に保存する方法をとりました。

(自分で理解するため)

ifはswitchに変更しましたが、選択が多いときはswitchを使うということですかね・・

2010/12/12 03:55:49
id:rikuba No.7

回答回数26ベストアンサー獲得回数12

ポイント80pt
<p>
  <span id="word1">何たら</span><br>
  <span id="word2">何たら</span><br>
  <span id="word3">何たら</span>
</p>

<form>

<select id="list">
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
</select>

<input type="button" value="変更" onclick="changeWord();">
<input type="button" value="リセット" onclick="resetWord();">

</form>

<script>
var words = [
  'こうたら1',
  'こうたら2',
  'こうたら3'
];

var lastChange;

function changeWord() {
  var select = document.getElementById('list');
  var number = select.value;
  var element = document.getElementById('word' + number);
  resetWord();
  lastChange = {
    element: element,
    word: element.innerHTML
  };
  element.innerHTML = words[number - 1];
}

function resetWord() {
  if (lastChange) {
    lastChange.element.innerHTML = lastChange.word;
  }
}
</script>

変更を保存しておき、次回の変更で元に戻しています。

Cookieは「次回ページを開いたときのために現在の変更を保存しておきたい」ということであれば必要になりますが、そうでなければ使う必要はないと思います。

id:tontonpokopoko

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

私には1番わかりやすかったです。とても参考になりました。

2010/12/12 04:03:09
  • id:rouge_2008
    変更前はすべて「何たら」なのですか?
    それから、『上書きされるのではなく、選択するたびに新規の動作がほしい。』がどういう事なのかよく分かりませんでした。
    すみませんが、もう少し具体的に説明できないでしょうか?
  • id:tontonpokopoko
    rouge_2008 さん、コメントをありがとうございます。

    変更前は、すべて違う言葉です。

    上書きという意味で言ったのは、
    今のままでは、選択するたびに変更箇所が増えるということです。

    location.reload();

    を使うことも考えましたが、出来るならページの移動なしで考えています。

  • id:tontonpokopoko
    追記、一度に変更されているのが一か所だけです。

  • id:rouge_2008
    変更前に変更箇所のIDとテキストをクッキーに保存しておくのはいかがでしょうか?

    クッキー確認 → あればIDとテキストを元に戻してから、新しい変更箇所のIDと変更前テキストをクッキーに上書き保存(※なければ新規に保存) → 変更箇所のテキストを変更する
  • id:tontonpokopoko
    回答をしてくれた方ありがとうございます。
    ちょっと検証をしてみますので、明日までお時間をください。

    クッキーを使うか、配列を使うかで解決が出来るみたいですね。

    どっちの動作が速いんでしょうか・・?

    配列はfor文を使いかなりのボリュームになるので、
    クッキーのほうがよさそうに思いますが・・
  • id:tontonpokopoko
    回答をしてくれた皆さん、ありがとうございました。
    今回は今後に変更したい個数などを増やすかもしれないと考え、
    皆さんの回答をもとに自分で理解する方法で解決いたしました。
    (inputのhiddenに保存、この方法は誰も言われてないから、もしかしてダメ?)

    最後にrouge_2008さん、いつもお世話になっています。
    お礼がなく申し訳ありません、ありがとうございます。
  • id:ymch
    hiddenを別途に用意したらHTML(DOM)要素が増えてしまうだけのような気も…
    リソースの無駄ですよ。

    functionの外側はグローバル・スコープですので、
    ページを遷移しない限り値は保ち続けられます。
    配列の要素が、例えば1000個以上とかにならなければ動作は遅くなりません。

    プログラムは因数分解だと私は考えています。
    私の書いた回答がスマートだとはこれっぽっちも思っていません。

    例えば、35×18を解く時に
      35×18
      =(7×5)×(9×2)
      =(7×9)×(5×2)
      = 63×10
      = 630
    …と考えるかどうかということです。
    私の書いた回答は、それではありません。

    あくまでも、こういう手法で簡単に出来ますよという、
    そのまま実行できる形で例示したまでのことです。
    (あえて、分かり易さのために無駄な処理方法を採用してます。)

    処理の重さがどうとかいう次元であれば、
    それは因数分解で共通部分を「外に出せば良いだけ」のこと。
    「document.getElementById のエイリアス」というのもその一部だと言えます。
    /*@cc_on _d=document;eval('var document=_d')@*/
    …という有名なおまじないを1行目に使えば劇的に速くなったりもします。

    私の例示したソースの中でも分かりやすい改善点はいくらでもあります。
    (リテラルな部分はファンクションに組み込まないなど)

    質問者様も回答を鵜呑みにせず、
    回答者をビックリさせるようなソースを書くつもりで頑張って下さいね!

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません