同一画面上で「続きを読む」で、残りの文章を表示させる方法

[新着] TAG indexオフライン版 3.0 を準備中です



0   名前: のんの : 2007/03/09(金) 15:01  ID:I8ZiYGpq sub-Q5
ニュースサイトに時々ある、「続きを読む」をクリックすると、画面は変わらずに(別ページに移行せずに)、下に続きの文章が現れるようにしたいと考えています。

以下のスクリプトで無事に表示はされるのですが、クリックしてすべての文章が表示されたときに、「続きを読む」が「文章を閉じる」に変わるようにしたいのです。(※どちらも普通のテキストです)

どなたかアドバイス、どうぞよろしくお願いします。



script部分
-------
function show(inputData) {
var objID=document.getElementById( "layer_" + inputData );
var buttonID=document.getElementById( "category_" + inputData );
if(objID.className=='close') {
objID.style.display='block';
objID.className='open';
}else{
objID.style.display='none';
objID.className='close';
}
}


本文内
--------------
<TD bgcolor="#FFFFFF">最初に表示されるテキスト<BR>
<div id="layer_1" style="display: none;position:relative;" class="close">
<BR>「全文を読む」をクリックして下に表示されるテキスト</div><BR>
<TABLE width="320">
<TR>
<TD align="left">
<a href="javascript:void(0)" id="category_1" onClick="show('1');">続きを読む</a>
</TD>
<TD align="right">最後に一行、引用元などが入る<TD>

1   名前: のんの : 2007/03/09(金) 15:01  ID:I8ZiYGpq sub-Q5
追記//

http://blog.livedoor.jp/jigokuhen00/archives/4465481.html

こちらのサイトで紹介されている方法がもっとも近いと思うのですが、
こちらはブログ用のスクリプトのようで、
どうしてもうまくいきません。

どのように改変したらよいでしょうか?

2   名前: カヅサツ ◆ThCi95HEzw : 2007/03/09(金) 15:01  [URL]  ID:O5hEMlpW sub-r2
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
	"http://www.w3.org/TR/html4/strict.dtd">
<html lang="ja" dir="ltr">
<head>
<title></title>
<style type="text/css">
body{
	color: #000000;
	background-color: #FFCCCC;
}
div.Ar_text{
	color: #000000;
	background-color: #FFFFFF;
	margin: 1em auto;
	padding: 1px;
	width: 70%;
}
div.Ar_text div.section{
	margin: 1em 1em;
}
div.Ar_text p{
	margin: 0em;
}
div.Ar_text p.Ar_Button{
	color: #000000;
	background-color: #CCCCFF;
	width: 320px;
	margin: 1em;
}
</style>
<script type="text/javascript">
function Ar_ChangeMain(Ar_Button){
	var Ar_text = Ar_Button.firstChild.nodeValue;
	var Ar_child = Ar_Button.parentNode.getElementsByTagName('div');
	for (i=0;i<Ar_child.length;i++){
		if(Ar_child[i].className.match(/Ar_main/i)){
			if(Ar_text == '続きを読む'){
				Ar_child[i].style.display = "block";
				Ar_text = document.createTextNode('文章を閉じる');
				Ar_Button.replaceChild(Ar_text, Ar_Button.firstChild);
			}
			else{
				Ar_child[i].style.display = "none";
				Ar_text = document.createTextNode('続きを読む');
				Ar_Button.replaceChild(Ar_text, Ar_Button.firstChild);
			}
		}
	}
}
function Ar_SetButton(){
	if(document.compatMode=="CSS1Compat"){
		var Ar_div = document.getElementsByTagName('div');
		for (i=0;i<Ar_div.length;i++){
			if(Ar_div[i].className.match(/Ar_text/i)){
				var Ar_p = document.createElement('p');
				var Ar_text = document.createTextNode('続きを読む');
				Ar_p.appendChild(Ar_text);
				Ar_p.className = 'Ar_Button';
				Ar_div[i].appendChild(Ar_p);
				Ar_p.onclick = function(){
					Ar_ChangeMain(this);
				}
			}
			if(Ar_div[i].className.match(/Ar_main/i)){
				Ar_div[i].style.display = "none";
			}
		}
	}
}
window.onload = function(){
	Ar_SetButton();
}
</script>
</head>
<body>
<h1>夢野久作</h1>
<div class="section Ar_text">
	<div class="section Ar_first">
		<h2>縊死体</h2>
		<p>どこかの公園のベンチである。</p>
	</div>
	<div class="section Ar_main">
		<p>眼の前には一条の噴水が、夕暮の青空高く高くあがっては落ち、あがっては落ちしている。</p>
		<p>その噴水の音を聞きながら、私は二三枚の夕刊を拡げ散らしている。そうして、どの新聞を見ても、私が探している記事が見当らないことがわかると、私はニッタリと冷笑しながら、ゴシャゴシャに重ねて押し丸めた。</p>
	</div>
