element.style.leftについて。



0   名前: なり : 2006/08/22(火) 08:01  ID:elQ/0TlY
IE6.0

こんにちは。

javascriptで、画面のテーブルをドラッグで動かすことをやろうとしてます。

そこで、現在の位置を取得する必要があると思いますが、取れません。
何をやっても数値ではなくNaNとなります。

以下がhtmlとjavascriptです。

//HTML
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=MS932"/>
<title>DOMTryページ</title>
<div id="board">

<div id="bar"><input type="button" id="close" value="close" onClick='closeChildWindow(); return false;'></div>
<div id="content"></div>
</div>

</body>
</html>

//javascript
function dragStart(e){

//ウィンドウとのマウスポインタの差
var board = document.getElementById('board');
//boardTopDif = e.clientX - parseInt(board.style.left);
alert(parseInt(document.getElementById('board').style.left));
boardTopDif = e.clientX - board.style.left;
boardLeftDif = e.clientY - parseInt(board.style.top);
window.alert(boardLeftDif);

var bar = document.getElementById('bar');
addListener(bar,'mousemove',moveChildWindow,false);
addListener(bar,'mouseup',dragEnd,false);
addListener(bar,'mouseout',dragEnd,false);

}

です。私が悩んでいるのは何故
alert(parseInt(document.getElementById('board').style.left));
がNaNになるかです。これが数値として扱えない理由が全く分かりません。

どなたか教えてください。





1   名前: sevi- : 2006/08/22(火) 08:01  ID:PQukhZTw
ElementObject.style.XXXは、対象要素に明示的に該当するstyle属性値が設定されていないとnullが返る.
というか、そういった用途にあまり向かないので

alert(parseInt(document.getElementById('board').style.left));
ではなく
alert(parseInt(document.getElementById('board').offsetLeft));
を使うと良いと思われる.


sevi-

2   名前: 匿名 : 2006/08/22(火) 08:01  ID:UzdqIW6b
どうもありがとうございます。

これで数値が取れるようになりました。
ただ、なぜか新規ウインドウのバーの左上の端を掴むと思ったとおりに移動できますが、
それ以外の場所は変な動きになります。

参考書とまったく同じように作っているのに何が悪いのでしょうか?

//html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=MS932"/>
<title>DOMTryページ</title>

<link rel = "stylesheet" type="text/css" href="../css/ajax.css"></link>
<script type="text/javascript" src="../js/ajax.js"></script>
<script type="text/javascript" src="../js/childwindow.js"></script>

</head>
<body onLoad = 'setListener()'>
<a href="#" onClick ='openChildWindow()'>ウィンドウ操作テスト</a>
<p id="text1">ajax構成要素</p>
<div id="empty">


</div>
<form>

<input type="button" onClick='putEmpty(); return false;' value="空の領域に追加">
<input type="button" onClick='changeStyleEmpty(); return false;' value="スタイルチェンジ">
<input type="button" onClick='makeBorder(); return false;' value="ボーダー追加">

</form>

<div id="board">
<div id="bar"><input type="button" id="close" value="close" onClick='closeChildWindow(); return false;'></div>
<div id="content"></div>
</div>

</body>
</html>


//js

var boardTopDif = 10;
var boardLeftDif = 10;



function closeChildWindow(){

var board = document.getElementById('board');
board.style.visibility = 'hidden';
}



function openChildWindow(e){

var board = document.getElementById('board');
board.style.visibility = 'visible';

}


function dragStart(e){

//ウィンドウとのマウスポインタの差
var board = document.getElementById('board');
boardTopDif = e.clientX - parseInt(board.offsetLeft);
boardLeftDif = e.clientY - parseInt(board.offsetTop);

var bar = document.getElementById('bar');
addListener(bar,'mousemove',moveChildWindow,false);
addListener(bar,'mouseup',dragEnd,false);
addListener(bar,'mouseout',dragEnd,false);

}

