dポイントプレゼントキャンペーン実施中!

オブジェクトがありませんとエラーが出てしまいます。
operaやNetscapeは動くようなのですがIEは動きません。
document.getElementById(target).style.top = y-offx+"px";
の部分でエラーがでるようなのですが。
出さないためにどうすれば良いかが、分かりません。
よろしくお願いします。

<html>
<head>
<title>ドラッグして移動する</title>
<script type="text/javascript"><!--
if(window.addEventListener)window.addEventListener("load",loadScript,false);
if(window.attachEvent)window.attachEvent("onload",loadScript);

//関数ロード
function loadScript(){
///ドラッグ用ロード
flag=false;
Menu=new Array("menu1","menu2","menu3");
for(i=0;i<Menu.length;i++){
XMenu=window.document.getElementById(Menu[i])
if(XMenu.addEventListener)XMenu.addEventListener("mousedown",dragOn,false);
if(XMenu.attachEvent)XMenu.attachEvent("onmousedown",dragOn);
}
}

//ドラッグ関数
function dragOn(){
flag=true;
target=this.id;
///移動
if(window.document.addEventListener)window.document.addEventListener("mousemove",dragMove,false);
if(window.document.attachEvent)window.document.attachEvent("onmousemove",dragMove);
///終了
if(window.document.addEventListener)window.document.addEventListener("mouseup",dragOff,false);
if(window.document.attachEvent)window.document.attachEvent("onmouseup",dragOff);
}
function dragMove(evt){
if (!flag) return;
if (window.createPopup){
x = event.x + document.body.scrollLeft;
y = event.y + document.body.scrollTop;
}else{
x = evt.pageX;
y = evt.pageY;
}
offx = 60;
offy = 75;
document.getElementById(target).style.top = y-offx+"px";document.getElementById(target).style.left = x-offy+"px";return false;
}
function dragOff(){flag=false;}

// --></script></head>
<body>
<!-- 各メニューで自分自身をドラッグ開始するように,関数を呼ぶ -->
<div id="menu1" style="background-color:red; position:absolute; width:120px;height:150px;" >メニュー1</div>

<div id="menu2" style="background-color:green; position:absolute;top:200px;width:120px;height:150px;" >メニュー2</div>

<div id="menu3" style="background-color:blue; position:absolute;top:400px;width:120px;height:150px;">メニュー3</div>

<div id="menu4" style="background-color:yellow; position:absolute;top:200px; left:200px;width:120px;height:150px;">メニュー4</div>
</body>
</html>

A 回答 (5件)

ふと気づいたので。


<html>
<head>
<title>ドラッグして移動する</title>
<script type="text/javascript"><!--
function addMyEvent(obj,type,func){
if(window.addEventListener){ obj.addEventListener(type, func, false) }
else{ if(window.attachEvent) obj.attachEvent("on"+type, func) }
}
addMyEvent(window,'load',function(){
var T = null, oW, oH;
addMyEvent(document,'mousedown',function(e){
if((o = e.target || e.srcElement).className == 'move')
T=o; oW = o.offsetWidth/2; oH = o.offsetHeight/2;
});
addMyEvent(document,'mouseup', function(){ T = null });
addMyEvent(document,'mousemove',function(e){
if(!T) return;
T.style.top = pos('scrollTop', e.clientY, oH),
T.style.left = pos('scrollLeft', e.clientX, oW);
});
function pos(a,b,c){ return b - c + (document.body[a] || document.documentElement[a]) +"px" }
});

// --></script></head>
<body>
<div id="menu1" class="move" style="background-color:red; position:absolute; width:120px;height:150px;" >メニュー1</div>
<div id="menu2" class="move" style="background-color:green; position:absolute;top:200px;width:120px;height:150px;" >メニュー2</div>
<div id="menu3" class="move" style="background-color:blue; position:absolute;top:400px;width:120px;height:150px;">メニュー3</div>
<div id="menu4" style="background-color:yellow; position:absolute;top:200px; left:200px;width:120px;height:150px;">メニュー4</div>
</body>
</html>

#4で書いた事と、可動メニューにクラス名をつけてマウスダウン監視をdocumnetに変更。
クラス名チェックで一致したら起動。
これでfor文が消せたので見方によってはすこしすっきりですかね?
    • good
    • 0
この回答へのお礼

御丁寧にありがとうございました。
とてつもなく勉強になりました。
質問外の質問にも解説付きで書いていただき、
勉強になります。
すごいです。目からウロコです。
質問して良かったです。

回答していただけたことに、
感謝致します。
ありがとうございました。

お礼日時:2008/03/23 23:53

いえいえ、いつも何か抜けてるので恥ずかしい限りです^^;


私が普段書く感じだと#3でもう最終です。
1年経ってすっかり忘れてから見直しても楽に流れを追える程度で止めていますから。
これ以上無理も含めてやるとしたら、

