基本上,任何一个稍具规模的应用系统都离不开消息,消息的展现方式也是百花齐放,精彩纷呈。随着Windows/Msn Messenger的不断普及,Messenger的Toast式的消息提示界面逐渐深入人心,不少人开始尝试在各种场合模仿这种界面,在WEB页面上,人们首先想到的是用DIV层来实现,但DIV的一个致命弱点就是必须在一个窗口容器内,如果这个窗口当时不在最前端,或尺寸位置不恰当,则用户可能看不到、或者不能完整看到该提示。popup对象是一个类似对话框的窗口,它的展现游离于其父窗口之外,可以指定在屏幕的任意位置,可以指定任意大小,并且没有标准窗口的边框,可塑性强,因此是生成Messenger式提示窗口的最佳选择。
在使用popup对象之前,我们先来系统地认识一下popup对象的一些主要特性:
与大部分的Window类型不同,popup没有边框;
当用户点击popup以外区域或新的popup打开时,当前popup总是(不是绝对)会被自动关闭;
popup对象即使打开时也永远不会获得焦点,父窗口中的处理继续执行;
构造popup对象时的DHTML可以在父窗口文档对象或其他文档对象中;
popup对象不支持文本框之类的输入控件;
popup窗口中任何元素都不可能被选中;
popup对象本身不会发生导航行为,点击其内部任何一个链接将只会影响其父窗口或产生新的浏览器实例;
一旦显示,popup对象不可能被移动;
popup对象不可能被用户修改尺寸大小。
popup对象的属性及方法很简单,最主要的就是show方法:
popup.show(iX, iY, iWidth, iHeight [, oElement])
可以在指定位置(iX,iY)显示指定大小(iWidth,iHeight)的窗口,oElement是一个坐标参照对象,若指定该对象,则iX, iY相对于该对象的坐标,若未指定,则默认为桌面对象,显然我们这里应该使用该默认设置。
在实际测试中发现,popup对象不能overflow:hidden到桌面以外,因此要让它从最底端升起,不能简单地将Y坐标指定为window.screen.height-1,如果不同时把popup的高度指定为0,则popup会自动调整坐标,显示全部窗口,因此,popup升降过程中的窗口高度应为桌面高度与Y坐标的差。为了防止窗口高度不断变化导致窗体内HTML代码展现的变形,我们可以将popup内部设计为一个fixed的table-layout,同时各单元格以overflow:hidden的样式确保。
我们定义了一个简单的消息类,有消息标题title、消息主体body、消息链接url、链接目标窗口target、小图标iconSmall、大图标iconBig、提示音sound几个属性,由于消息的产生是不确定的,因此必须建立一个先进先出的消息队列及消息守护精灵来进行管理,很遗憾的一点就是popup同时只能有一个,因此无法实现类似Messenger消息洪水涌入时爬楼的壮观景象。
var screenWidth=window.screen.width;
var screenHeight=window.screen.height;
var webroot="/MatrixWeb";
var POPUP_WIDTH="180";
var POPUP_HEIGHT="116";
var x=0, y=0, h=0;
var currentMsg;
var mq=new Queue();
var timerShow;
var daemonTimer=setInterval("QueueDaemon()",2000);
var p;

function QueueDaemon() {
if (currentMsg!=null) return;
currentMsg=mq.Dequeue();
if (currentMsg==null) return;
CreatePopup(currentMsg);
x = screenWidth - POPUP_WIDTH -1;
y = screenHeight -1;
h=0;
p.show(x, y, POPUP_WIDTH, h);
timerShow = window.setInterval(PopupRaise,5);
wavFile.src=webroot + currentMsg.sound + ".wav"
wavFile.play();
}

function PopupRaise() {
try {
if (h>=POPUP_HEIGHT || p==null || !p.isOpen) {
window.clearInterval(timerShow);
timerShow = window.setTimeout(PopupToLower, 5000);
} else {
h++; y--;
h++; y--;
p.show(x,y,POPUP_WIDTH,h);
}
}
catch(e){}
}