function moveChildWindow(e){

var board = document.getElementById('board');

board.style.left = (e.clientX - boardLeftDif) + 'px';
board.style.top = (e.clientY - boardTopDif) + 'px';
}

function dragEnd(e){

var bar = document.getElementById('bar');
removeListener(bar,'mousemove',moveChildWindow,false);
removeListener(bar,'mouseup',dragEnd,false);
removeListener(bar,'mouseout',dragEnd,false);

}

function addListener(elem, eventType, func, cap){
elem.attachEvent('on' + eventType, func);
return false;
}

function setListener(e){

var bar = document.getElementById('bar');
addListener(bar,'mousedown',dragStart,false);

}



function removeListener(elem, eventType, func, cap){
if(elem.removeEventListener){
elem.removeEventListener(eventType, func, cap)
}else if(elem.detachEvent){
elem.detachEvent('on' + eventType, func);
}
}

よろしくお願いします。

3   名前: sevi- : 2006/08/22(火) 08:01  ID:PQukhZTw
書籍に書いてあるコードが正常に動くとは限らない.
書籍に書いてあるコードを正確に記述したとも限らない.

取りあえず文書内で外部参照しているCSSファイルとJSファイルのコードが足りない
ようなので,助言は不可能だ.申し訳ない.

sevi-

4   名前: Z ◆XTzyosZXcL : 2006/08/22(火) 08:01  ID:7S9Va0oj
>>2
>参考書とまったく同じように作っているのに何が悪いのでしょうか?
>>3でsevi-さんがおっしゃていいるとおりです。
 とりあえずHTML(XHTML)部分だけでも下記文法チェッカでチェックして修正されることをお奨めします。

http://htmllint.itc.keio.ac.jp/htmllint/htmllint.html

>charset=MS932
 WWWに公開するHTML(XHTML)には、下記資料にある符号化方式に限定したほうがよいと思います。

日本語と文字コード:
http://www.kanzaki.com/docs/jcode.html

#フォーム関係は出来ればCGIなどサーバ側スクリプトを使うことをお奨めします。

5   名前: なり : 2006/08/22(火) 08:01  ID:UzdqIW6b
すみません。以下がすべてのHTMLとJSとCSSです。
赤い文字をクリックすると、ウィンドウ見たいなdivが出ます。

それをドラッグして動かしたいのですが、今は、最初にドラッグして動かそうとすると
何故か、座標軸0,0へ移動してしまいます。
それ以降は、普通に、移動できるのですが。

これは、どこに問題があると思われますか??

//HTML
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"/>
<link rel = "stylesheet" type="text/css" href="../css/ajax.css"></link>
<script type="text/javascript" src="../js/cngwindow.js"></script>
<title></title>
</head>

<body >
<div width ="800">
<a href="#" value="board" onClick ='openChildWindow(this.value)'>ウィンドウ操作テスト</a>
</div>
<div id="board" value="board">
<div id="bar"><input type="button" id="close" value="close" onClick='closeChildWindow(board.value); return false;'></div>
<div id="content"></div>
</div>
<div id="board1" value="board1">
<div id="bar1"><input type="button" id="close" value="close" onClick='closeChildWindow(board1.value); return false;'></div>
<div id="content1"></div>
</div>

</body>

</html>



6   名前: なり : 2006/08/22(火) 08:01  ID:UzdqIW6b
さっきの続きのJSです。

//Javascript

var offsetX = 0;
var offsetY = 0;
var moveobj = 0;

//ウィンドウを閉じる
function closeChildWindow(elem){

var div = document.getElementById(elem);
div.style.visibility = 'hidden';
}


//ウィンドウを開く
function openChildWindow(elem){

var elem = document.getElementById(elem);
elem.style.visibility = 'visible';

}

//アクション追加
function addAction(elem){

var div = document.getElementById(elem);
div.onmousedown = startDrag;
}