■変数X,Yは整理用の不要な変数ですから
target.style.top = e.clientY - oH + (document.body.scrollTop || document.documentElement.scrollTop) + "px";
としてしまう。

■配列がソート処理や順番が関係ないケースなので for文は for(var i in Menu) でもOKです。

■関数名などを簡略化して文字数を減らす
エディタなどを使ってるならaddMyEventの様に意味まで含めた長い名前にしなくても追いやすいですからね。
他にスクリプトやライブラリがあるならグローバル変数・関数は短い名前だと干渉する確率が高くなるので逆に良くないですけど。
documentと言うのも良く出てくるので、ローカルでvar D = documentにして短くしちゃう事もあります。

■document.body.scrollTop || document.documentElement.scrollTop のどちらか理解できる方と言う記述
DOCTYPEをつけない(必ずつけるべき といわれていますけどw)とか、特定のブラウザ専用なら
どちらか片方だけにできるかもしれないので、テストして可能ならそうします。

DOCTYPEがない場合は document.body.scrollTop だけでIE、Firefox、Netscape、Safari、Operaでもきちんと動きます。
DOCTYPEをつけると「NetscapeやSafari」と「IEやFirefox」とで方法が分かれてくるので変更はしない方が良いと思います。Operaは両方理解できます。

また長い記述が気持ち悪い場合は、好みによって
addMyEvent(document,'mousemove',function(e){
if(!target) return;
var t=target.style;
t.top = pos('scrollTop', e.clientY, oH);
t.left = pos('scrollLeft', e.clientX, oW);
});
function pos(a,b,c){ return b - c + (document.body[a] || document.documentElement[a]) +"px" }

とかですかね。

ただ、これらは処理が短くなるとか速くなるとかではなく記述上の好み?みたいなレベルだと思います。これらをやる事で何か得した気分になる時くらいしかやらないです。^^;
最後のposの様に関数化すると返って処理が遅くなる(といっても人が感じるレベルではない)場合があるので、
mousemoveのような連続して処理が発生し続ける場合は関数化しない事も1つの選択方法です。


他の人なら、もっとこうすれば簡単になるってのをすぐ見つけられるかもしれないですよ。
その時々で脳が一方向だけ向いてしまうので時間が経つと「この処理無駄だな」とか出てくる時もありますし。

と、こんな感じです^^;
    • good
    • 0

<html>


<head>
<title>ドラッグして移動する</title>
<script type="text/javascript"><!--

/* add event 共用関数 */
function addMyEvent(obj,type,func){
if(window.addEventListener){ obj.addEventListener(type, func, false) }
else{ if(window.attachEvent) obj.attachEvent("on"+type, func) }
}

/* windowにonloadイベントをaddして、関数は全部その中に */
addMyEvent(window,'load',function(){
var target = null; //操作対象の有無をフラグ代わり
var oW, oH; //可動メニューの幅と高さを入れる変数
var Menu = ["menu1","menu2","menu3"]; //new Array(A,B,C)と同じ※空要素は禁止
for(var i=0; i<Menu.length; i++){
var XMenu = document.getElementById(Menu[i]);
addMyEvent(XMenu,'mousedown',function(o){ return function(){ target=o; oW = o.offsetWidth/2; oH = o.offsetHeight/2; }}(XMenu));
}
addMyEvent(document,'mouseup', function(){ target = null });
addMyEvent(document,'mousemove',function(e){
if(!target) return;
var Y = e.clientY - oH + (document.body.scrollTop || document.documentElement.scrollTop);
var X = e.clientX - oW + (document.body.scrollLeft || document.documentElement.scrollLeft);
target.style.top = Y + "px";
target.style.left = X + "px";
});
});

// --></script></head>
<body>
<div id="menu1" style="background-color:red; position:absolute; width:120px;height:150px;" >メニュー1</div>
<div id="menu2" style="background-color:green; position:absolute;top:200px;width:120px;height:150px;" >メニュー2</div>
<div id="menu3" style="background-color:blue; position:absolute;top:400px;width:120px;height:150px;">メニュー3</div>
<div id="menu4" style="background-color:yellow; position:absolute;top:200px; left:200px;width:120px;height:150px;">メニュー4</div>
</body>
</html>

スクロールがある場合の処理も入れておかねばいけなかったですね。
ある程度まとめても理解しづらくない?と思うのでまた少し丸めました。
インデントつけないと見辛いかも^^;
    • good
    • 0
この回答へのお礼

何回も書き込んでくださり、ありがとうございました。
段階的に書いてくださったおかげで違いがわかりやすかったです。
みごとに動きました。
おかげさまで解決しました。

質問外の質問になるかもしれないのですが、
「ある程度まとめても理解しづらくない」
「もう少し丸め込む事できますが」
とありますが、これ以上まとめることなどできるものなのでしょうか。

