延續上個例子用Javascript寫Modal Dialog簡易教學
加入底下紅色的程式碼(先不要加上深紅色的程式片段),就可以做到移動視窗,簡單的邏輯是:
- 在對話框攔截 Mouse Down 事件,記錄當時對話框的位置,與滑鼠位置,與標記「滑鼠已按下」
- 在對話框攔截 Mouse Move 事件,根據「滑鼠是否按下」來決定是否移動對話框,移動方式為根據 ( [此時滑鼠位置] - [Mouse Down中的滑鼠位置] + [對話框在Mouse Down中的位置] )來計算出對話框目前應該要在的位置,並且移動之,(透過Java Script
- 在對話框攔截 Mouse Up 事件,標記「滑鼠已經放開」
這邏輯很簡單,但你會發現一個瑕疵,就是當你滑鼠移動很快,會讓畫面重繪跟不上,你的滑鼠會超出對話框,然後Mouse事件就不會被處理,所以視窗就不再被移動了。
怎麼解決?加上底下深紅色的程式片段,讓佈滿整個頁面的遮罩層也處理Mouse Move跟Mouse Up,就可以解決了。我不知道這個作法是否完美、正規。如果有人知道更好的、更正確的作法,麻煩告訴我喔,謝謝。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="jquery-1.7.1.min.js"></script>
<!-- Script 區段 -->
<script language='JavaScript' type='text/JavaScript'>
$(document).ready(function()
{
var DivSourceX = 0;
var DivSourceY = 0;
var DivEnvDwX = 0;
var DivEnvDwY = 0;
var DivEnvMvX = 0;
var DivEnvMvY = 0;
var DivMouseFlag = false; // 用來判斷是否處於滑鼠按著的狀態
// 按下「X」圖隱藏遮罩層
$(".closeDialog").click(function()
{
ShowModalDialog( false );
});
// 按鈕後顯示遮罩層
$(".btnOpenModal").click(function()
{
ShowModalDialog( true );
});
// 遮罩層控制
function ShowModalDialog( YesOrNo )
{
if ( true == YesOrNo )
{
$(".DivOverlapMask").css( "visibility", "visible" );
$(".DivDialog").css( "visibility", "visible" );
$(".closeDialog").css( "visibility", "visible" );
}
else
{
$(".DivOverlapMask").css( "visibility", "hidden" );
$(".DivDialog").css( "visibility", "hidden" );
$(".closeDialog").css( "visibility", "hidden" );
}
}
// DivDialog 為對話框主體層,需要攔截 Mouse的 Up, Down, Move
$(".DivDialog").mousedown(function(event)
{
DivMouseDown( event );
});
$(".DivDialog").mouseup(function()
{
DivMouseUp( );
});
$(".DivDialog").mousemove(function(event)
{
DivMouseMove( event );
});
// 需要加上遮罩層攔截 Mouse Up 與 Move 才能在「滑鼠意外滑出對話框時,還能繼續移動對話框」
$(".DivOverlapMask").mouseup(function()
{
DivMouseUp( );
});
$(".DivOverlapMask").mousemove(function(event)
{
DivMouseMove( event );
});
// Mouse Down 的時候,紀錄當時視窗的原始位置,滑鼠當時的位置
function DivMouseDown(EvtDw)
{
DivSourceX = $(".DivDialog").position().left;
DivSourceY = $(".DivDialog").position().top;
if ( !EvtDw )
{
EvtDw = window.event;
}
if ( EvtDw.pageX || EvtDw.pageY )
{
DivEnvDwX = EvtDw.pageX;
DivEnvDwY = EvtDw.pageY;
}
else if ( EvtDw.clientX || EvtDw.clientY )
{
DivEnvDwX = EvtDw.clientX;
DivEnvDwY = EvtDw.clientY;
}
else if ( EvtDw.x || EvtDw.y )
{
DivEnvDwX = EvtDw.x;
DivEnvDwY = EvtDw.y;
}
DivMouseFlag = true;
}
function DivMouseUp()
{
DivMouseFlag = false;
}
// Mouse Move 的時候,根據滑鼠的目前位置,原始位置,與物件原始位置,計算,然後將對話框移動到應該去的位置
function DivMouseMove(EvtMv)
{
if ( DivMouseFlag )
{
if ( !EvtMv )
{
EvtMv = window.event;
}
if ( EvtMv.pageX || EvtMv.pageY )
{
DivEnvMvX = EvtMv.pageX;
DivEnvMvY = EvtMv.pageY;
}
else if ( EvtMv.clientX || EvtMv.clientY )
{
DivEnvMvX = EvtMv.clientX;
DivEnvMvY = EvtMv.clientY;
}
else if ( EvtMv.x || EvtMv.y )
{
DivEnvMvX = EvtMv.x;
DivEnvMvY = EvtMv.y;
}
NewDivX = DivSourceX + ( DivEnvMvX - DivEnvDwX );
NewDivY = DivSourceY + ( DivEnvMvY - DivEnvDwY );
$(".DivDialog").css(
{
top: NewDivY + "px",
left: NewDivX + "px"
});
}
}
})
</script>
<!-- CSS 區段 -->
<style type="text/css">
/* 只是背景 */
.DivGround
{
position: absolute;
width: 400px;
height: 300px;
top: 30px;
left: 30px;
border: solid;
background-color: #66ccff;
text-align:center;
}
/* 遮罩,將整個瀏覽器佈滿,讓原本背景層都無法點選 */
.DivOverlapMask
{
position:fixed;
top:0px;
left:0px;
height:100%;
width:100%;
margin:0;
padding:0;
background:gray;
opacity:0.95;
visibility:hidden;
}
/* Modal Dialog 層 */
.DivDialog
{
position:absolute;
width:200px;
height:100px;
margin:0;
padding:0;
left:100px;
top:100px;
background-color: #eeaaaa;
border-radius: 10px;
visibility:hidden;
}
/*「X」按鈕 */
.closeDialog
{
position:absolute;
width:32px;
height:32px;
right:8px;
top:8px;
cursor:pointer;
visibility:hidden;
}
</style>
<title>無標題文件</title>
</head>
<body>
<!-- Modal Dialog 的原理就是在背景層(可以很多層)之上,蓋上一層遮罩,最後給一個DIV當成對
話框 -->
<div class= "DivGround">
<button class = "btnOpenModal" > 開 啟 </button>
<div class = "DivOverlapMask" >
<div class = "DivDialog" >
<img class = "closeDialog" src="img/close-button.png" ></img> </div>
</div>
</div>
</body>
</html>
為了讓程式畫面美觀,底下程式碼會稍微多了點,但其實,方法與原理不難。
- 把網頁主體先完成之後,準備好一個按鈕,或某個觸發的點,可以觸發事件。
- 在主體層上堆一層「遮罩層」。這層設定寬、高都是100%,然後設定透明度opacity:0.85或0.95(自己看喜歡怎樣的感覺來調整);然後這層在包含著DIV,這個DIV就是用來當對話框用的,你可以在這個DIV當中繼續包入其他元素,記得要包含個按鈕或圖示可以把對話框「關掉」的。
- 將「遮罩層」設定好一個控制函式,根據傳入參數來設定「遮罩層」,來把「遮罩層」給隱藏或打開來。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="jquery-1.7.1.min.js"></script>
<!-- Script 區段 -->
<script language='JavaScript' type='text/JavaScript'>
// 按下「X」圖隱藏遮罩層
$(".closeDialog").click(function()
{
ShowModalDialog( false );
});
// 按鈕後顯示遮罩層
$(".btnOpenModal").click(function()
{
ShowModalDialog( true );
});
function ShowModalDialog( YesOrNo )
{
if ( true == YesOrNo )
{
$(".DivOverlapMask").css( "visibility", "visible" );
$(".DivDialog").css( "visibility", "visible" );
$(".closeDialog").css( "visibility", "visible" );
}
else
{
$(".DivOverlapMask").css( "visibility", "hidden" );
$(".DivDialog").css( "visibility", "hidden" );
$(".closeDialog").css( "visibility", "hidden" );
}
}
})
</script>
<!-- CSS 區段 -->
<style type="text/css">
/* 只是背景 */
.DivGround
{
position: absolute;
width: 400px;
height: 300px;
top: 30px;
left: 30px;
border: solid;
background-color: #66ccff;
text-align:center;
}
/* 遮罩,將整個瀏覽器佈滿,讓原本背景層都無法點選 */
.DivOverlapMask
{
position:fixed;
top:0px;
left:0px;
height:100%;
width:100%;
margin:0;
padding:0;
background:gray;
opacity:0.85;
filter: alpha(opacity=85);
-moz-opacity: 0.85;
visibility:hidden;
}
/* Modal Dialog 層 */
.DivDialog
{
position:fixed;
width:200px;
height:100px;
margin:0;
padding:0;
left:100px;
top:100px;
background-color: #eeaaaa;
border-radius: 10px;
visibility:hidden;
}
/*「X」按鈕 */
.closeDialog
{
position:absolute;
width:32px;
height:32px;
right:8px;
top:8px;
cursor:pointer;
visibility:hidden;
}
</style>
<title>無標題文件</title>
</head>
<body>
<!-- Modal Dialog 的原理就是在背景層(可以很多層)之上,蓋上一層遮罩,最後給一個DIV當成對
話框 -->
<div class= "DivGround">
<button class = "btnOpenModal" > 開 啟 </button>
<div class = "DivOverlapMask" >
<div class = "DivDialog">
<img class = "closeDialog" src="img/close-button.png" ></img> </div>
</div>
</div>
</body>
</html>
我雖然不知道原因
但是網路上查到的資訊是這樣告訴我的,如果有錯,麻煩可以回文告訴我一下
img 這個 tag,如果你要把圖片來源 src = "xxxx.png" 寫在CSS裡,是沒有辦法的,應該說,寫了沒有用。雖然 Dreamwave 的 intelligent senses 還是會引導你在 CSS 的程式片段中幫你引導出 Src 的程式類似這樣:src:url(img/close-button.png);可是,實際執行,圖片就是不會出來。
解法一:
在 CSS 中不要用 src 屬性,而改用 background-image 屬性,當然,您也想到了,這樣很怪,且,這樣圖片會多出一個外框,無法消掉.......,這樣不算解決方案。
解法二:
不要寫在 CSS 當中,直接寫在 HTML 裡<img class = "ImgStyle" src="img/button.png" ></img>,這樣就解決了,只是,這個無法放到CSS當中,不知道的人,可能得花好久的時間才找得出原因呢。
因為Dreamwave CS6 有對程式碼做 色彩區分
所以我相信他所以當我用 <!-- xxxx --> 來加註解的時候,該段程式碼確實變成灰色,但是.......
實際上,他不是變成註解,導致整個CSS片段都被當成錯誤的而跳過
意外的多花費了我一個上午的時間找出為什麼我的 DIV 都突然無法正常呈現大小。
後來查很久才知道,原來是註解寫法寫錯了(昏)
底下這段程式碼最下方body內有四行被遮住的,可以逐一打開其中一個來感受一下,當你滑鼠游標滑入該物件裡面時,滑鼠游標會變成十字移動圖示,但是當你按著滑鼠移動,就會有不同了,在div跟table會顯示為輸入文字的符號,而在button跟img則顯示為移動的十字符號。怎麼回事?這是因為,前兩者是可包容其他物件的區塊物件,用來排版的,而後兩者是不可包容其他物件在其中的功能物件,系統預設按著滑鼠移動叫做拖動,而針對上述兩種類型的物件都預設了滑鼠的圖示,而且無法改(目前我還不會)。
所以如果要拖動物件,而且拖動的對象是個區塊物件,譬如拖動視窗,那會做不出效果來,建議可以放個功能物件在區塊物件上,就像是放個標題列一樣意思,讓使用者在功能物件上按下滑鼠,才觸發移動,並對區塊物件做移動,這樣就行了。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Mouse Move</title>
<script src="http://code.jquery.com/jquery-1.8.2.js"></script>
<!-- Script 區段 -->
<script>
$(document).ready(function(e)
{
$(".TheObj").mousemove(function(e)
{
$(".TheObj").text( "mouse moving" );
$(".TheObj").css( "cursor", "move" );
});
})
</script>
<!-- CSS 區段 -->
<style type="text/css">
.TheObj
{
width:600px;
height:400px;
border:solid;
cursor:pointer;
}
</style>
</head>
<!-- Body 區段 -->
<body>
<!-- <div class = "TheObj"></div> -->
<!-- <table class = "TheObj"></table> -->
<!-- <button class = "TheObj"></button> -->
<!-- <img class = "TheObj"></img> -->
</body>
</html>
iframe是無法處理事件的,首先,你在Tag裡頭,想輸入<iframe onClick = "aFunc()",如果你在Dreamwave 或 Visual Studio 這類有 intelligent senses(忘記是不是這樣拼了)的提示功能的開發工具,你會發現他的提示當中,並沒有onXXXXX,也就是他不處理事件。而且如果想透過JQuery的方式來加入事件跟函式的關連,你會發現,intelligent senses有提示你Enevt可用,但是寫了之後,沒有作用。
你可以用底下的程式碼執行在瀏覽器看看,在body內,有遮掉三行,分別為div, span, iframe,你可以個別打開看看,會發現只有iframe沒有作用。所以,盡量不要在你的架構上「需要去處理iframe」的Event,不然,就不要用iframe了,把該頁面直接寫在這個HTML或PHP就好了。
當然,Google一下,你也會找到解法,比方從iframe內部的頁面傳事件到Parent來,或用AddListener之類的方式,但是有比較困難,暫時還是先避開就好吧。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>jQuery (document).ready 教學</title>
<script src="http://code.jquery.com/jquery-1.8.2.js"></script>
<!-- CSS 區段 -->
<script language="javascript">
$(document).ready(function(e)
{
$("body").click(function(e)
{
alert('Mouse Click body.')
$(".OutScreen").text( "Click body" );
});
$(".button").click(function(e)
{
alert('Mouse Click button.')
$(".OutScreen").text( "Click button" );
});
$(".OutScreen").click(function(e)
{
alert('Mouse Click Screen.')
$(".OutScreen").text( "Click Screen" );
});
});
</script>
<!-- CSS 區段 -->
<style type="text/css">
.OutScreen
{
width:600px;
height:400px;
border:solid;
background:#FF6;
}
</style>
</head>
<body>
這個網頁展示的是在 Body 主體上,放了一個按鈕,跟一個來比較的物件,可發現,iframe是無法處理事件的<br>
<!--<iframe class="OutScreen" >xxxxx</iframe>-->
<!--<span class="OutScreen" >xxxxx</span>-->
<!--<div class="OutScreen" >xxxxx</div>-->
<button class = "button">按鈕</button> <br>
</body>
</html>
$(".DivDialogTitle").click(function (e) { DivClick(event); });
這種JQuery的寫法,可以把某個TAG物件的Click事件跟某個指定的函式關連在一起,可正常運作,沒有問題。
$(".DivDialogTitle").mousedown(function (e) { DivMouseDown(event); });
但是想把Mouse的事件跟某個指定的函式關連在一起,抱歉,FireFox辦不到(以後會不會更新成可支援,不曉得)
該怎麼做?得回到最原始的HTML語法在Tag中把事件跟函式綁定
<div onmouseup = "DivMouseUp(Event)" >
是的,改成這樣就行了
-------------------------------------------------------------------------------------------
事件函式假設如下
function DivMouseDown(e)
{
// 如果 e 是 null (有時候吧,意外發生),就把 e 設定為 window 的 event
if ( !e )
{
e = window.event;
}
var IeMousePosition = e.X;
var FireFoxMousePosition = e.PageX;
}
如上頭所列,想取得Mouse的位置,如果是IE或Chrome或Safari或Opera,你可以這麼用:e.X。如果是FireFox,那你得用e.PageX。