用戶首頁博客設(shè)置文章相冊(cè)留言評(píng)論系統(tǒng)
這里要注意幾個(gè)小問題,其一這種樹結(jié)構(gòu)是懸浮層絕對(duì)定位的,在創(chuàng)建層的時(shí)候一定要直接放在body的下面,這樣做的是確保在IE里面能遮掩住任何層,因?yàn)樵贗E里面是有stacking context這種東西的潛規(guī)則在里面的,另外當(dāng)然還有一個(gè)select你能遮住我嗎?老掉牙的問題,這里是采用在每個(gè)懸浮層后面加個(gè)iframe元素,當(dāng)然同一級(jí)的菜單只產(chǎn)生一個(gè)iframe元素,菜單有幾級(jí)將產(chǎn)生幾個(gè)iframe遮掩,然后菜單顯示和隱藏的時(shí)候同時(shí)顯示和隱藏iframe。
不過這種菜單并不合適前臺(tái),因?yàn)槟壳爸恢С衷谀_本里動(dòng)態(tài)添加菜單節(jié)點(diǎn),而不能從現(xiàn)有的html元素獲取菜單節(jié)點(diǎn),我們?yōu)榱薙EO等前臺(tái)導(dǎo)航一般是在后臺(tái)動(dòng)態(tài)輸出的,假如菜單有多級(jí)的話也建議不超過2層,對(duì)客戶來說太多層也懶得去看,不過有個(gè)面包屑導(dǎo)航顯示還是很不錯(cuò)的。
menu.js 2.右鍵菜單樹(ContextMenu) 無限級(jí)節(jié)點(diǎn)樹 要實(shí)現(xiàn)無限級(jí)的功能,如果沒有什么小技巧,好象就只能遞歸了。不過需要注意一定要有個(gè)正確條件判斷來return,避免死循環(huán)。從數(shù)據(jù)的存放結(jié)構(gòu)來說,一般我們數(shù)據(jù)庫里保存有id、name、parentId字段,樹結(jié)構(gòu)里仍然保存這種結(jié)構(gòu),在展開樹節(jié)點(diǎn)的時(shí)候我們需要根據(jù)id獲取它所有的子節(jié)點(diǎn),并保存起來,避免第二次重復(fù)遍歷。 層次關(guān)系結(jié)構(gòu) 我這里是想說,呈現(xiàn)出來的HTML具有層次關(guān)系,每一個(gè)樹節(jié)點(diǎn)對(duì)象有層次關(guān)系。HTML層次關(guān)系表現(xiàn)為子節(jié)點(diǎn)的元素一定是父節(jié)點(diǎn)的元素的子節(jié)點(diǎn),本來我覺得這并不是必須的,后來我發(fā)現(xiàn)只有這樣做才能保持子子節(jié)點(diǎn)的狀態(tài),比如我點(diǎn)擊一級(jí)節(jié)點(diǎn)只需要展開所有的二級(jí)節(jié)點(diǎn),三級(jí)或四級(jí)節(jié)點(diǎn)的狀態(tài)不需要改變,HTML結(jié)構(gòu)有這種層次關(guān)系支持就很容易實(shí)現(xiàn)。與之相對(duì)應(yīng)的是樹節(jié)點(diǎn)對(duì)象,它保存著父節(jié)點(diǎn)對(duì)象、子節(jié)點(diǎn)集合對(duì)象、引用元素等等,以方便遞歸調(diào)用,這些信息都被附加到對(duì)應(yīng)的dom元素上。 帶checkbox和radio選擇 實(shí)際項(xiàng)目的需求都是復(fù)雜多變的,有時(shí)候我們需要提供radio單選功能,有時(shí)候可能需要提供checkbox多選功能,為了能在后臺(tái)直接獲取選擇的值,提供帶checkbox和radio選擇功能也是必須的。當(dāng)然,是否創(chuàng)建checkbox或radio我們可以在實(shí)例化時(shí)配置指定,每一個(gè)節(jié)點(diǎn)初始化時(shí)是否選中也可設(shè)置指定,這里需要注意的是我們直接創(chuàng)建checkbox和radio是不能指定name屬性的,轉(zhuǎn)個(gè)彎換種思路來實(shí)現(xiàn)即可。 看似較復(fù)雜的樹結(jié)構(gòu),其實(shí)我只給最外面的容器元素綁定了一個(gè)click事件而已,另外點(diǎn)擊checkbox的聯(lián)動(dòng)也是在這個(gè)click事件里處理的,因?yàn)樵氐氖录菚?huì)向父元素冒泡觸發(fā)的,并且很容易使用事件對(duì)象event獲取觸發(fā)源元素,因此我就能獲取你點(diǎn)擊是checkbox還是什么其他的元素了,很方便。這樣做的好處就是集中來處理一個(gè)事件,而不需要臃腫的給每一個(gè)元素添加事件,充分展示代碼的優(yōu)雅之美。 演示效果: http://demo.jb51.net/js/tree_json/TreeMenu.htm 聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com
代碼如下:
/*
** Author : Jonllen
** Create : 2009-12-13
** Update : 2010-05-08
** SVN : 152
** WebSite: http://www.jonllen.com/
*/
var Menu = function (container) {
this.container = container;
return this;
}
Menu.prototype = {
list : new Array(),
active : new Array(),
iframes : new Array(),
settings : {
id : null,
parentId : 0,
name : null,
url : null,
level : 1,
parent : null,
children : null,
css : null,
element : null
},
push : function (item) {
var list = Object.prototype.toString.apply(item) === '[object Array]' ? item : [item];
for( var i=0; i< list.length; i++) {
var settings = list[i];
for( p in this.settings) {
if( !settings.hasOwnProperty(p) ) settings[p] = this.settings[p];
}
this.list.push(settings);
}
return this;
},
getChlid : function (id) {
var list = new Array();
for( var i=0;i < this.list.length; i++)
{
var item = this.list[i];
if( item.parentId == id)
{
list.push(item);
}
}
return list;
},
render : function (container) {
var _this = this;
var menuElem = container || this.container;
for( var i=0;i < this.list.length; i++)
{
var item = this.list[i];
if ( item.parentId != 0 ) continue;
var itemElem = document.createElement('div');
itemElem.innerHTML = ''+item.name+'';
itemElem.className = 'item';
if ( item.css ) itemElem.className += ' '+item.css;
var disabled = (' '+item.css+' ').indexOf(' disabled ')!=-1;
if ( disabled ) {
itemElem.childNodes[0].disabled = true;
itemElem.childNodes[0].className = 'disabled';
itemElem.childNodes[0].removeAttribute('href');
}
if ( (' '+item.css+' ').indexOf(' hidden ')!=-1 ) {
itemElem.style.display = 'none';
}
itemElem.menu = item;
itemElem.menu.children = this.getChlid(item.id);
itemElem.onmouseover = function (e){
_this.renderChlid(this);
};
menuElem.appendChild(itemElem);
}
document.onclick = function (e){
e = window.event || e;
var target = e.target || e.srcElement;
if (!target.menu) {
var self = _this;
for( var i=1;i<_this.active.length;i++) {
var item = _this.active[i];
var menuElem = document.getElementById('menu'+item.id);
if ( menuElem !=null)
menuElem.style.display = 'none';
}
for(var j=1;j<_this.iframes.length;j++){
_this.iframes[j].style.display = 'none';
}
}
};
},
renderChlid : function (target){
var self = this;
var item = target.menu;
var activeItem = self.active[item.level];
while(activeItem) {
var activeItemElem = activeItem.element;
if ( activeItemElem!= null ) activeItemElem.style.display = 'none';
activeItem = self.active[activeItem.level + 1];
}
self.active[item.level] = item;
var level = item.level;
while(this.iframes[level]) {
this.iframes[level].style.display = 'none';
level++;
}
var childElem = document.getElementById('menu'+item.id);
if (childElem==null) {
var hasChild = false;
for( var j=0;j
hasChild = true;
break;
}
}
if( hasChild) {
var xy = self.elemOffset(target);
var x = xy.x;
var y = target.offsetHeight + xy.y;
if ( item.level >= 2 )
{
x += target.offsetWidth - 1;
y -= target.offsetHeight;
}
childElem = document.createElement('div');
childElem.id = 'menu'+item.id;
childElem.className = 'child';
childElem.style.position = 'absolute';
childElem.style.left = x + 'px';
childElem.style.top = y + 'px';
childElem.style.zIndex = 1000 + item.level;
for( var i=0;i < item.children.length; i++)
{
var childItem = item.children[i];
var childItemElem = document.createElement('a');
var disabled = (' '+childItem.css+' ').indexOf('disabled')!=-1;
if ( disabled ) {
childItemElem.disabled = true;
childItemElem.className += ' '+childItem.css;
}else {
childItemElem.href = childItem.url;
}
if ( (' '+childItem.css+' ').indexOf(' hidden ')!=-1 ) {
childItemElem.style.display = 'none';
}
childItemElem.innerHTML = childItem.name;
childItemElem.menu = childItem;
childItemElem.menu.children = self.getChlid(childItem.id);
var hasChild = false;
for( var j=0;j
hasChild = true;
break;
}
}
if( hasChild ) {
childItemElem.className += ' hasChild';
}
childItemElem.onmouseover = function (e) {
self.renderChlid(this)
};
childElem.appendChild(childItemElem);
}
document.body.insertBefore(childElem,document.body.childNodes[0]);
item.element = childElem;
}
}
if( childElem!=null) {
var iframeElem = this.iframes[item.level];
if ( iframeElem == null) {
iframeElem = document.createElement('iframe');
iframeElem.scrolling = 'no';
iframeElem.frameBorder = 0;
iframeElem.style.cssText = 'position:absolute; overflow:hidden;';
document.body.insertBefore(iframeElem,document.body.childNodes[0]);
this.iframes[item.level]=iframeElem;
}
childElem.style.display = 'block';
iframeElem.width = childElem.offsetWidth;
iframeElem.height = childElem.offsetHeight;
iframeElem.style.left = parseInt(childElem.style.left) + 'px';
iframeElem.style.top = parseInt(childElem.style.top) + 'px';
iframeElem.style.display = 'block';
}
},
elemOffset : function(elem){
if( elem==null) return {x:0,y:0};
var t = elem.offsetTop;
var l = elem.offsetLeft;
while( elem = elem.offsetParent) {
t += elem.offsetTop;
l += elem.offsetLeft;
}
return {x : l,y : t};
}
};
演示地址 http://demo.jb51.net/js/tree_json/menu.htm
打包下載地址
自定義右鍵菜單(ContextMenu)和懸浮層樹(Tree)其實(shí)現(xiàn)上都大同小異,都是在腳本里動(dòng)態(tài)添加節(jié)點(diǎn),然后在生成一個(gè)絕對(duì)定位層,只不過右鍵菜單樹(ContextMenu)觸發(fā)的事件不一樣。另外右鍵菜單還需要提供一個(gè)動(dòng)態(tài)添加菜單項(xiàng)功能,以實(shí)現(xiàn)右擊不同的元素可以顯示不同的右鍵菜單,我這里提供一種"回調(diào)函數(shù)",使用見如下代碼:
ContextMenu回調(diào)函數(shù)
代碼如下:
//ContextMenu
var contextmenu = new ContextMenu(...{ container : document.getElementById('treemenu') });
contextmenu.push( ...{ html : 'Powered By: Jonllen', css : 'disabled'});
contextmenu.push( ...{ html : '', css : 'line'});
contextmenu.push( ...{ html : '刷新(R)', href : 'javascript:location.reload();'});
for(var i=0;i
id : menu[i].id,
level : menu[i].level,
parentId : menu[i].parentId,
html : menu[i].name,
href : menu[i].url
});
}
contextmenu.render();
//原有回調(diào)函數(shù)
var contextmenuOnShow = contextmenu.onShow;
//設(shè)置新的回調(diào)函數(shù)
contextmenu.onShow = function (target, _this)...{
var item = target.treemenu || target.parentNode.treemenu;
if( item ) ...{
var html = '添加'+item.html+'“子節(jié)點(diǎn)'+(item.children.length+1)+'”';
_this.push( ...{
html : html,
click : function (e)...{
item.expand = false;
var newItem = ...{
id : item.id + '0'+ (item.children.length+1),
level : item.level + 1,
parentId : item.id,
html : item.html+'子節(jié)點(diǎn)'+(item.children.length+1),
href : '#',
css : 'item',
createExpand : true
};
item.children.push(newItem);
treemenu.list.push(newItem);
treemenu.renderChild(item);
},
clickClose : true,
index : 1,
type : 'dynamic'
});
_this.push( ...{
html : '刪除節(jié)點(diǎn)“'+item.html+'”',
click : function (e)...{
if( confirm('是否確認(rèn)刪除節(jié)點(diǎn)“'+item.html+'”?'))
treemenu.remove(item);
},
clickClose : true,
index : 2,
type : 'dynamic'
});
}
contextmenuOnShow(target, _this);
};
那么"回調(diào)函數(shù)"如何來實(shí)現(xiàn)呢?其實(shí)很簡單,就是函數(shù)運(yùn)行到某一行代碼時(shí)運(yùn)行預(yù)先設(shè)置的"回調(diào)函數(shù)",有點(diǎn)像事件機(jī)制,如同綁定多個(gè)window.onload事件,由于之前可能有綁定函數(shù),所以先記錄之前的函數(shù),再設(shè)置新綁定的函數(shù),之后再調(diào)用之前綁定的函數(shù)。上面的所示代碼實(shí)現(xiàn)右擊元素如果為treemenu節(jié)點(diǎn),則在右鍵里添加添加和刪除treemenu節(jié)點(diǎn)菜單,效果見后面節(jié)點(diǎn)樹(TreeMenu)示例。
回調(diào)函數(shù)里我們需要注意作用域,this指針指向當(dāng)前回調(diào)函數(shù)對(duì)象,而不是在運(yùn)行回調(diào)函數(shù)的上下里,不過我們也可以使用call方法來把回調(diào)函數(shù)在當(dāng)前this上下文里運(yùn)行。我這里是采用給回調(diào)函數(shù)傳遞2個(gè)參數(shù)的辦法,這樣在回調(diào)函數(shù)就能很方便的獲取this對(duì)象和其他變量,這個(gè)在Ajax的Callback回調(diào)函數(shù)里普遍使用。
自定義右鍵菜單(ContextMenu)只適合一些輔助功能的快捷操作,如有一些業(yè)務(wù)功能復(fù)雜的OA系統(tǒng)等,下面我也將會(huì)結(jié)合節(jié)點(diǎn)樹(TreeMenu)進(jìn)行使用。如果可以話盡量不要使用右鍵菜單,其一是需要培訓(xùn)用戶右擊操作的習(xí)慣,其二自定義右鍵菜單丟失掉了原有右鍵菜單的一些功能,如查看源文件等。
這里右鍵菜單區(qū)域。
右擊我你可以看屬性哦。
你也可以選擇我再右擊復(fù)制。
你能遮住我嗎?
ContextMenu.js
代碼如下:
/**//*
** Author : Jonllen
** Create : 2010-05-01
** Update : 2010-05-09
** SVN : 153
** WebSite: http://www.jonllen.com/
*/
var ContextMenu = function (settings) ...{
for( p in this.settings)
...{
if( !settings.hasOwnProperty(p) ) settings[p] = this.settings[p];
}
this.settings = settings;
this.settings.menu = document.createElement('div');
this.settings.menu.className = this.settings.css;
this.settings.menu.style.cssText = 'position:absolute;display:none;';
document.body.insertBefore(this.settings.menu,document.body.childNodes[0]);
return this;
}
ContextMenu.prototype = ...{
list : new Array(),
active : new Array(),
iframes : new Array(),
settings : ...{
menu : null,
excursionX : 0,
excursionY : 0,
css : 'contextmenu',
container : null,
locked : false
},
item : ...{
id : null,
level : 1,
parentId : 0,
html : '',
title : '',
href : 'javascript:;',
target : '_self',
css : null,
element : null,
childElement : null,
parent : null,
children : null,
type : 'static',
click : null,
clickClose : false
},
push : function (item) ...{
var list = Object.prototype.toString.apply(item) === '[object Array]' ? item : [item];
for( var i=0; i< list.length; i++) ...{
var _item = list[i];
for( p in this.item) ...{
if( !_item.hasOwnProperty(p) ) _item[p] = this.item[p];
}
_item.element = null;
if( _item.name ) _item.html = _item.name;
if( _item.url ) _item.href = _item.url;
if( _item.type == 'static') ...{
this.list.push(_item);
}else ...{
if(this.dynamic == null) this.dynamic = new Array();
this.dynamic.push(_item);
}
}
return this;
},
bind : function ()...{
var _this = this;
for( var i=0; this.dynamic && i
var item = this.dynamic[i];
var itemElem = document.createElement('div');
itemElem.title = item.title;
itemElem.innerHTML = ''+item.html+'';
itemElem.className = 'item ' + (item.css?' '+item.css:'');
item.element = itemElem;
if( item.click ) ...{
(function (item)...{
item.element.childNodes[0].onclick = function (e)...{
if( item.clickClose) _this.hidden();
return item.click(e);
};
})(item);
}
itemElem.contextmenu = item;
itemElem.onmouseover = function (e)...{ _this.hidden(item.level);};
var index = item.index || 0;
if( index >= this.settings.menu.childNodes.length)
index = this.settings.menu.childNodes.length - 1;
if( index < 0 )
this.settings.menu.appendChild(itemElem);
else
this.settings.menu.insertBefore(itemElem, this.settings.menu.childNodes[index]);
}
},
render : function ( container ) ...{
var _this = this;
container = container || this.settings.container;
this.settings.menu.innerHTML = '';
for( var i=0;i < this.list.length; i++)
...{
var item = this.list[i];
if ( item.parentId != 0 ) continue;
var itemElem = document.createElement('div');
itemElem.title = item.title;
itemElem.innerHTML = ''+item.html+'';
itemElem.className = 'item ' + (item.css?' '+item.css:'');
var disabled = _this.hasClass(itemElem, 'disabled');
if ( disabled ) ...{
itemElem.childNodes[0].disabled = true;
itemElem.childNodes[0].className = 'disabled';
itemElem.childNodes[0].removeAttribute('href');
}
if ( _this.hasClass(itemElem, 'hidden') ) ...{
itemElem.style.display = 'none';
}
if( item.click ) ...{
(function (item)...{
item.element.childNodes[0].onclick = function (e)...{
if( item.clickClose) _this.hidden();
return item.click(e);
};
})(item);
}
itemElem.contextmenu = item;
itemElem.contextmenu.children = this.getChlid(item.id);
if( itemElem.contextmenu.children.length > 0 )
itemElem.childNodes[0].className += ' hasChild';
itemElem.onmouseover = function (e)...{ _this.renderChlid(this);};
this.settings.menu.appendChild(itemElem);
}
this.active[0] = ...{ element : _this.settings.menu };
this.settings.menu.contextmenu = _this;
container.oncontextmenu = function (e)...{
e = window.event || e;
var target = e.target || e.srcElement;
if( e.preventDefault)
e.preventDefault();
var mouseCoords = _this.mouseCoords(e);
_this.settings.menu.style.left = mouseCoords.x + _this.settings.excursionX + 'px';
_this.settings.menu.style.top = mouseCoords.y + _this.settings.excursionY + 'px';
_this.hidden();
_this.show(0, target);
return false;
};
this.addEvent(document, 'click', function (e)...{
e = window.event || e;
var target = e.target || e.srcElement;
var isContextMenu = !!target.contextmenu;
if( isContextMenu == false) ...{
var parent = target.parentNode;
while( parent!=null) ...{
if( parent.contextmenu) ...{
isContextMenu = true;
break;
}
parent = parent.parentNode;
}
}
if (isContextMenu == false) ...{
_this.hidden();
}
});
},
renderChlid : function ( target )...{
if(this.settings.locked) return;
var contextmenu = target.contextmenu;
var currentLevel = contextmenu.level;
this.hidden(currentLevel);
var hasChild = false;
for( var j=0;j
hasChild = true;
break;
}
}
if( !hasChild) return;
var childElem = contextmenu.element;
if (childElem == null) ...{
childElem = document.createElement('div');
childElem.className = this.settings.css;
childElem.style.position = 'absolute';
childElem.style.zIndex = 1000 + contextmenu.level;
var _this = this;
for( var i=0;i < contextmenu.children.length; i++)
...{
var childItem = contextmenu.children[i];
var childItemElem = document.createElement('div');
childItemElem.title = childItem.title;
childItemElem.innerHTML = ''+childItem.html+'';
childItemElem.className = 'item' + (childItem.css?' '+childItem.css : '');
var disabled = this.hasClass(childItemElem, 'disabled');
if ( disabled ) ...{
childItemElem.childNodes[0].disabled = true;
childItemElem.childNodes[0].removeAttribute('href');
}
if ( this.hasClass(childItemElem, 'hidden') ) ...{
childItemElem.style.display = 'none';
}
if( childItem.click ) ...{
(function (childItem)...{
childItem.element.childNodes[0].onclick = function (e)...{
if( childItem.clickClose) _this.hidden();
return childItem.click(e);
};
})(childItem);
}
childItem.parent = contextmenu;
childItemElem.contextmenu = childItem;
childItemElem.contextmenu.children = this.getChlid(childItem.id);
var hasChild = false;
for( var j=0; j
hasChild = true;
break;
}
}
if( hasChild ) ...{
childItemElem.childNodes[0].className += ' hasChild';
}
childItemElem.onmouseover = function (e)...{ _this.renderChlid(this);};
childElem.appendChild(childItemElem);
}
document.body.insertBefore(childElem,document.body.childNodes[0]);
contextmenu.element = childElem;
}
this.active[currentLevel] = contextmenu;
var xy = this.elemOffset(target);
var x = xy.x + target.offsetWidth + this.settings.excursionX;
var y = xy.y + this.settings.excursionY;
childElem.style.left = x + 'px';
childElem.style.top = y + 'px';
childElem.style.display = 'block';
this.show(currentLevel);
},
getChlid : function (id) ...{
var list = new Array();
for( var i=0;i < this.list.length; i++)
...{
var item = this.list[i];
if( item.parentId == id)
...{
list.push(item);
}
}
return list;
},
show : function (level, target) ...{
if(this.settings.locked) return;
level = level || 0;
var item = this.active[level];
if ( level == 0 ) ...{
for( var i=0;this.dynamic && i < this.dynamic.length; i++)
...{
var dynamicItemElem = this.dynamic[i].element;
if( dynamicItemElem !=null) dynamicItemElem.parentNode.removeChild(dynamicItemElem);
}
if (this.dynamic) this.dynamic.length = 0;
this.onShow(target, this);
}
var menuElem = item.element;
menuElem.style.display = 'block';
var iframeElem = this.iframes[level];
if ( iframeElem == null) ...{
iframeElem = document.createElement('iframe');
iframeElem.scrolling = 'no';
iframeElem.frameBorder = 0;
iframeElem.style.cssText = 'position:absolute; overflow:hidden;';
document.body.insertBefore(iframeElem,document.body.childNodes[0]);
this.iframes.push(iframeElem);
}
iframeElem.width = menuElem.offsetWidth;
iframeElem.height = menuElem.offsetHeight;
var menuElemOffset = this.elemOffset(menuElem);
iframeElem.style.left = menuElemOffset.x + 'px';
iframeElem.style.top = menuElemOffset.y + 'px';
iframeElem.style.display = 'block';
},
onShow : function (target, _this) ...{
if( target.nodeType == 1 && target.tagName == 'A' && target.innerHTML.indexOf('.rar') != -1 )...{
//解壓文件
_this.push( ...{
html : '解壓縮到“'+target.innerHTML.substring(0,target.innerHTML.lastIndexOf('.'))+'\\”...',
click : function (e)...{
e = e || window.event;
var srcElement = e.srcElement || e.target;
srcElement.className = 'on';
srcElement.innerHTML = '解壓縮到“'+target.innerHTML.substring(0,target.innerHTML.lastIndexOf('.'))+'\\”...';
var url = '/Ajax/FileZip.aspx?mode=unzip&files='+target.href.substring(target.href.replace('//','xx').indexOf('/'));
if( typeof Ajax == 'undefined') return;
Ajax.get(url, function (data, _this)...{
_this.settings.locked = true;
eval(data);
if( rs.success ) ...{
location.reload();
}else...{
alert(rs.error);
_this.hidden();
}
}, _this);
srcElement.onclick = null;
_this.settings.locked = true;
},
clickClose : false,
index : 2,
type : 'dynamic'
});
}
else if( target.nodeType == 1 && target.title.indexOf('添加到') == 0) ...{
//添加單個(gè)壓縮文件
_this.push( ...{
html : target.title,
title : target.title,
click : function (e)...{
var index = target.href.indexOf('?path=');
if( index != -1)...{
var fullName = target.href.substring(index+'?path='.length);
}else ...{
var fullName = target.href.substring(target.href.replace('//','xx').indexOf('/'));
}
e = e || window.event;
var srcElement = e.srcElement || e.target;
srcElement.className = 'on';
srcElement.innerHTML = '正在添加到“'+fullName.substring(fullName.lastIndexOf('/')+1)+'.rar”...';
var url = '/Ajax/FileZip.aspx?mode=zip&files='+fullName;
if( typeof Ajax == 'undefined') return;
Ajax.get(url, function (data, _this)...{
_this.settings.locked = true;
eval(data);
if( rs.success ) ...{
location.reload();
}else...{
alert(rs.error);
_this.hidden();
}
}, _this);
srcElement.onclick = null;
_this.settings.locked = true;
},
clickClose : false,
index : 2,
type : 'dynamic',
css : 'on'
});
}else ...{
//添加多個(gè)壓縮文件
var fileName = '';
var files = new Array();
var ids = document.getElementsByName('ids');
for( var i=0; i
var file = ids[i].value;
files.push(file);
if( files.length == 1) ...{
fileName = file.substring(file.lastIndexOf('/')+1) + '.rar';
}
}
if( files.length > 0 )...{
_this.push( ...{
html : '添加'+files.length+'個(gè)文件到壓縮包“'+fileName+'”',
click : function (e)...{
e = e || window.event;
var srcElement = e.srcElement || e.target;
srcElement.className = 'on';
srcElement.innerHTML = '正在添加到“'+fileName+'”...';
var url = '/Ajax/FileZip.aspx?mode=zip&files='+files.join('|');
if( typeof Ajax == 'undefined') return;
Ajax.get(url, function (data, _this)...{
_this.settings.locked = true;
eval(data);
if( rs.success ) ...{
location.reload();
}else...{
alert(rs.error);
_this.hidden();
}
}, _this);
srcElement.onclick = null;
_this.settings.locked = true;
},
clickClose : false,
index : 2,
type : 'dynamic'
});
}
}
if( target.nodeType == 1 && target.tagName == 'A') ...{
_this.push( ...{
html : '屬性“'+target.innerHTML+'”',
href : target.href,
click : function (e)...{
prompt('屬性“'+target.innerHTML+'”',target.href);
return false;
},
clickClose : true,
index : 3,
type : 'dynamic'
});
}
var selection = window.getSelection ? window.getSelection().toString() : document.selection.createRange().text;
if( selection ) ...{
_this.push( ...{
html : '復(fù)制“' + (selection.length > 15 ? selection.substring(0,12) + '...' : selection) +'”',
title : '復(fù)制“' + selection + '”',
click : function (e) ...{
if(window.clipboardData) ...{
window.clipboardData.clearData();
window.clipboardData.setData("Text", selection);
}else ...{
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var clip = Components.classes['@mozilla.org/widget/clipboard;1'].createInstance(Components.interfaces.nsIClipboard);
var trans = Components.classes['@mozilla.org/widget/transferable;1'].createInstance(Components.interfaces.nsITransferable);
if (!clip || !trans) return;
trans.addDataFlavor('text/unicode');
var len = new Object();
var str = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString);
str.data = selection;
trans.setTransferData("text/unicode",str,selection.length*2);
var clipid=Components.interfaces.nsIClipboard;
if (!clip) return false;
clip.setData(trans,null,clipid.kGlobalClipboard);
}
},
clickClose : true,
index : 0,
type : 'dynamic'
});
}
_this.bind();
},
hidden : function (level) ...{
level = level || 0;
for( var i = level; i
var iframeElem = this.iframes[i];
if ( iframeElem !=null)
iframeElem.style.display = 'none';
if(this.settings.locked) return;
var menuElem = item.element;
if ( menuElem !=null)
menuElem.style.display = 'none';
}
this.onHidden(level);
},
onHidden : function (level) ...{
},
hasClass : function (elem, name)
...{
return !!elem && (' '+elem.className+' ').indexOf(' '+name+' ') != -1;
},
elemOffset : function(elem)...{
var left = 0;
var top = 0;
while (elem.offsetParent)...{
left += elem.offsetLeft;
top += elem.offsetTop;
elem = elem.offsetParent;
}
left += elem.offsetLeft;
top += elem.offsetTop;
return ...{x:left, y:top};
},
mouseCoords : function (e)...{
if (e.pageX && e.pageY) ...{
return ...{
x: e.pageX,
y: e.pageY
};
}
var d = (document.documentElement && document.documentElement.scrollTop) ? document.documentElement : document.body;
return ...{
x: e.clientX + d.scrollLeft,
y: e.clientY + d.scrollTop
};
},
addEvent : function(target,eventType,func)...{
if(target.attachEvent)
...{
target.attachEvent("on" + eventType, func);
}else if(target.addEventListener)
...{
target.addEventListener(eventType == 'mousewheel' ? 'DOMMouseScroll' : eventType, func, false);
}
return this;
},
removeEvent : function(target,eventType,func)...{
if(target.detachEvent)
...{
target.detachEvent("on" + eventType, func);
}else if(target.removeEventListener)
...{
target.removeEventListener(eventType == 'mousewheel' ? 'DOMMouseScroll' : eventType, func, false);
}
return this;
}
}
演示地址 http://demo.jb51.net/js/tree_json/ContextMenu.htm
3.節(jié)點(diǎn)樹(TreeMenu)
節(jié)點(diǎn)樹(TreeMenu)是我們實(shí)際項(xiàng)目中運(yùn)用得最多了,網(wǎng)上很著名的有梅花雪的MzTreeVew,聽說對(duì)大數(shù)據(jù)量時(shí)做了一些優(yōu)化,效率很高。但我不太喜歡拿來主義,有些東西既然我看不懂或還不明白它為什么要這么做,所以就想嘗試著自己來"造輪子"。當(dāng)然功能肯定是沒有MzTreeVew的那么強(qiáng)大,大數(shù)據(jù)量時(shí)我也沒有做效率測(cè)試,圖片先借MzTreeVew的。
代碼如下:
var inputTemp = document.createElement('div');
inputTemp.innerHTML = '';
var inputElem = inputTemp.childNodes[0];
只綁定一個(gè)click事件
打包下載地址 JavaScript 多種樹結(jié)構(gòu)菜單效果
本文轉(zhuǎn)載自金龍博客:http://www.jonllen.com/jonllen/js/menu.aspx,轉(zhuǎn)載請(qǐng)保留此段聲明。