お礼日時:2008/03/23 08:10

さっそく訂正^^;



マウスアップ、マウスムーブのイベント付加はオンロード関数の中に入れるべきですね。


<html>
<head>
<title>ドラッグして移動する</title>
<script type="text/javascript"><!--

/* 何度も使うので関数化 */
function addMyEvent(obj,type,func){
if(window.addEventListener){ obj.addEventListener(type, func, false) }
else{ if(window.attachEvent) obj.attachEvent("on"+type, func); }
}

/* windowにonloadイベント付加 */
addMyEvent(window,'load',loadScript);
/* 呼ばれる関数 */
function loadScript(){
flag=false;
var Menu = new Array("menu1","menu2","menu3");
for(i=0;i<Menu.length;i++){
var XMenu = document.getElementById(Menu[i]);
/* 各menuにマウスダウンイベント付加と、thisにあたるオブジェクト渡し */
addMyEvent(XMenu,'mousedown',function(o){ return function(){ dragOn(o) } }(XMenu) );

}

/*
マウスアップ、マウスムーブは 何度もイベントを作るのは変なので
dragOn関数にいれずにドキュメントへのイベント付加を1度だけ実行
*/
addMyEvent(document,'mouseup',function(){ flag=false; });
addMyEvent(document,'mousemove',dragMove);

}


//ドラッグ関数
function dragOn(el){
flag=true;
target=el;
}

function dragMove(evt){
if (!flag) return;
x = evt.clientX - 60;
y = evt.clientY -75;
target.style.top = y+"px";
target.style.left = x +"px";
}



// --></script></head>
<body>
<!-- 各メニューで自分自身をドラッグ開始するように,関数を呼ぶ -->
<div id="menu1" style="background-color:red; position:absolute; width:120px;height:150px;" >メニュー1</div>

<div id="menu2" style="background-color:green; position:absolute;top:200px;width:120px;height:150px;" >メニュー2</div>

<div id="menu3" style="background-color:blue; position:absolute;top:400px;width:120px;height:150px;">メニュー3</div>

<div id="menu4" style="background-color:yellow; position:absolute;top:200px; left:200px;width:120px;height:150px;">メニュー4</div>
</body>
</html>
    • good
    • 0

前にサンプルで貰った物からイベントの付加をメソッドを使った方法に変えたようですね。


メソッドを使う方法にすると、呼ばれた関数内のでのthis の意味がIEの場合は変ってしまうのでオブジェクト不明になってるんだと思います。

ちょっと重複する指示などもあったので、もう少しスクリプトを丸めておきました。
もう少し丸め込む事できますが、この状態なら理解もしやすいかと。
(ミスもあるかもしれません)

<html>
<head>
<title>ドラッグして移動する</title>
<script type="text/javascript"><!--

/* 何度も使うので関数化 */
function addMyEvent(obj,type,func){
if(window.addEventListener){ obj.addEventListener(type, func, false) }
else{ if(window.attachEvent) obj.attachEvent("on"+type, func); }
}

/* windowにonloadイベント付加 */
addMyEvent(window,'load',loadScript);
/* 呼ばれる関数 */
function loadScript(){
flag=false;
var Menu = new Array("menu1","menu2","menu3");
for(i=0;i<Menu.length;i++){
var XMenu = document.getElementById(Menu[i]);
/* 各menuにマウスダウンイベント付加と、thisにあたるオブジェクト渡し */
addMyEvent(XMenu,'mousedown',function(o){ return function(){ dragOn(o) } }(XMenu) );

}
}

/*
マウスアップ、マウスムーブは 何度もイベントを作るのは変なので
dragOn関数にいれずにドキュメントへのイベント付加を1度だけ実行
*/
addMyEvent(document,'mouseup',function(){ flag=false; });
addMyEvent(document,'mousemove',dragMove);

//ドラッグ関数
function dragOn(el){
flag=true;
target=el;
}

function dragMove(evt){
if (!flag) return;
x = evt.clientX - 60;
y = evt.clientY -75;
target.style.top = y+"px";
target.style.left = x +"px";
}



// --></script></head>
<body>
<!-- 各メニューで自分自身をドラッグ開始するように,関数を呼ぶ -->
<div id="menu1" style="background-color:red; position:absolute; width:120px;height:150px;" >メニュー1</div>

<div id="menu2" style="background-color:green; position:absolute;top:200px;width:120px;height:150px;" >メニュー2</div>

<div id="menu3" style="background-color:blue; position:absolute;top:400px;width:120px;height:150px;">メニュー3</div>

<div id="menu4" style="background-color:yellow; position:absolute;top:200px; left:200px;width:120px;height:150px;">メニュー4</div>
</body>
</html>

これで希望通り動きますか?
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!