📄 zpmenu-core.js
字号:
} else if (this.config.glide) { this.addAnimation('glide'); } else if (this.config.wipe) { this.addAnimation('wipe'); } else if (this.config.unfurl) { this.addAnimation('unfurl'); } // Oninit callback if (typeof this.config.onInit == 'function') { // To be able to reference to this object from onInit function setTimeout(function() { objMenu.config.onInit(); }, 0); }};/** * Initializes a menu from the HTML source. * * @private * @param {object} objSource Source HTMLElement object */Zapatec.Menu.prototype.loadDataHtml = function(objSource) { // Check arguments if (!objSource) { return; } this.list = objSource; this.items = {}; this.trees = {}; this.selectedItem = null; // Sub-menu container counter this.lastContainerNumber = 0; this.menuId = objSource.id || Zapatec.Utils.generateID("tree"); var objContainer = this.top_parent = Zapatec.Utils.createElement("div"); // Initially menu is hidden and will be shown on triggerEvent objContainer.style.display = 'none'; // In order to work correctly when menu is put inside <center></center> objContainer.style.textAlign = 'left'; objContainer.__zp_menu = Zapatec.Utils.createElement("div", objContainer); objContainer.__zp_menu.className = 'zpMenu'; objContainer.className = "zpMenuContainer zpMenu-top"; if (this.config.vertical) { // vertical:true, set top div container class to // NOTE:zpMenu-vertical-mode and zpMenu-level-1 defines the top vertical menu Zapatec.Utils.addClass(objContainer, "zpMenu-vertical-mode"); } else { Zapatec.Utils.addClass(objContainer, "zpMenu-horizontal-mode"); } // Create menu var strRootMenuId = this.createTree(objSource, objContainer, 0); // Reference to the root menu this.rootMenu = this.trees[strRootMenuId]; // Associate menu with the theme var objTheme = Zapatec.Utils.createElement('div'); objTheme.className = this.getClassName({prefix: 'zpMenu'}); objTheme.appendChild(objContainer); // Insert menu into the page if (this.container) { // Put menu into the specified container this.container.appendChild(objTheme); } else { // Replace source ul element with menu objSource.parentNode.insertBefore(objTheme, objSource); objSource.parentNode.removeChild(objSource); } Zapatec.Menu.all[this.menuId] = this; // check if we have an initially selected node and sync. the tree if so if (this.selectedItem) { this.sync(this.selectedItem.__zp_item); } // Get path from cookies this.path = Zapatec.Utils.getCookie(this.config.pathCookie); if (this.path) { // Remove path from cookies Zapatec.Utils.writeCookie(this.config.pathCookie, ''); } // Show menu if triggerEvent is not set if (!this.config.triggerEvent) { this.showMenu(); if (!this.config.triggerEvent && this.config.scrollWithWindow && this.rootMenu) { Zapatec.ScrollWithWindow.register(this.rootMenu); } /*This solves the issue when menu is centered using table, but conflicts withdragging: if (this.config.scrollWithWindow) { objTheme.style.position = 'relative'; objTheme.style.width = objContainer.offsetWidth + 'px'; objTheme.style.height = objContainer.offsetHeight + 'px'; objContainer.style.position = 'absolute'; objContainer.style.left = '0px'; objContainer.style.top = '0px'; }*/ }};/** *<pre> * This global variable keeps a "hash table" (that is, a plain JavaScript * object) mapping ID-s to references to Zapatec.Menu objects. It's helpful if * you want to operate on a tree but you don't want to keep a reference to it. * Example: * * // the following makes a tree for the <ul id="tree-id"> element * var tree = new Zapatec.Menu("tree-id"); * // ... later * var existing_tree = Zapatec.Menu.all("tree-id"); * // and now we can use existing_tree the same as we can use tree * // the following displays true * alert(existing_tree == tree); * * So in short, this variable remembers values returned by "new * Zapatec.Menu(...)" in case you didn't. * </pre> * @private */Zapatec.Menu.all = {};/** * Function that creates a (sub)tree. This function walks the UL element, * computes and assigns CSS class names and creates HTML elements for a subtree. * Each time a LI element is encountered, createItem() is called which * effectively creates the item. Beware that createItem() might call back this * function in order to create the item's subtree. (so createTree and createItem * form an indirect recursion). * * @private * @param {object} list UL element * @param {object} objContainer Parent element that should hold the (sub)tree * @param {number} level Level of this (sub)tree in the main tree * @return ID of the (sub)tree * @type number */Zapatec.Menu.prototype.createTree = function(list, objContainer, level) { // Set id attribute of the container objContainer.id = 'zpMenu' + this.id + 'Container' + this.lastContainerNumber; this.lastContainerNumber++; var id; var intItem=1, bFirst=true; if (list) id=list.id; // list can be null if (!id) id=Zapatec.Utils.generateID("tree.sub"); var objMenu = this; function _makeIt() { objMenu.creating_now = true; var last_li = null; //previous <li> var next_li; //next <li> var i = (list ? list.firstChild : null); var items = objContainer.__zp_items = []; objMenu.trees[id] = objContainer; objContainer.__zp_level = level; objContainer.__zp_treeid = id; objContainer.__zp_keymap = {}; var strOddEven; while (i) { if (last_li) last_li.className += " zpMenu-lines-c"; if (i.nodeType != 1) i = i.nextSibling; else { next_li = Zapatec.Utils.getNextSibling(i, 'li'); if (i.tagName.toLowerCase() == 'li') { last_li = objMenu.createItem(i, objContainer, next_li, level, intItem); if (last_li) { //false when webmaster creates malformed tree // ONLY do odd/even for NON HR items // If HR items had odd/even then visual odd/even themes (see zebra) look wrong if (!/zpMenu-item-hr/i.test(last_li.className)) { // this previously created item is NOT in the HR class, create odd/even class strOddEven="zpMenu-item-" + (intItem % 2==1 ? "odd" : "even"); Zapatec.Utils.addClass(last_li, strOddEven) intItem++ } if (bFirst) { // First li for this sub-menu bFirst=false; Zapatec.Utils.addClass(last_li, "zpMenu-item-first"); } //adds it to the parent's array of items items[items.length] = last_li.__zp_item; } } i = next_li; } } // Last li for this sub-menu if (last_li) Zapatec.Utils.addClass(last_li, "zpMenu-item-last"); // If item is first and last at one time if (last_li && (last_li.className.indexOf("zpMenu-item-first") >= 0) && (last_li.className.indexOf("zpMenu-item-last") >= 0)) { Zapatec.Utils.removeClass(last_li, "zpMenu-item-last"); Zapatec.Utils.removeClass(last_li, "zpMenu-item-first"); Zapatec.Utils.addClass(last_li, "zpMenu-item-single"); } i = objContainer.firstChild; if (i && !level) { i.className = i.className.replace(/ zpMenu-lines-./g, ""); i.className += (i === last_li) ? " zpMenu-lines-s" : " zpMenu-lines-t"; } if (last_li && (level || last_li != i)) { last_li.className = last_li.className.replace(/ zpMenu-lines-./g, ""); last_li.className += " zpMenu-lines-b"; } objMenu.creating_now = false; }; if (this.config.dynamic && level > 0) this.trees[id] = _makeIt; else _makeIt(); return id;};/** * <pre> * Counter that is increased by 1 before each item added. Next menu item will * have tabIndex property value = current value of Zapatec.Menu.tabIndex + 1. * * Note: * in Opera tabIndex property value of node must be > 0, otherwise it will be * ignored; * Mozilla starts travelling from nodes with tabIndex > 0; * IE starts travelling from nodes with tabIndex == 0; * all nodes without tabIndex set explicitly have tabIndex == 0 * </pre> * @private */Zapatec.Menu.tabIndex = 1000;/** * Walks through a LI element and creates the HTML elements associated with that * tree item. When it encounters an UL element it calls createTree() in order to * create the item's subtree. This function may also call item_addIcon() in * order to add the +/- buttons or icons present in the item definition as IMG * tags, or item_addDefaultIcon() if the tree configuration specifies * "defaultIcons" and no IMG tag was present. * * @private * @param {object} li LI element * @param {object} objContainer Parent element where the HTML elements should be * created * @param {object} next_li Next LI element, if this is not the last one * @param {number} level Level of this item in the main tree * @param {number} intItem Nth item for this sub-tree * @return DIV element holding the HTML elements of the created item * @type object */Zapatec.Menu.prototype.createItem = function(li, objContainer, next_li, level, intItem) { if (!li.firstChild) { return; } var id = li.id || Zapatec.Utils.generateID("tree.item"); var item = this.items[id] = Zapatec.Utils.createElement("div", objContainer.__zp_menu); item.id = this.formElementId({ prefix: 'zpMenu', suffix: 'Item' }); var t = Zapatec.Utils.createElement("table", item); var tb = Zapatec.Utils.createElement("tbody", t); var tr = Zapatec.Utils.createElement("tr", tb); var td = Zapatec.Utils.createElement("td", tr); var has_icon = false; if (!level) { // This will allow to have correct item offsetWidth value in Opera td.style.whiteSpace = 'nowrap'; } t.className = "zpMenu-table"; t.cellSpacing = 0; t.cellPadding = 0; td.className = "zpMenu-label" //If there's a title attribute to the LI var title = li.getAttribute('title'); if (title) { //apply it to the menu item td.setAttribute('title', title); } // add the LI's classname to the item.className = "zpMenu-item" + (li.className ? ' ' + li.className : ''); Zapatec.Utils.addClass(item, "zpMenu-level-" + (level+1)); // Define the Nth level of a sub-menu, 1 based item.__zp_item = id; item.__zp_tree = this.menuId; item.__zp_parent = objContainer.__zp_treeid; item.onmouseover = new Function('Zapatec.Widget.callMethod(' + this.id + ',"mouseOver","' + item.id + '")'); item.onmouseout = new Function('Zapatec.Widget.callMethod(' + this.id + ',"mouseOut","' + item.id + '")'); item.onclick = Zapatec.Menu.onItemClick; Zapatec.Utils.addClass(item, "zpMenu-item-" + (intItem % 2==1 ? "odd" : "even")); // Parse li var fc, subtree = false, accessKey = null; var getAccessKey = function(node) { var key = null; if (node.nodeType == 1) { // ELEMENT_NODE if (key = node.getAttribute('accesskey')) { // Remove accesskey attribute because it will cause duplicate onclick event node.removeAttribute('accesskey', false); if (/^[a-z0-9]$/i.test(key)) { return key; } else { key = null; } } var childNodes = node.childNodes; for (var i = 0; i < childNodes.length; i++) { if (key = getAccessKey(childNodes[i])) { break; } } } else if (node.nodeType == 3) { // TEXT_NODE var label = node.data.replace(/(^\s+|\s+$)/g, ''); if (/_([a-z0-9])/i.test(label)) { label = label.replace(/_([a-z0-9])/i, '<span style="text-decoration:underline">$1</span>'); key = RegExp.$1; var span = Zapatec.Utils.createElement("span"); span.innerHTML = label; var objParentNode = node.parentNode; objParentNode.insertBefore(span, node); objParentNode.removeChild(node); } } return key; }; while (fc = li.firstChild) { if (fc.nodeType == 1 && (/^[ou]l$/i.test(fc.tagName.toLowerCase()))) { // Subtree if (!subtree) { this.item_addIcon(item, null); var np = Zapatec.Utils.createElement("div", objContainer); // The following to be able to position menu at the bottom right corner // of the screen without appearing of scrollbars // Also Opera zIndex requires absolute positioning np.style.position = 'absolute'; if (!this.config.triggerEvent) { np.style.left = '-9999px'; np.style.top = '-9999px'; } if (this.config.dropShadow) { var ds = np.__zp_dropshadow = Zapatec.Utils.createElement('div'); objContainer.insertBefore(ds, np); ds.style.position = 'absolute'; if (!this.config.triggerEvent) { ds.style.left = '-9999px'; ds.style.top = '-9999px'; } ds.style.backgroundColor = '#000'; if (window.opera) { ds.style.backgroundColor = '#666'; // opacity doesn't work in Opera } else { ds.style.filter = 'alpha(opacity=' + this.config.dropShadow + ')'; } ds.style.opacity = this.config.dropShadow / 100; } np.__zp_item = id; np.__zp_menu = Zapatec.Utils.createElement("div", np); np.__zp_menu.className = 'zpMenu' + (fc.className ? ' ' + fc.className : ''); np.className = 'zpMenuContainer'; np.__zp_menu.onmouseover = Zapatec.Menu.onItemMouseOver; np.__zp_menu.onmouseout = Zapatec.Menu.onItemMouseOut; if (next_li) { np.__zp_menu.className += " zpMenu-lined"; } // Will hold sub-menu icons np.__zp_icons = []; // Build submenu item.__zp_subtree = this.createTree(fc, np, level+1); // Align captions in the sub-menu if (np.__zp_icons.length) { this.alignSubMenu(np); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -