1. 中断されたレイヤー ツリー (ツリー) このツリー構造は、ノードのマウス移動イベントをリッスンして、下または右に子ノードを表示します。ノードの子ノードなどを再帰的に表示します。
ユーザーのホームページ ブログ設定 記事 アルバム メッセージ コメント システム
ここで注意すべき小さな問題がいくつかあります。まず、この種のツリー構造は、レイヤーを作成するときの絶対的な配置です。以下では、これは、IE でコンテキストをスタックするなどの隠されたルールがあるため、IE で確実にカバーできるようにするために行われます。また、もちろん、選択できます。私をカバーしますか?古い質問ですが、これは各フローティングレイヤーの後ろに iframe 要素を追加することです。もちろん、メニューに複数のレベルがある場合、同じレベルのメニューは複数の iframe マスクを生成します。表示と非表示を切り替えると、iframe の表示と非表示が同時に行われます。
ただし、この種のメニューはフロントエンドには適していません。これは、現時点ではスクリプト内でのメニュー ノードの動的追加のみがサポートされており、SEO などの目的で既存の HTML 要素からメニュー ノードを取得できないためです。フロントエンド ナビゲーション。通常はバックグラウンドで動的に追加します。出力の場合、メニューに複数のレベルがある場合、顧客はあまりにも多くのレベルを見るのが面倒になりますが、それでも非常に優れています。ブレッドクラムナビゲーション表示を行うには。
menu.js
/*
** 著者 : Jonllen
** 作成 : 2009-12-13
** 更新 : 2010-05-08
** SVN : 152
** Web サイト: http://www.jonllen.com/
*/
var Menu = function (container) {
this.container = コンテナ;
これを返します;
}
Menu.prototype = {
list : new Array(),
active : new Array(),
iframes : new Array(),
settings : {
id : null、
parentId : 0、
name : null、
url : null、
レベル : 1、
親 : null、
子 : null、
css : null,
element : null
},
push : function (item) {
var list = Object.prototype.toString.apply(item) === '[オブジェクト配列]' ?アイテム : [アイテム];
for( var i=0; i
var settings = list[i]; for( p in this.settings) { if( !settings.hasOwnProperty(p) ) settings[p] = this.settings[p]; } this.list.push(設定); } これを返します; }, 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); } } リストを返します。 }, render : function (container) { var _this = this; var menuElem = コンテナ || this.container; for( var i=0;i < this.list.length; i ) { var item = this.list[i]; if ( item.parentId != 0 ) 続行; var itemElem = document.createElement('div'); itemElem.innerHTML = '' item.name ' '; itemElem.className = 'アイテム'; if ( item.css ) itemElem.className = ' ' item.css; var 無効 = (' ' item.css ' ').indexOf(' 無効 ')!=-1; if (無効) { itemElem.childNodes[0].disabled = true; itemElem.childNodes[0].className = '無効'; itemElem.childNodes[0].removeAttribute('href'); } if ( (' ' item.css ' ').indexOf(' hidden ')!=-1 ) { itemElem.style.display = 'none'; } itemElem.menu = アイテム; itemElem.menu.children = this.getChlid(item.id); itemElem.onmouseover = function (e){ _this.renderChlid(this); }; menuElem.appendChild(itemElem); } document.onclick = function (e){ e = window.even || e; var target = e.target || e.src要素; if (!target.menu) { var self = _this; for( var i=1;i<_this.active.length>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>_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] = アイテム; var レベル = item.level; while(this.iframes[レベル]) { this.iframes[レベル].style.display = 'none'; レベル; } var childElem = document.getElementById('menu' item.id); if (childElem==null) { var hasChild = false; for( var j=0;jif( (' ' item.children[j].css ' ').indexOf(' hidden ') == - 1) { hasChild = true; 休憩; } } 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 = 'メニュー' item.id; childElem.className = '子'; childElem.style.position = '絶対'; 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 無効 = (' ' childItem.css ' ').indexOf('無効')!=-1; if (無効) { 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;jif( (' ' childItemElem.menu.children[j].css ' ').indexOf(' hidden ' ) == -1) { hasChild = true; 休憩; } } 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 = 'いいえ'; iframeElem.frameBorder = 0; iframeElem.style.cssText = '位置:絶対;オーバーフロー:非表示;'; document.body.insertBefore(iframeElem,document.body.childNodes[0]); this.iframes[item.level]=iframeElem; } childElem.style.display = 'ブロック'; 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 = 'ブロック'; } }, 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 打包下ダウンロード地址
2.右键菜单树(ContextMenu) 自定右键菜单(ContextMenu) 和悬浮层树(Tree)其实现上都大同小异,都是在記里动态追加节点さらに、右のメニューは、異なる要素が異なる右のメニューを表示できるようにするために、右のメニュー(ContextMenu)によってのみ起動されるイベントを追加する必要があります。单、我这里提供一种"回调関数",使用见如下代:
ContextMenu回调関数
//ContextMenu
var contextmenu = new ContextMenu(...{ コンテナ : 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
contextmenu.push(...{ id : menu[i].id, level : menu[i].level, parentId : menu[i].parentId, html : menu[i].name, href : menu[i].url }); } contextmenu.render(); //原有回调関数 var contextmenuOnShow = contextmenu.onShow; //設定新しい回调関数数 contextmenu.onShow = function (target, _this)...{ var item = target.treemenu || target.parentNode.treemenu; if( item ) ...{ var html = '追加' item.html '“子节点' (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 '子节点' (item.children.length 1), href : '#', css : 'item', createExpand : true }; ; treemenu.list.push(newItem); treemenu.renderChild(item); clickClose : true、 index : 1、 type : 'dynamic' }); _this.push( ...{ html : '删除节点“' item.html '”', click : function (e)...{ if(confirm('是否确认删除节点“' item.html '”?')) treemenu.remove(item); }, clickClose : true, index : 2, type : 'dynamic ' }); } contextmenuOnShow(target, _this); }; それでは、「コールバック関数」を実装するにはどうすればよいでしょうか?実際、関数が特定のコード行に到達すると、事前に設定された「コールバック関数」が実行されます。これは、複数の window.onload イベントをバインドするようなイベント メカニズムに似ています。前に、最初に以前の関数を記録し、次に新しくバインドされた関数を設定してから、以前にバインドされた関数を呼び出します。上記のコードは、右クリック要素がツリーメニュー ノードの場合、右クリックでツリーメニュー ノードの追加および削除メニューが追加されることを実現しています。その効果は、以下のノード ツリー (TreeMenu) の例に示されています。 this ポインタは、コールバック関数が実行されるコンテキストではなく、現在のコールバック関数オブジェクトを指すことに注意する必要があります。現在の this コンテキストのコールバック関数。ここでは、コールバック関数がこのオブジェクトと他の変数を簡単に取得できるように、コールバック関数に 2 つのパラメーターを渡す方法を採用しています。これは Ajax コールバック関数でよく使用されます。 カスタム右クリック メニュー (ContextMenu) は、一部の補助機能のショートカット操作にのみ適しています。たとえば、複雑な業務機能を備えた OA システムがある場合は、ノード ツリー (TreeMenu) と組み合わせて使用します。 ) 下に。可能であれば、右クリック メニューを使用しないようにしてください。第 2 に、右クリック メニューをカスタマイズすると、表示などの元の右クリック メニューの機能が失われます。ソースファイル。 ここは右クリックメニューエリアです。 私を右クリックすると、プロパティが表示されます。 私を選択して右クリックしてコピーすることもできます。 カバーしてもらえますか? ContextMenu.js
/**//*
** 著者 : Jonllen
** 作成 : 2010-05-01
** 更新 : 2010-05-09
** SVN : 153
** ウェブサイト: http://www.jonllen.com/
*/
var ContextMenu = function (settings) ...{
for( p in this.settings)
...{
if ( !settings.hasOwnProperty(p) ) 設定[p] = this.settings[p];
}
this.settings = 設定;
this.settings.menu = document.createElement('div');
this.settings.menu.className = this.settings.css;
this.settings.menu.style.cssText = '位置:絶対;表示:なし;';
document.body.insertBefore(this.settings.menu,document.body.childNodes[0]);
これを返します;
}
ContextMenu.prototype = ...{
list : new Array()、
active : new Array()、
iframes : new Array()、
settings : ...{
メニュー : null,
excursionX : 0,
excursionY : 0,
css : 'contextmenu',
コンテナ : null,
ロック : false
},
item : ...{
id : null,
level : 1,
parentId : 0,
html : '',
title : '',
href : 'javascript:;'、
ターゲット : '_self'、
css : null、
要素 : null、
childElement : null、
親 : null、
子: null,
type : 'static',
click : null,
clickClose : false
},
push : function (item) ...{
var list = Object .prototype.toString.apply(item) === '[オブジェクト配列]' ?アイテム : [アイテム];
for( var i=0; 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); } } これを返します; }, 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 = アイテム; itemElem.onmouseover = function (e)...{ _this.hidden(item.level);}; var インデックス = item.index || 0; if(index >= this.settings.menu.childNodes.length) index = this.settings.menu.childNodes.length - 1; if(index this.settings.menu.appendChild(itemElem); else this.settings.menu.insertBefore(itemElem, this.settings.menu.childNodes[index]); } }, render : function (container) ...{ var _this = this; コンテナ = コンテナ || 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 ) 続行; var itemElem = document.createElement('div'); itemElem.title = item.title; itemElem.innerHTML = '' item.html ' '; itemElem.className = 'item ' (item.css?' ' item.css:''); vardisabled = _this.hasClass(itemElem, 'disabled'); if (無効) ...{ itemElem.childNodes[0].disabled = true; itemElem.childNodes[0].className = '無効'; 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 = アイテム; 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] = ...{ 要素 : _this.settings.menu }; this.settings.menu.contextmenu = _this; container.oncontextmenu = function (e)...{ e = window.event || e; var target = e.target || e.src要素; 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, ターゲット); false を返します。 }; this.addEvent(document, 'click', function (e)...{ e = window.event || e; var target = e.target || e.srcElement; var isContextMenu = !!target.contextmenu; if( isContextMenu == false) ...{ varparent = target.parentNode; while(parent!=null) >if(parent.contextmenu) ...{ isContextMenu = true; } parent =parent.parentNode; == 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;jif( (' ' contextmenu.children[j].css ' ').indexOf(' hidden ') == -1) ...{ hasChild = true; 休憩; } } if( !hasChild) return; var childElem = contextmenu.element; if (childElem == null) ...{ childElem = document.createElement('div'); childElem.className = this.settings.css; childElem.style.position = '絶対'; 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 : ''); vardisabled = this.hasClass(childItemElem, 'disabled'); if (無効) ...{ 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; jif( (' ' childItemElem.contextmenu.children[j].css ' ').indexOf( ' 非表示 ') == -1) ...{ hasChild = true; 休憩; } } 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 = 'ブロック'; 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); } } リストを返します。 }, show : function (level, target) ...{ if(this.settings.locked) return; レベル = レベル || 0; var item = this.active[レベル]; 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(ターゲット, this); } var menuElem = item.element; menuElem.style.display = 'ブロック'; var iframeElem = this.iframes[レベル]; if ( iframeElem == null) ...{ iframeElem = document.createElement('iframe'); iframeElem.scrolling = 'いいえ'; iframeElem.frameBorder = 0; iframeElem.style.cssText = '位置:絶対;オーバーフロー:非表示;'; 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 = 'ブロック'; }, 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 || 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( Ajax のタイプ == '未定義') 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; }, clickClose : false; インデックス : 2、 タイプ : '動的' }); } else if( target.nodeType == 1 && target.title.indexOf('追加へ') == 0) ...{ // 追加单个压缩文件 _this. Push( ...{ html : target.title, title : target.title, click : function (e)...{ varindex = 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 = '正在追加' fullName.lastIndexOf ('/') 1) '.rar”...'; var url = '/Ajax/FileZip.aspx?mode=zip&files=' if( typeof Ajax == 'unknown') return; Ajax.get(url, function (data, _this)...{ _this.settings.locked = true; eval(data); if( rs.success ) . ..{ location.reload(); }else...{ alert(rs.error); } }; ); srcElement.onclick = null; _this.settings.locked = true; }, clickClose : false, index : 2, type : 'dynamic', css : 'on' }); }else ...{ // 多个压缩文件を追加 var fileName = ''; var ファイル = new Array(); var ids = document.getElementsByName('ids'); for( var i=0; iif( !ids[i].checked) continue; var ファイル = ids[i].value; files.push(ファイル); if( files.length == 1) ...{ fileName = file.substring(file.lastIndexOf('/') 1) '.rar'; } } if( files.length > 0 )...{ _this.push( ...{ html : '追加' files.length '个文件到压缩包“' fileName '”', click : function (e)...{ e = e || var srcElement = e.srcElement || 🎜>srcElement.className = 'on'; srcElement.innerHTML = '正在追加“' fileName '”...' var url = '/Ajax/FileZip.aspx?mode=zip&files='; files.join('|'); if( typeof Ajax == '未定義') return; Ajax.get(url, function (data, _this)...{ _this.settings.ロック = true; eval(data); if( rs.success ) ...{ location.reload(); alert(rs.エラー); _this.hidden(); } }, _this); _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' }); } varselection = window.getSelection ? window.getSelection().toString() : document.selection.createRange().text; if(selection) ...{ _this.push( ...{ html : '复制“' (selection.length > 15 ?selection.substring(0,12) '.. .' : 選択) '”', タイトル : '复制”' 選択 '”', クリック : function (e) ...{ if(window.clipboardData) ...{ window.clipboardData.clearData(); window.clipboardData.setData("テキスト", }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 = 新しいオブジェクト(); var str = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString); str.data = 選択; trans.setTransferData("text/unicode",str,selection.length*2); var Clipid=Components.interfaces.nsIClipboard; if (!clip) は false を返します。 clip.setData(trans,null,clipid.kGlobalClipboard); } }, clickClose : true, index : 0, type : 'dynamic' }); } _this.bind(); }, hidden : 関数 (レベル) ...{ レベル = レベル || 0; for( var i = level; ivar item = this.active[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(レベル); }, onHidden : 関数 (レベル) ...{ }, hasClass : 関数 (elem, 名前) ...{ return !!elem && ( ' ' elem.className ' ').indexOf(' ' 名前 ' ') != -1; }, elemOffset : function(elem)...{ var left = 0; var トップ = 0; while (elem.offsetParent)...{ left = elem.offsetLeft; トップ = elem.offsetTop; elem = elem.offsetParent; } left = elem.offsetLeft; トップ = 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,関数); }else if(target.addEventListener) ...{ target.addEventListener(eventType == 'mousewheel' ? 'DOMMouseScroll' :eventType, func, false); } これを返します; }, removeEvent : function(target,eventType,func)...{ if(target.detachEvent) ...{ target.detachEvent("on"eventType,関数); }else if(target.removeEventListener) ...{ target.removeEventListener(eventType == 'mousewheel' ? 'DOMMouseScroll' :eventType, func, false); } これを返します; } } デモアドレスhttp://demo.jb51.net/js/tree_json/ContextMenu.htm 3. ノードツリー (TreeMenu) ノード ツリー (TreeMenu) は、実際のプロジェクトで最もよく使用されます。インターネット上で有名な Meihuaxue の MzTreeVew は、大量のデータ向けに最適化されており、非常に効率的です。しかし、私は物事を採用するのがあまり好きではありません。理解できないことや、なぜそのようなことをするのかがわからないので、自分で「車輪を発明」してみたいと思っています。もちろん、この機能は MzTreeVew ほど強力ではありません。最初に MzTreeVew から画像を借りたときの効率テストは行いませんでした。 無限レベルのノードツリー 無限レベルの関数を実現するには、コツがなければ再帰しかないようです。ただし、無限ループを回避するには、リターンを決定するための正しい条件が必要であることに注意してください。データ ストレージ構造に関しては、通常、データベースには id、name、parentId フィールドが保存されますが、この構造はツリー ノードを展開するときにも、id に基づいてすべての子ノードを取得して保存する必要があります。 . 、2 度目の反復を避けるため。 階層関係構造 ここで言いたいのは、提示されている HTML には階層関係があり、各ツリー ノード オブジェクトにも階層関係があるということです。 HTML の階層関係は、子ノードの要素が親ノードの要素の子ノードでなければならないことを示しています。最初はこれは必要ないと思っていましたが、後でこれを行うことによってのみ子ノードの状態を維持できることがわかりました。たとえば、第 1 レベルのノードをクリックすると、第 2 レベルのノードをすべて展開するだけで済み、第 3 レベルまたは第 4 レベルのノードのステータスを変更する必要はありません。HTML 構造は簡単に実装できます。この階層関係のサポートにより、これに対応するのがツリー ノード オブジェクトで、再帰呼び出しを容易にするために親ノード オブジェクト、子ノード コレクション オブジェクト、参照要素などが格納されます。この情報は対応する DOM 要素に付加されます。 チェックボックスとラジオ選択機能付き 実際のプロジェクトのニーズは複雑で変わりやすいものです。ラジオの単一選択機能を提供する必要がある場合もあれば、チェックボックスの複数選択機能を提供する必要がある場合もあります。そのためには、バックグラウンドで選択された値を直接取得し、チェックボックスとラジオ選択機能を提供することも必要です。もちろん、インスタンス化時に各ノードを選択するかどうかを設定して指定することもできますが、ここで注意する必要があるのは、直接作成するときに name 属性を指定できないことです。ひねりを加えれば、チェックボックスやラジオを実装するだけです。 var inputTemp = document.createElement('div '); inputTemp.innerHTML = ' '; var inputElem = inputTemp.childNodes[0]; >Tie のみクリックイベントを定義する
より複雑なツリー構造のように見えますが、実際には一番外側のコンテナ要素にクリックイベントをバインドしているだけです。また、チェックボックスをクリックするというリンクも で処理されます。このクリック イベントは、要素のイベントがバブルアップして親要素にトリガーされ、イベント オブジェクト イベントを使用してトリガー ソース要素を取得するのが簡単であるため、チェックボックスまたはその他の要素をクリックしたかどうかを取得できます。とても便利です。この利点は、各要素にイベントを追加するのではなく、1 つのイベントの処理に集中できることです。これにより、コードの優雅さと美しさが十分に発揮されます。 デモ効果: http://demo.jb51.net/js/tree_json/TreeMenu.htm パッケージのダウンロードアドレス JavaScript 複数ツリー構造メニュー効果 これに転載記事 Jinlong ブログより: http://www.jonllen.com/jonllen/js/menu.aspx 、転載する際はこの記述を守ってください。