function PopupToLower() {
if (p!=null) timerShow = window.setInterval(PopupLower,5);
}

function PopupLower() {
try {
if (h <= 0 || p==null || !p.isOpen) {
window.clearInterval(timerShow);
PopupClose();
} else {
h--; y++;
h--; y++;
h--; y++;
p.show(x,y,POPUP_WIDTH,h);
}
}
catch(e){}
}

function PopupClose() {
if (p!=null && p.isOpen) p.hide();
if (timerShow!=null) clearInterval(timerShow) ;
p=null;
currentMsg=null;
}

function CreatePopup(msg){
try{
p=window.createPopup();
var d=p.document;
var b=d.body;
b.rightmargin=0;
b.leftmargin=0;
b.topmargin=0;
b.bottommargin=0;
b.background=webroot + "/images/popup.png";
b.innerHTML=Popup_CreateBody(msg);
b.style.border="1pm solid #A6B4CF";
b.style.borderStyle="outset";
b.style.cursor="default";
b.style.fontFamily="Tahoma,Simsun";
b.style.fontSize="9pt";

var closeButton=d.getElementById("CloseButton");
closeButton.onclick=PopupClose;
closeButton.setAttribute("popup", p);

if (msg.url!=null && msg.url!="") {
var popupMessage=d.getElementById("PopupMessage");
popupMessage.style.cursor="hand";
this.url=msg.url;
this.target=msg.target;
popupMessage.onclick=OpenMessageLink;
popupMessage.setAttribute("popup",this);
}
}catch(Xj){}
}

function OpenMessageLink() {
var cp=this.getAttribute("popup");
window.open(cp.url, cp.target);
}

function Popup_CreateBody(msg){
var popupHtml = "<table cellspacing='0' style='table-layout:fix;' width='100%' height='100%'>";
popupHtml += "<tr height='22'><td width='22'>";
if (msg.iconSmall!=null) popupHtml += "<img src='" + webroot + "/images/" + msg.iconSmall + "'>";
else popupHtml += "<img src='" + webroot + "/images/butterfly.gif'>";
var titleWidth = POPUP_WIDTH-40;
popupHtml += "</td><td><nobr><div style='font-size:9pt;width:" + titleWidth + ";overflow:hidden;'>";
if (msg.title!=null) popupHtml += msg.title;
popupHtml += "</div></nobr></td><td width='16'>";
popupHtml += "<img src='" + webroot + "/images/signmeout.gif' id='CloseButton'>";
popupHtml += "</td></tr><tr height='76'><td colspan='3' align='left' valign='middle' id='PopupMessage'>";
var msgWidth=POPUP_WIDTH-2;
popupHtml += "<div style='font-size:9pt;width:" + msgWidth + ";overflow:hidden;'>";
popupHtml += "<img src='" + webroot + "/images/" + msg.iconBig + "' border=0 align=left>"
popupHtml += msg.body;
popupHtml += "</div></td><tr height='16'><td colspan='3' align='right'>";
popupHtml += "<img src='" + webroot + "/images/toastmsn.gif'></td></tr></table>";
return popupHtml;
}

function Queue(){
var items=new Array();
var first=0;
var count=0;
this.Count=function(){return count;};
this.Enqueue=function(x){ //入列
items[first+count]=x;
count++;
return x;
};
this.Dequeue=function(){ //出列
var result=null;
if (count>0){
result=items[first];
delete items[first];
first++;
count--;
}
return result;
};
}

function Message(Title,Body,Url,Target,IconSmall,IconBig,Sound){
this.title=Title;
this.body=Body;
this.url=Url;
this.target=Target;
this.iconSmall=IconSmall;
this.iconBig=IconBig;
this.sound=Sound;
}
测试页面
参考内容:
Using the Popup Object
Msn Web Messenger