- PR -

JavaScriptでappendChildするとレイアウトがおかしくなります。

1
投稿者投稿内容
未記入
常連さん
会議室デビュー日: 2008/03/13
投稿数: 22
投稿日時: 2008-05-04 01:46
こんにちは。教えてください。
ASP.NETでWebアプリを開発しています。質問はJavaScriptについてです。

JavaScriptは初心者で、今一わかってないです。

カレンダーを作るコードを組みました。

取り合えず指定の年月のカレンダーのレイアウトになったtableノードを返すようにしてあるのですが、取得したオブジェクトをどっかのノードにappendChildすると、tdやthノードのcolspanが無効になってしまいます。それで、appendChildではなく、取得したオブジェクトのinnerHTMLをどっかのノードのinnerHTMLに指定すると、ちゃんと指定したとおりのレイアウトになります。

この違いがよくわかりません。というか、どういう仕様なのでしょうか?同じノードをappendChildするのとinnerHTMLで書き加えるので、何で異なる動作になるかが理解できません。

閲覧はIE7だけでやっています。

とても困っています。助けてください。よろしくお願いします。

function Calendar( Y , M , ID ){
this.Year = Y;
this.Month = M;
this.ID = ID;

this.CalendarHTML = function(){
var div , tbl , tbody , thead , td , tr , th , txt , img , ST , ED;

div = CreateNode( "div" , null );
tbl = CreateNode( "table" , null , "id" , this.ID , "border" , "0" , "bgcolor" , "#000000" , "cellspacing" , "1" , "cellpadding" , "3" );
thead = CreateNode( "thead" , null , "bgcolor" , "#FFFFFF" ,"align" , "center" );

tr = CreateNode( "tr" , null , "bgcolor" , "#FFFFFF" );

th = CreateNode( "th" , null , "align" , "center" );
img = CreateNode( "img" , null , "src" , "Images/big_left.GIF" , "alt" , "" ,"onclick" ,"" );
th.appendChild( img );
tr.appendChild( th );

th = CreateNode( "th" , null , "align" , "center" );
img = CreateNode( "img" , null , "src" , "Images/small_left.GIF" , "alt" , "" );
th.appendChild( img );
tr.appendChild( th );

th = CreateNode( "th" , Y + "年" + M + "月" , "colspan" , "3" , "align" , "center" );
tr.appendChild( th );

th = CreateNode( "th" , null , "align" , "center" );
img = CreateNode( "img" , null , "src" , "Images/small_right.gif" , "alt" , "" );
th.appendChild( img );
tr.appendChild( th );

th = CreateNode( "th" , null , "align" , "center" );
img = CreateNode( "img" , null , "src" , "Images/big_right.gif" , "alt" , "" );
th.appendChild( img );
tr.appendChild( th );

thead.appendChild( tr );
tbl.appendChild( thead );

//曜日部分
var tbody = CreateNode( "tbody" , null ,"align" , "center" );
tr = CreateNode( "tr" , null , "bgcolor" , "#FFFFFF" ,"align" , "center" );
td = CreateNode( "td" , "日" ); tr.appendChild( td );
td = CreateNode( "td" , "月" ); tr.appendChild( td );
td = CreateNode( "td" , "火" ); tr.appendChild( td );
td = CreateNode( "td" , "水" ); tr.appendChild( td );
td = CreateNode( "td" , "木" ); tr.appendChild( td );
td = CreateNode( "td" , "金" ); tr.appendChild( td );
td = CreateNode( "td" , "土" ); tr.appendChild( td );
tbody.appendChild( tr );

tr = CreateNode( "tr" , null , "bgcolor" , "#FFFFFF" );

ST = GetDayOfWeek( this.Year , this.Month , 1 );//1日は何曜日かな

if( M == 1 || M == 3 || M == 5 || M == 7 || M == 8 || M == 10 || M == 12 ){
ED = 31;
}else if( M == 4 || M == 6 || M == 9 || M == 11 ){
ED = 30;
}else{
if( Y % 4 == 0 ){
ED = 29;
}else{
ED = 28;
}
}

for( var i = 0; i <= ST + ED + 6 - ( ST + ED ) % 7; i++ ){
if( i - ST + 1 > 31 ){ break; }
if( i % 7 == 0 ){
if( i != 0 ){
tbody.appendChild( tr );
}
tr = CreateNode( "tr" , null , "bgcolor" , "#FFFFFF" );
}

if( i < ST || i > ST + ED ){
td = CreateNode( "td" , "\n" ,"id" , "td" + i ); tr.appendChild( td );
}else{
td = CreateNode( "td" , i - ST + 1 , "id" , "td" + i ); tr.appendChild( td );
}
}

tbody.appendChild( tr );
tbl.appendChild( tbody );
div.appendChild( tbl );

alert( div.innerHTML ) ;

return tbl;
}

}