</div>
<div class="section Ar_text">
	<div class="section Ar_first">
		<h2>虫の生命</h2>
		<p>炭焼きの勘太郎は妻も子も無い独身者(ひとりもの)で、毎日毎日奥山で炭焼竈(がま)の前に立って煙の立つのを眺めては、淋しいなあと思っておりました。</p>
	</div>
	<div class="section Ar_main">
		<p>今年も勘太郎は炭焼竈に楢の木や樫の木を一パイ詰めて、火を点(つ)けるばかりにして正月を迎えましたが、丁度二日の朝の初夢に不思議な夢を見ました。</p>
		<p>勘太郎は睡っているうちに、どこからともなく悲しい小さい声で歌う唱い声が聞こえて来ました。</p>
	</div>
</div>
</body>
</html>

3   名前: のんの : 2007/03/09(金) 15:01  ID:DRqCzkKR sub-Q5
ありがとうございます!!
無事に解決しました。

ご親切にどうもありがとうございました!

4   名前: 匿名 : 2007/03/09(金) 15:01  ID:UMe4AhfY sub-Gs
>>2
var i; した方が良いのはともかく、以下の部分:
function Ar_SetButton(){
	var Ar_p = document.createElement('p');
	Ar_p.onclick = function(){
		Ar_ChangeMain(this);
	}
}

・Ar_p が DOM ノードを指しており、
・Ar_p.onclick はクロージャへの参照を持ち、
・クロージャは Ar_p への参照を保持している。

つまり DOM ノード Ar_p が循環参照されているため、実は IE、Firefox 等でメモリリークする可能性がある。

なので、(on)unload 時に明示的に *.onclick = null するか、もしくは function(){ Ar_ChangeMain(this); } を Ar_SetButton 関数の外に出してクロージャにしない方が無難。

http://www.microsoft.com/japan/msdn/ie/general/ie_leak_patterns.aspx
http://nanto.asablo.jp/blog/2005/12/04/165848

5   名前: 匿名 : 2007/03/09(金) 15:01  ID:zI2A4Ka1 sub-Cz
ごめん、>>4 で余計なことを言ったかもしれない。

>>2 の場合、クロージャ内で親関数内のノード参照変数(Ar_p)を使用していないので、Ar_p.onclick の設定後に Ar_p = null; か delete Ar_p; して、ノードへの参照を切っておくだけで良い。たぶん。

メモリリーク問題は Fx2 では修正されているはず。IE7 は未確認。

6   名前: カヅサツ ◆ThCi95HEzw : 2007/03/09(金) 15:01  [URL]  ID:O5hEMlpW sub-r2
> Ar_p.onclick の設定後に Ar_p = null; か delete Ar_p; して、ノードへの参照を切っておくだけで良い。たぶん。

ご指摘ありがとうございます。