//ドラッグスタート
function startDrag(e){

//マウスカーソルはevent.clientXと、event.clientY
//どれだけスクロールしたかは、document.body.scrollLeftとdocument.body.scrollTop
//そこから、現在のオブジェクトの位置を引けば、動かす値が出る。

offsetX = event.clientX + document.body.scrollLeft - this.style.posLeft;
offsetY = event.clientY + document.body.scrollTop - this.style.posTop;

this.onmousemove = moveDrag;
this.onmouseup = endDrag;
this.onmouseout = endDrag;
return false;

}

//ドラッグ中
function moveDrag(e){

moveobj = this;
moveobj.style.left = event.clientX + document.body.scrollLeft - offsetX;
moveobj.style.top = event.clientY + document.body.scrollTop - offsetY;
return false;
}

//ドラッグ終了
function endDrag(e){

offsetX = 0;
offsetY = 0;

this.onmousemove = null;
this.onmouseout = null;
this.onmouseup = null;
moveobj = null;
}

//ドラッグから外れたら
function outDrag(e){

offsetX = 0;
offsetY = 0;

this.onmousemove = null;
this.onmouseout = null;
this.onmouseup = null;

}

window.onload = function(){

addAction('board');
}


7   名前: なり : 2006/08/22(火) 08:01  ID:UzdqIW6b
続きのcssです。

//CSS

body {
margin-left: 0px;
margin-top: 0px;
margin-right: 0px;
margin-bottom: 0px;
width:800;
}

#text1 {
border-top-style: none;
border-right-style: none;
border-left-style: none;
border-bottom-width: 1px;
border-bottom-style: solid;
background-color: #F8F3FD;

.text2 {

background-color: #CCCC2C;
font-family: Gergia, "MS 明朝";

}


p{
font-size: x-small;

}

a{
color: red;
font-size: 10px;
text-decoration: none;
}
a:hover {
font-size: 12px;
color: #297287;
text-decoration: underline
}

.programmed{

color: blue;
font-size: 10px;
font-weight: bold;
font-family: helvetica;

}

#board{

position:absolute;
visibility:hidden;
background-color:#dddddd;
border-top:1px solid #eeeeee;
border-right:1px solid #4c4c4c;
border-left:1px solid #eeeeee;
border-bottom:1px solid #4c4c4c;
width:200px;
padding:0px;
height:100px;
filter:alpha(opacity=30);
-moz-opacity:0.3;
opacity:0.3;
cursor:all-scroll;
left:120;
top:220;
}

#bar{
position:absolute;
background-color:#cccccc;
border-top:1px solid #eeeeee;
border-right:1px solid #eeeeee;
border-left:1px solid #eeeeee;
border-bottom:1px solid #eeeeee;
text-align:right;
width:100%;

}
#board1{

position:absolute;
visibility:hidden;
background-color:#dddddd;
border-top:1px solid #eeeeee;
border-right:1px solid #4c4c4c;
border-left:1px solid #eeeeee;
border-bottom:1px solid #4c4c4c;
width:200px;
padding:0px;
height:100px;
filter:alpha(opacity=30);
-moz-opacity:0.3;
opacity:0.3;
left:120;
top:220;
}

#bar1{
position:absolute;
background-color:#cccccc;
border-top:1px solid #eeeeee;
border-right:1px solid #eeeeee;
border-left:1px solid #eeeeee;
border-bottom:1px solid #eeeeee;
text-align:right;
width:100%;

}
#content1{
color:#000000;
paddinf:10px;

}

#close{
font-size:10px;

}

#content{
color:#000000;
paddinf:10px;

}


8   名前: sevi- : 2006/08/22(火) 08:01  ID:A5/hQl8Z
現象を確認した.
問題を特定し修正と改良を施したソースを以下に提示する.

・onmouseoutは設定しない方が良い.なぜなら、
カーソル移動の方が対象DIVの移動処理より早くなるので、
onmouseoutに解除を登録すると、高速ドラッグする事が
難しくなってしまうからである.

そういった理由により,onmousemove等イベントハンドラは
bodyに設定するのが妥当と考える.

取りあえずIEしか考慮してないようなので動作検証もIEに限定
した.後は自分でやるように.

sevi-

//ウィンドウを閉じる
function closeChildWindow(id_elem)
{
	document.getElementById(id_elem).style.visibility = 'hidden';
}

//ウィンドウを開く
function openChildWindow(id_elem)
{
	document.getElementById(id_elem).style.visibility = 'visible';
}

//アクション追加
function addAction(id_elem)
{
	var div = document.getElementById(id_elem);
	div.onmousedown = startDrag;
	
	var iOffsetX;
	var iOffsetY;
	var fn_body_onmousemove;
	var fn_body_onmouseup;
	function startDrag()
	{
		iOffsetX = event.offsetX;
		iOffsetY = event.offsetY;
		fn_body_onmousemove = document.body.onmousemove;
		fn_body_onmouseup = document.body.onmouseup;
		document.body.onmousemove = moveDrag;
		document.body.onmouseup = endDrag;
		return false;
	}
	function moveDrag()
	{
		div.style.left = event.clientX - iOffsetX;
		div.style.top = event.clientY - iOffsetY;
		return false;
	}
	function endDrag()
	{
		document.body.onmouseup = fn_body_onmouseup;
		document.body.onmousemove = fn_body_onmousemove;
	}
}

window.onload = function(){addAction('board');}

9   名前: なり : 2006/08/22(火) 08:01  ID:UzdqIW6b
どうもありがとうございます。
onmouseoutがあると、高速ドラッグに対応できないなんて知りませんでした。。

ただ、なんかいまいち理解できない点があります。

私のソースで、
offsetX = event.clientX + document.body.scrollLeft - this.style.posLeft;
offsetY = event.clientY + document.body.scrollTop - this.style.posTop;

どうも結局この式をoffsetXYに当てた場合に原点の座標にいってしまうみたいです。

offsetX = event.offsetX
offsetY = event.offsetYとすると、原点にいく問題は起こりません。

moveobj.style.left = event.clientX + document.body.scrollLeft - offsetX;

これらのそれぞれの要素をalertで表示すると、
event.clientX =240
document.body.scrollLeft = 0
offsetX = 0
moveobj.style.left = 0
と例えば出てくるのですが、明らかに原点座標とは程遠いのに、
なんで、座標に戻るのか考え付かないです。
スタイルシートでleftやtopを定義してないからかとも思ったのですが、違うみたいです。








10   名前: sevi- : 2006/08/22(火) 08:01  ID:A5/hQl8Z
原因の説明を忘れていたようだ.
用事があったので回答が遅くなり、申し訳ない.

マウスクリック時、以下の二つの変数に初期化値を与えている.

offsetX = event.clientX + document.body.scrollLeft - this.style.posLeft;
offsetY = event.clientY + document.body.scrollTop - this.style.posTop;

が、本来この二つの変数には、ドラッグ対象となる要素の左上隅の座標から
マウスクリックされた座標までの相対距離が代入されなくてはならない.
が、上記コードはそのようになっておらず、結果としてウインドウの左上隅
の座標からマウスクリックされた座標までの相対距離が代入されている.

マウス移動時は、マウスの座標より上記算出された相対距離を引いた値を
ドラッグ対象の座標に逐次代入する.

よって、結果、クリック後の最初のマウス移動の際、演算結果はほぼ0
もしくは0となり、瞬時に左上隅に対象は移動してしまう.

sevi-

11   名前: Pid : 2006/08/22(火) 08:01  ID:qX78Rjxr
offsetLeft/offsetTop と style.left/top とのピクセル値には微妙なズレが生じることがあるため,

・初期化時に offsetLeft/Top を取得し style.left/top に設定
・以後は style.top/left のみで処理する

ことをおススメします。また,style.left/top は CSS の left/top プロパティですから,単位が必須です。


あと,>>0 では「テーブル」とお書きになっていながら実際には div 要素をお使いなのでほっとしましたが (^^;),(素の状態の)table 要素のドラッグ移動は,実はかなり大変だったりします。

一覧へ戻る