function CreateNode( Tag , Txt , Attribute ){
var elm = document.createElement( Tag );
if( Txt != null ){
var txt = document.createTextNode( Txt );
elm.appendChild( txt );
}

for( var i = 2; i < arguments.length; i += 2 ){
elm.setAttribute( arguments[ i ] , arguments[ i + 1 ] );
}

return elm;
}
function GetDayOfWeek( Y , M , D ){
if( M <= 2 ){
M += 12;
Y -= 1;
}
return ( Y + parseInt( Y / 4 ) - parseInt( Y / 100 ) + parseInt( Y / 400 ) + parseInt( 2.6 * M + 1.6 ) + D ) % 7;
}
ぴあちゃん
ぬし
会議室デビュー日: 2008/02/07
投稿数: 287
投稿日時: 2008-05-04 04:36
対処方法は・・・・考えられることは、
・ノードを作るだけでは、レンダリングされない。
・colspan="3" の前に 7つあるはずのカラムが見えてないので、レンダリングエンジンのレイアウト計算が正しく出来ない。

<colgroup>追加して、カラムは7つありますよ、って宣言してもダメ。
となると、後は、見えない行を1行追加して、それに7カラム配置する
しかないかな。
むーん、ダメだな。

諦めるのがいいかも。

とりあえず、下のコードコピペして試してごらんアレ。



コード:
<html>
<Head><title>Calendar DEMO </title>
<script>
function Calendar( Y , M , ID ){ 
	this.Year = Y; 
	this.Month = M; 
	this.ID = ID; 
	
	this.CalendarHTML = function(){ 
		var div , tbl , tbody , thead , td , tr , th , txt , img , ST , ED; 
		
		
		div = CreateNode( "div" , null ); 
		tbl = CreateNode( "table" , null , "id" , this.ID , "border" , "0" , "bgcolor" , "#000000" , "cellspacing" , "1" , "cellpadding" , "3" ); 

		var colg = CreateNode("colgroup",null);
		colg.appendChild(CreateNode("col",null, "width", "50"));
		colg.appendChild(CreateNode("col",null, "width", "50"));
		colg.appendChild(CreateNode("col",null, "width", "50"));
		colg.appendChild(CreateNode("col",null, "width", "50"));
		colg.appendChild(CreateNode("col",null, "width", "50"));
		colg.appendChild(CreateNode("col",null, "width", "50"));
		colg.appendChild(CreateNode("col",null, "width", "50"));

		tbl.appendChild(colg);
		
		thead = CreateNode( "thead" , null , "bgcolor" , "#FFFFFF" ,"align" , "center" ); 
		
		tr = CreateNode( "tr" , null , "bgcolor" , "#FFFFFF" ); 
		
		th = CreateNode( "th" , null , "align" , "center" ); 
		img = CreateNode( "img" , null , "src" , "Images/big_left.GIF" , "alt" , "" ,"onclick" ,"" ); 
		th.appendChild( img ); 
		tr.appendChild( th ); 
		
		th = CreateNode( "th" , null , "align" , "center" ); 
		img = CreateNode( "img" , null , "src" , "Images/small_left.GIF" , "alt" , "" ); 
		th.appendChild( img ); 
		tr.appendChild( th ); 
		
		th = CreateNode( "th" , Y + "年" + M + "月" , "colspan" , "3" , "align" , "center" ); 
		var yyyymmTH = tr.appendChild( th ); 
		
		th = CreateNode( "th" , null , "align" , "center" ); 
		img = CreateNode( "img" , null , "src" , "Images/small_right.gif" , "alt" , "" ); 
		th.appendChild( img ); 
		tr.appendChild( th ); 
		
		th = CreateNode( "th" , null , "align" , "center" ); 
		img = CreateNode( "img" , null , "src" , "Images/big_right.gif" , "alt" , "" ); 
		th.appendChild( img ); 
		tr.appendChild( th ); 
		
		thead.appendChild( tr ); 
		tbl.appendChild( thead ); 
		
		//曜日部分 
		var tbody = CreateNode( "tbody" , null ,"align" , "center" ); 
		tr = CreateNode( "tr" , null , "bgcolor" , "#FFFFFF" ,"align" , "center" ); 
		td = CreateNode( "td" , "日" ); tr.appendChild( td ); 
		td = CreateNode( "td" , "月" ); tr.appendChild( td ); 
		td = CreateNode( "td" , "火" ); tr.appendChild( td ); 
		td = CreateNode( "td" , "水" ); tr.appendChild( td ); 
		td = CreateNode( "td" , "木" ); tr.appendChild( td ); 
		td = CreateNode( "td" , "金" ); tr.appendChild( td ); 
		td = CreateNode( "td" , "土" ); tr.appendChild( td ); 
		tbody.appendChild( tr ); 
		
		tr = CreateNode( "tr" , null , "bgcolor" , "#FFFFFF" ); 
		
		ST = GetDayOfWeek( this.Year , this.Month , 1 );//1日は何曜日かな 
		
		if( M == 1 || M == 3 || M == 5 || M == 7 || M == 8 || M == 10 || M == 12 ){ 
			ED = 31; 
		}else if( M == 4 || M == 6 || M == 9 || M == 11 ){ 
			ED = 30; 
		}else{ 
			if( Y % 4 == 0 ){ 
				ED = 29; 
			}else{ 
				ED = 28; 
			} 
		} 
	
		for( var i = 0; i <= ST + ED + 6 - ( ST + ED ) % 7; i++ ){ 
			if( i - ST + 1 > 31 ){ break; } 
			if( i % 7 == 0 ){ 
				if( i != 0 ){ 
					tbody.appendChild( tr ); 
				} 
				tr = CreateNode( "tr" , null , "bgcolor" , "#FFFFFF" ); 
			} 
			
			if( i < ST || i > ST + ED ){ 
				td = CreateNode( "td" , "\n" ,"id" , "td" + i ); tr.appendChild( td ); 
			}else{ 
				td = CreateNode( "td" , i - ST + 1 , "id" , "td" + i ); tr.appendChild( td ); 
			} 
		} 
	
		tbody.appendChild( tr ); 
		tbl.appendChild( tbody ); 
		
		yyyymmTH.colspan = "3";
		
		div.appendChild( tbl ); 
		
		alert( div.innerHTML ) ; 
		
		return tbl; 
	} 
} 

