跨幀 (frameset,freame,iframe) 的無限級菜單
大家都知道在IE中,存在frameset,freame,iframe三種幀元素,他們在佈局中運用廣泛,而且也很實用,但是有時候使用起來還是有一些小麻煩。如你是做相關框架或者是企業管理軟件的,需要使用到它來佈局,那他的層級是最高的,也就是說他的z-index是最高的,那就會帶來一個問題,假如你的ifream上面可能會出現諸如菜單,懸浮div的時候,那他們將會被幀覆蓋。這樣降帶來用戶無法接受的體驗,可以解決的方案很多,但是如果你確實已經在用幀並且無法替代它(出於開發時間或者成本),那麼我們不妨來學習製作一下跨幀的下拉菜單,僅限IE,其他瀏覽器不再考慮範圍。
首先我們採用的方案就是IE下的window.createPopup,它是彈出對話框,當用戶焦點退出對話框的時候,對話框會自動消失,我們也可以再它消失的時候釋放一些資源等。但是他也會帶來幾個問題,需要我們去考慮:
1. 我們需要寫一些javascript來實現下拉菜單,這需要對javascript有一點了解。
2. popup window 是不支持父窗口css導入,這需要我們去用javascript動態寫入,
好像CSS風格也不支持expression。
3. popup window初始化的時候是不可見的,需要調用popupwin.show()來顯示窗口,這點我們可能好好利用。
好了下面我們看一個列子:當點擊按鈕時會出現一個彈出框。
<HTML>
<HEAD>
<TITLE>Popup Example</TITLE>
<SCRIPT LANGUAGE="JScript">
var oPopup = window.createPopup();
function ButtonClick()
{
var oPopBody = oPopup.document.body;
oPopBody.style.backgroundColor = "lightyellow";
oPopBody.style.border = "solid black 1px";
oPopBody.innerHTML = "Click outside <B>popup</B> to close.";
oPopup.show(100, 100, 180, 25, document.body);
}
</SCRIPT>
</HEAD>
<BODY>
<BUTTON οnclick="ButtonClick()">Click Me!</BUTTON>
</BODY>
</HTML>
接下來我們一起來分析怎樣來實現無限級跨幀菜單,我想第一步分析下數據結構,以便我們來用基於對象的javascript來實現menu Object。很容易想到它就是tree結構。
屬行 | 描述 | 值描述 |
Id | menuitem 的唯一標示 | 可以任意定義,但是得保證唯一 |
index | 序列,用與所有menuitem排序,擴展功能 | 一般從0開始不斷增加 |
title | menuitem標題,描述 | 任意字符串 |
properties | 屬性集合,擴展使用 | 存儲任意其他信息 |
parentId | 父menuitem的Id, | |
children | menuitem的子按鈕 | |
classStyle | 常量字符串,用於模擬typeof | |
icon | 按鈕圖標,擴展用 | |
url | 按鈕鏈接地址 |
還有一個target屬性,指定我們以怎樣的方式打開我們的新的鏈接,如_self, _blank,或者其他frame的引用。
MenuItem = function(id ,index,parentId, title,icon,url,toTarget)
{
this.defaultIcon = "menu.gif";
this.id =id;
this.index = (index!=null && parseInt(index)>0) ? parseInt(index): 0 ;
this.title = title;
this.properties = new Array();
this.parentId = parentId;
this.children = new Array();
this.classStyle ="MenuItem";
this.icon = (icon!=null && icon.length>0)? icon : this.defaultIcon;
this.url = (url!=null && url.length>0)? url:"";
this.toTarget = toTarget;
};
以上就是類似與樹的節點,那下面就是我們樹本身的一些操作和封裝,比如menu的樣式css,添加主菜單和子菜單的基本方法:
1. Menubar 的結構:
PopMenu = function (cssFile, normalClass,hotClass,menuClass,menuWidth,menuHeight)
{
this.defaultMenuWidth = 80;
this.defaultMenuHeight = 25;
this.cssFile = cssFile;
this.normalClass = normalClass;
this.hotClass = hotClass;
this.menuClass = menuClass;
this.menuWidth = (menuWidth && menuWidth!=null && parseInt(menuWidth) >0)? parseInt(menuWidth):this.defaultMenuWidth;
this.menuHeight = (menuHeight && menuHeight!=null && parseInt(menuHeight) >0)? parseInt(menuHeight):this.defaultMenuHeight;
this.menus = new Array();
this.popWin =window.createPopup();
this.popWin.document.createStyleSheet(this.cssFile);
if(window.navigator.appName.indexOf("Microsoft")>=0) this.appName = "IE";
else if(window.navigator.appName.indexOf("Netscape")>=0) this.appName="NS";
else this.appName ="OT";
appName = this.appName;
};
2.初始化菜單
PopMenu.prototype.initTopMenu = function (divId)
{
popMenuInstant = this;
var target = null;
if(divId!=null && divId.length>0)
{
target = document.getElementById(divId);
if (target==null ) {
alert("could not find the menu element!");
return;
}
}
var len = this.getTopMenusLength();
target.style.width= (parseInt(this.getMenuWidth())*len+ 10 * len);
target.style.height= parseInt(this.getMenuHeight()+4);
if(len>0)
{
var menutable = document.createElement("table");
var menuContent ="";
for(var i=0;
i<len ;
i++)
{
var tempMenu = this.getTopMenus()[i];
var url = (tempMenu.getURL()!=null && tempMenu.getURL().length>0)?tempMenu.getURL():".";
menuContent+=("<td id ='"+tempMenu.getMenuId()+"' class='"+this.normalClass+"' " +
" οnmοuseοver='javascript:_onMenuItemFocus.call(this);' " +
" onmouseout ='javascript:_onMenuItemNormal.call(this);' " +
" >"+tempMenu.getMenuTitle()+"</td>");
}
target.innerHTML =
"<table class='menuTable'>"+
"<tr>"+
menuContent+
"</tr>"+
"</table>";
}
};
3. 創建菜單:
PopMenu.prototype.addMenuItem = function(id ,index,title,icon,url)
{
var menuItem = new MenuItem(id ,index,null, title,icon,url,null);
this.menus.push(menuItem);
};
4. 創建子菜單:
PopMenu.prototype.addSubMenuItem = function(id ,index,parentId, title,icon,url,toTarget)
{
if(parentId ==null ||parentId.length<=0)
{
this.addMenuItem(id, index, title, icon,url);
}
else
{
var parent = this.findMenu(parentId);
var menuItem = new MenuItem(id ,index,parentId, title,icon,url,toTarget);
parent.addChild(menuItem);
}
};
4.點擊按鈕,創建popup 子菜單
_createSubMenu =function(menuId)
{
var menu = popMenuInstant.findMenu(menuId);
var parentMenu = null;
if(menu.getParentId()!=null && menu.getParentId().length>0 )
parentMenu = popMenuInstant.findMenu(menu.getParentId());
var children = menu.getChildren();
if(children.length && children.length>0)
{
var width = popMenuInstant.menuWidth;
var height = ((parseInt(children.length)+1) * popMenuInstant.menuHeight);
var htmlStr = "<div style=\"width:"+(parseInt(width))+"px;\" >"
+ "<table class=\"menuTable\" >";
for (var i = 0; i < children.length; i++)
{
var menu = children[i];
if(typeof menu == "object" && menu.getClassStyle()=="MenuItem")
{
htmlStr += "<tr style=\"width:"+(parseInt(width))+"px;\"><td id=\""+menu.getMenuId()+"\"" +
" class=\"" +popMenuInstant.normalClass+"\""+
" οnmοuseοver=\"javascript:window.top._onMenuItemFocus.call(this);" +"\""+
" οnmοuseοut=\"javascript:window.top._onMenuItemNormal.call(this);" +"\""+
" οnclick=\"javascript:window.top._onMenuItemClick.call(this);" +"\""+
"><div>" +menu.getMenuTitle()+"</div></td></tr>";
}
}
htmlStr += "</table>";
htmlStr += "</div>";
var popWin =null;
if(parentMenu!=null&&parentMenu.getMenuId()!=null && parentMenu.getMenuId().length>0 )
{
popWin = this.document.parentWindow.createPopup();
popWin.document.createStyleSheet(popMenuInstant.cssFile);
popWin.document.body.innerHTML = htmlStr;
if(!popWin.isOpen)
{
popWin.show ((parseInt(this.clientLeft)+parseInt(this.clientWidth)),
(parseInt(this.clientTop)+parseInt(this.clientHeight)), width, height, this);
}
else
{
popWin.hide();
popWin.show ((parseInt(this.clientLeft)+parseInt(this.clientWidth)),
(parseInt(this.clientTop)), width, height, this);
}
}
else
{
popWin = window.top.createPopup();
popWin.document.createStyleSheet(popMenuInstant.cssFile);
popWin.document.body.innerHTML = htmlStr;
if(!popWin.isOpen)
popWin.show (-5, parseInt(this.offsetHeight)+2, width, height, this);
else
{
popWin.hide();
popWin.show (-5, parseInt(this.offsetHeight)+2, width, height, this);
}
}
}
};
這樣我們就可以很簡單的來實現頁面的東西了:iframe就是爲了測試是不是可以跨幀。
<div id ="popmenu"></div>
<iframe name="mainFreame" id="mainFreame" width="1024" height="800"></iframe>
是不是有點操作對象的感覺了:
<script type="text/javascript">
var popMenu = new PopMenu("css/menu.css","normalMenu","focusMenu","menu","200","25");
popMenu.addMenuItem("menu1", 1, "Menu 1", "file.gif","");
popMenu.addMenuItem("menu2", 2, "Menu 2", "file.gif","");
popMenu.addMenuItem("menu3", 3, "Menu 3", "file.gif","");
popMenu.addMenuItem("menu4", 4, "Menu 4", "file.gif","");
popMenu.addSubMenuItem("menu21", 1, "menu2", "Menu 2-1", "file.gif","http://www.hao123.com","_blank");
popMenu.addSubMenuItem("menu22", 2, "menu2", "Menu 2-2", "file.gif","http://www.hao123.com","_self");
popMenu.addSubMenuItem("menu211", 1, "menu21", "Menu 2-1-1", "file.gif","http://www.hao123.com","mainFreame");
popMenu.addSubMenuItem("menu2111", 1, "menu211", "Menu 2-1-1-1", "file.gif","http://www.163.com","mainFreame");
popMenu.addSubMenuItem("menu2112", 2, "menu211", "Menu 2-1-1-2", "file.gif","http://www.163.com","mainFreame");
popMenu.addSubMenuItem("menu21121", 1, "menu2112", "Menu 2-1-1-2-1", "file.gif","http://www.163.com","mainFreame");
popMenu.addSubMenuItem("menu21122", 2, "menu2112", "Menu 2-1-1-2-2", "file.gif","http://www.163.com","mainFreame");
popMenu.addSubMenuItem("menu221", 2, "menu22", "Menu 2-2-1", "file.gif","http://www.csdn.com","mainFreame");
popMenu.addSubMenuItem("menu222", 2, "menu22", "Menu 2-2-1", "file.gif","http://www.csdn.com","mainFreame");
popMenu.addSubMenuItem("menu31", 1, "menu3", "Menu 3-1", "file.gif","http://www.baidu.com","mainFreame");
popMenu.addSubMenuItem("menu32", 2, "menu3", "Menu 3-2", "file.gif","http://www.baidu.com","mainFreame");
popMenu.addSubMenuItem("menu33", 2, "menu3", "Menu 3-3", "file.gif","http://www.baidu.com","mainFreame");
popMenu.initTopMenu("popmenu");
</script>
效果圖:
點擊效果:
完成,本人只是在探討實現方法和過程,有可能程序不夠完善,讀者見諒。如果想下載源代碼,
請鏈接:http://download.csdn.net/detail/wodetiankong516/4493907