なお、一見メモリリークを引き起こしそうだが実はそうでないパターンもある。以下の例がそうだ。
メモリリーク問題に関しては、私は理解しているようで理解していないので(というか「参照を持っている/いないの区別をイマイチ理解していない)、
(前略)
<script type="text/javascript">
function Ar_ChangeMain(Ar_Button){
	var Ar_text = Ar_Button.firstChild.nodeValue;
	var Ar_child = Ar_Button.parentNode.getElementsByTagName('div');
	for (var i=0;i<Ar_child.length;i++){
		if(Ar_child[i].className.match(/Ar_main/i)){
			if(Ar_text == '続きを読む'){
				Ar_child[i].style.display = "block";
				Ar_text = document.createTextNode('文章を閉じる');
				Ar_Button.replaceChild(Ar_text, Ar_Button.firstChild);
			}
			else{
				Ar_child[i].style.display = "none";
				Ar_text = document.createTextNode('続きを読む');
				Ar_Button.replaceChild(Ar_text, Ar_Button.firstChild);
			}
		}
	}
}
function Ar_SetButton(){
	if(document.compatMode=="CSS1Compat"){
		var Ar_div = document.getElementsByTagName('div');
		for (var i=0;i<Ar_div.length;i++){
			if(Ar_div[i].className.match(/Ar_text/i)){
				var Ar_p = document.createElement('p');
				var Ar_text = document.createTextNode('続きを読む');
				Ar_p.appendChild(Ar_text);
				Ar_p.className = 'Ar_Button';
				Ar_div[i].appendChild(Ar_p);
				Ar_p.onclick = function(){
					Ar_ChangeMain(this);
				}
				Ar_p = null;
			}
			if(Ar_div[i].className.match(/Ar_main/i)){
				Ar_div[i].style.display = "none";
			}
		}
	}
}
window.onload = function(){
	Ar_SetButton();
}
</script>
(後略)


7   名前: 匿名 : 2007/03/09(金) 15:01  ID:rEkc4Z1y sub-kJ
スレ違いご容赦。間違いがあれば乞うツッコミ。
         script engine                 !         DOM Tree        
                                       !                         
                                       !           root          
                                       !            |            
+------------Function1------------+    !      +-----+-----+      
|                                 |    !      |           |      
| [n1]----------------------------|----!---> node1        |      
|                                 |    !                  |      
| [n2]----------------------------|----!----------> +---node2---+
|                                 |    !            |           |
| [f1]---> +---Function2----+ <---|----!------------|--[click]  |
|          |                |     |    !            |           |
|          | [n1] [n2] [f1] |     |    !            +-----------+
|          |                |     |    !                         
|          +----------------+     |    !                         
|                                 |    !                         
+---------------------------------+    !                         
                                       !                         

・変数([name])は何かを参照する(-->)。

・まず HTML 文書がパースされ、DOM 文書がメモリ内に構築される。
・Function1 内で、DOM ノードを「直接」参照する変数 [n1]、[n2] を作成する(ちなみに、Ar_p は直接の参照だが、Ar_div は直接の参照ではない)。
・Function1 内の関数 Function2 は、親関数内にある全ての変数を参照する。

・関数は実行後、変数と何かとの参照関係を切り、それぞれ破棄されるのを待つ。
・ただし、他から参照されている限りは破棄されない。
・ゆえに、node2 が Function2 を参照している場合、Function2 は破棄されない。
・すると、Function2 が参照している親関数内の変数 [n1]、[n2]、[f1] も破棄されない。
・結果的に、スクリプト世界と DOM ツリー世界とをまたいだ、以下の循環が成立。
* [n2] --> node2 --> [click] --> Function2 --> [n2]
* [n1] --> node1 --> root --> node2 --> [click] --> Function2 -->[n1]
・ページを移動してもなぜかメモリが回収されない。

・手っ取り早い方法として、[n1]-->node1、[n2]-->node2 への参照を切ってしまえば、世界をまたいだ循環は防げる。
・あるいは、[click] が不要になった時点で Function2 への参照を切れば良い。

・どうしても Function2 内で [n1]、[n2] を参照したい場合は工夫が必要(「leak free closure」などで検索するといろいろ見つかる)。
・なお、同一世界内での循環参照は問題ない。

こんなこと、考えずに済むようになれば良いのだけど。

8   名前: カヅサツ ◆ThCi95HEzw : 2007/03/09(金) 15:01  [URL]  ID:O5hEMlpW sub-r2
>>7
すいません。今気づきました。
勉強になります。ありがとうございました。

> こんなこと、考えずに済むようになれば良いのだけど。

うわ難しいよう(泣き笑い)

一覧へ戻る