function CreateNode( Tag , Txt , Attribute ){ 
	var elm = document.createElement( Tag ); 
	if( Txt != null ){ 
		var txt = document.createTextNode( Txt ); 
		elm.appendChild( txt ); 
	} 
	
	for( var i = 2; i < arguments.length; i += 2 ){ 
		elm.setAttribute( arguments[ i ] , arguments[ i + 1 ] ); 
	} 
	
	return elm; 
} 
function GetDayOfWeek( Y , M , D ){ 
	if( M <= 2 ){ 
		M += 12; 
		Y -= 1; 
	} 
	return ( Y + parseInt( Y / 4 ) - parseInt( Y / 100 ) + parseInt( Y / 400 ) + parseInt( 2.6 * M + 1.6 ) + D ) % 7; 
}

window.attachEvent("onload",function() {
	var cal = new Calendar("2006","12","divID");
	var obj = cal.CalendarHTML();
	obj.border="2";
	document.body.appendChild(obj);
	document.getElementById("HTMLID").innerHTML = obj.outerHTML;
	setTimeout(function() {
		obj.rows(0).cells(2).colSpan = "3";
	}, 1000);
});
</script>
</head>
<body>
<div id="divID">
</div>
<hr>
<div id="HTMLID">
</div>

</body>
</html>


ぴあちゃん
ぬし
会議室デビュー日: 2008/02/07
投稿数: 287
投稿日時: 2008-05-04 04:43
visibility = "hidden";
で作っておいて、
body 内にペーストしたら、
タイムアウト 0 ms のタイマー起動して
rowSpan="3" 指定して
その中で、visibility = "visible" して
あげればいいね。

忘れてた。

誰か助けてください、ってのは良くない。お馬鹿さんに見えちゃうよ。

ASP.NETなら、素直に Calendarコントロール使うことを薦めます。
もしくは、AjaxToolKitのカレンダー。

# しかしこれが解決したからって、DOM ノードの アペンドは使わないので
# しょ?innerHTML で普通に出来るのだから。だとしたら全然困ってない
# じゃん。



[ メッセージ編集済み 編集者: ぴあちゃん 編集日時 2008-05-04 04:53 ]
未記入
常連さん
会議室デビュー日: 2008/03/13
投稿数: 22
投稿日時: 2008-05-04 15:13
ぴあちゃんさん、お返事ありがとうございます!

なんか駄目そうなので、あきらめますです。

因みに困っているのは本当です。まずASP.NETのサーバーコントロールはあんまり使わないようにしています。社内用のアプリなのですが、このアプリ用のサーバーが1台で、スペックもごく普通のものですから、できるだけクライアントサイドで処理したいのです。

またinnerHTMLすればレイアウトは崩れないのですが、innerHTMLした時点で、自作のカレンダークラスのインスタンスとして参照できなくなるわけで、getElementByIdしないといけなくなっちゃうわけでありまして、それが凄く嫌なのです。やりようはあるでしょうが、要らない手間なきがしてなんか嫌だなあって感じです。

色々な感じです。お返事ありがとうございました!
1

スキルアップ/キャリアアップ(JOB@IT)