dommenu.js
来自「IPcop软路由防火墙 FREE 开源源代码」· JavaScript 代码 · 共 1,168 行 · 第 1/3 页
JS
1,168 行
// build the submenu var menu = document.createElement('div'); menu.id = in_parentElement.id + '[0]'; menu.className = settings.items['subMenuBarClass']; menu.style.zIndex = settings.items['baseZIndex']; menu.style.position = 'absolute'; // position the menu in the upper left corner hidden so that we can work on it menu.style.visibility = 'hidden'; menu.style.top = 0; menu.style.left = 0; in_parentElement.data.setItem('subMenu', menu); var menuTable = menu.appendChild(document.createElement('table')); // ** opera wants to make absolute tables width 100% ** if (domMenu_isOpera) { menuTable.style.width = '1px'; menuTable.style.whiteSpace = 'nowrap'; } if (domMenu_isKonq) { menuTable.cellSpacing = 0; } menuTable.style.border = 0; menuTable.style.borderCollapse = 'collapse'; var menuTableBody = menuTable.appendChild(document.createElement('tbody')); var numSiblings = in_parentElement.data.items['numChildren']; for (var index = 1; index <= numSiblings; index++) { var dataIndex = in_parentElement.data.items['level'] == 1 && settings.items['verticalExpand'] == 'north' && settings.items['axis'] == 'horizontal' ? numSiblings + 1 - index : index; var menuTableCell = menuTableBody.appendChild(document.createElement('tr')).appendChild(document.createElement('td')); menuTableCell.style.padding = 0; menuTableCell.id = in_parentElement.id + '[' + dataIndex + ']'; // add element to list of parent children in_parentElement.data.items['childElements'].setItem(menuTableCell.id, menuTableCell); // assign the settings to nth level element menuTableCell.data = in_parentElement.data.items[dataIndex]; menuTableCell.data.merge(new domMenu_Hash( 'basename', in_parentElement.data.items['basename'], 'parentElement', in_parentElement, 'numChildren', menuTableCell.data.numericLength, 'childElements', new domMenu_Hash(), 'offsets', new domMenu_Hash(), 'level', in_parentElement.data.items['level'] + 1, 'index', index )); // assign the styles var parentStyle = in_parentElement.data.items['level'] == 1 ? in_parentElement.parentNode.style : in_parentElement.style; menuTableCell.style.cursor = 'default'; var element = menuTableCell.appendChild(document.createElement('div')); var outerElement = element; outerElement.className = settings.items['subMenuElementClass']; if (menuTableCell.data.items['numChildren']) { element = outerElement.appendChild(document.createElement('div')); // {!} depends on which way we are opening {!} element.style.backgroundImage = 'url(arrow.gif)'; element.style.backgroundRepeat = 'no-repeat'; element.style.backgroundPosition = 'right center'; // add appropriate padding to fit the arrow element.style.paddingRight = '12px'; } // fill in the menu item contents element.innerHTML = menuTableCell.data.items['contents']; // attach the events menuTableCell.onmouseover = function(in_event) { domMenu_openEvent(this, in_event, settings.items['openMouseoverSubMenuDelay']); }; menuTableCell.onmouseout = function(in_event) { domMenu_closeEvent(this, in_event); }; if (settings.items['openClickSubMenuDelay'] >= 0 && menuTableCell.data.items['numChildren']) { menuTableCell.onmousedown = function(in_event) { domMenu_openEvent(this, in_event, settings.items['openClickSubMenuDelay']); }; menuTableCell.onmouseup = function(in_event) { var eventObj = domMenu_isIE ? event : in_event; eventObj.cancelBubble = true; }; if (domMenu_isIE) { menuTableCell.ondblclick = function(in_event) { domMenu_openEvent(this, in_event, settings.items['openClickSubMenuDelay']); }; } } else if (menuTableCell.data.items['uri']) { menuTableCell.style.cursor = domMenu_pointerStyle; menuTableCell.onclick = function(in_event) { domMenu_resolveLink(this, in_event); }; } else if (!menuTableCell.data.items['numChildren']) { outerElement.className += ' ' + settings.items['subMenuElementHeadingClass']; } // prevent highlighting of text if (domMenu_isIE) { menuTableCell.onselectstart = function() { return false; }; } menuTableCell.oncontextmenu = function() { return false; }; } menu = document.body.appendChild(menu); domMenu_toggleSubMenu(in_parentElement, 'visible');}// }}}// {{{ domMenu_changeActivePath()/** * Close the old active path up to the new active element * and return the value of the new active element (or the same if unchanged) * If the new active element is not set, the top level is assumed * * @return mixed new active element or false if not set */function domMenu_changeActivePath(in_newActiveElement, in_oldActiveElement, in_closeDelay){ // protect against crap if (!in_oldActiveElement && !in_newActiveElement) { return false; } // cancel open timeouts since we know we are opening something different now for (var i in domMenu_timeouts['open'].items) { domMenu_cancelTimeout(i, 'open'); } // grab some info about this menu system var basename = in_oldActiveElement ? in_oldActiveElement.data.items['basename'] : in_newActiveElement.data.items['basename']; var settings = domMenu_settings.items[basename]; // build the old and new paths var oldActivePath = new domMenu_Hash(); if (in_oldActiveElement) { var tmp_oldActivePathElement = in_oldActiveElement; do { oldActivePath.setItem(tmp_oldActivePathElement.id, tmp_oldActivePathElement); } while ((tmp_oldActivePathElement = tmp_oldActivePathElement.data.items['parentElement']) && tmp_oldActivePathElement.id != basename); // unhighlight the old active element if it doesn't have children open if (!in_oldActiveElement.data.items['subMenu'] || in_oldActiveElement.data.items['subMenu'].style.visibility == 'hidden') { domMenu_toggleHighlight(in_oldActiveElement, false); } } var newActivePath = new domMenu_Hash(); var intersectPoint; if (in_newActiveElement) { var actualActiveElement = in_newActiveElement; window.status = in_newActiveElement.data.items['statusText'] + ' '; // in the event we have no old active element, just highlight new one and return // without setting the new active element (handled later) if (!in_oldActiveElement) { domMenu_cancelTimeout(in_newActiveElement.id, 'close'); domMenu_toggleHighlight(in_newActiveElement, true); return false; } // if the new element is in the path of the old element, then pretend event is // on the old active element else if (oldActivePath.hasItem(in_newActiveElement.id)) { in_newActiveElement = in_oldActiveElement; } var tmp_newActivePathElement = in_newActiveElement; do { // if we have met up with the old active path, then record merge point if (!intersectPoint && oldActivePath.hasItem(tmp_newActivePathElement.id)) { intersectPoint = tmp_newActivePathElement; } newActivePath.setItem(tmp_newActivePathElement.id, tmp_newActivePathElement); domMenu_cancelTimeout(tmp_newActivePathElement.id, 'close'); // {!} this is ugly {!} if (tmp_newActivePathElement != in_oldActiveElement || actualActiveElement == in_oldActiveElement) { domMenu_toggleHighlight(tmp_newActivePathElement, true); } } while ((tmp_newActivePathElement = tmp_newActivePathElement.data.items['parentElement']) && tmp_newActivePathElement.id != basename); // if we move to the child of the old active element if (in_newActiveElement.data.items['parentElement'] == in_oldActiveElement) { return in_newActiveElement; } // if the new active element is in the old active path else if (in_newActiveElement == in_oldActiveElement) { return in_newActiveElement; } // find the sibling element var intersectSibling; if (intersectPoint) { for (var i in oldActivePath.items) { if (oldActivePath.items[i].data.items['parentElement'] == intersectPoint) { intersectSibling = oldActivePath.items[i]; break; } } } var isRootLevel = in_newActiveElement.data.items['level'] == 1 ? true : false; var closeDelay = isRootLevel ? settings.items['closeMouseoutMenuDelay'] : settings.items['closeMouseoutSubMenuDelay']; } else { var isRootLevel = false; var closeDelay = settings.items['closeMouseoutMenuDelay']; window.status = window.defaultStatus; } // override the close delay with that passed in if (typeof(in_closeDelay) != 'undefined') { closeDelay = in_closeDelay; } // if there is an intersect sibling, then we need to work from there up to // preserve the active path if (intersectSibling) { // only if this is not the root level to we allow the scheduled close // events to persist...otherwise we close immediately if (!isRootLevel) { // toggle the sibling highlight (only one sibling highlighted at a time) domMenu_toggleHighlight(intersectSibling, false); } // we are moving to another top level menu // {!} clean this up {!} else { // add lingering menus outside of old active path to active path for (var i in domMenu_timeouts['close'].items) { if (!oldActivePath.hasItem(i)) { var tmp_element = document.getElementById(i); if (tmp_element.data.items['basename'] == basename) { oldActivePath.setItem(i, tmp_element); } } } } } // schedule the old active path to be closed for (var i in oldActivePath.items) { if (newActivePath.hasItem(i)) { continue; } // make sure we don't double schedule here domMenu_cancelTimeout(i, 'close'); if (isRootLevel) { domMenu_toggleHighlight(oldActivePath.items[i], false); domMenu_toggleSubMenu(oldActivePath.items[i], 'hidden'); } else { var tmp_args = new Array(); tmp_args[0] = oldActivePath.items[i]; var tmp_function = 'domMenu_toggleHighlight(argv[0], false); domMenu_toggleSubMenu(argv[0], ' + domMenu_quote('hidden') + ');'; // if this is the top level, then the menu is being deactivated if (oldActivePath.items[i].data.items['level'] == 1) { tmp_function += ' domMenu_activeElement.setItem(' + domMenu_quote(basename) + ', false);'; } domMenu_callTimeout(tmp_function, closeDelay, tmp_args, i, 'close'); } } return in_newActiveElement;}// }}}// {{{ domMenu_deactivate()function domMenu_deactivate(in_basename, in_delay){ if (!in_delay) { in_delay = 0; } domMenu_changeActivePath(false, domMenu_activeElement.items[in_basename], in_delay);}// }}}// {{{ domMenu_openEvent()/** * Handle the mouse event to open a menu * * When an event is received to open the menu, this function is * called, handles reinitialization of the menu state and sets * a timeout interval for opening the submenu (if one exists) */function domMenu_openEvent(in_this, in_event, in_openDelay){ if (domMenu_isGecko) { try { window.getSelection().removeAllRanges(); } catch (e) {} } // setup the cross-browser event object and target var eventObj = domMenu_isIE ? event : in_event; var currentTarget = domMenu_isIE ? in_this : eventObj.currentTarget; var basename = currentTarget.data.items['basename']; // if we are moving amoungst children of the same element, just ignore event if (eventObj.type != 'mousedown' && domMenu_getElement(eventObj[domMenu_eventFrom], basename) == currentTarget) { return; } // if we click on an open menu, close it if (eventObj.type == 'mousedown' && domMenu_activeElement.items[basename]) { var settings = domMenu_settings.items[basename]; domMenu_changeActivePath(false, domMenu_activeElement.items[basename], currentTarget.data.items['level'] == 1 ? settings.items['closeClickMenuDelay'] : settings.items['closeClickSubMenuDelay']); return; } // if this element has children, popup the child menu if (currentTarget.data.items['numChildren']) { // the top level menus have no delay when moving between them // so activate submenu immediately if (currentTarget.data.items['level'] == 1 && domMenu_activeElement.items[basename]) { // ** I place changeActivePath() call here so the hiding of selects does not flicker ** // {!} instead I could tell changeActivePath to clear select ownership but not // toggle visibility....hmmm....{!} domMenu_activateSubMenu(currentTarget); // clear the active path and initialize the new one domMenu_activeElement.setItem(basename, domMenu_changeActivePath(currentTarget, domMenu_activeElement.items[basename])); } else { // clear the active path and initialize the new one domMenu_activeElement.setItem(basename, domMenu_changeActivePath(currentTarget, domMenu_activeElement.items[basename])); var tmp_args = new Array(); tmp_args[0] = currentTarget; var tmp_function = 'if (!domMenu_activeElement.items[' + domMenu_quote(basename) + ']) { domMenu_activeElement.setItem(' + domMenu_quote(basename) + ', argv[0]); } domMenu_activateSubMenu(argv[0]);'; domMenu_callTimeout(tmp_function, in_openDelay, tmp_args, currentTarget.id, 'open'); } } else { // clear the active path and initialize the new one domMenu_activeElement.setItem(basename, domMenu_changeActivePath(currentTarget, domMenu_activeElement.items[basename])); }}// }}}// {{{ domMenu_closeEvent()/** * Handle the mouse event to close a menu * * When an mouseout event is received to close the menu, this function is * called, sets a timeout interval for closing the menu. */function domMenu_closeEvent(in_this, in_event){ // setup the cross-browser event object and target var eventObj = domMenu_isIE ? event : in_event; var currentTarget = domMenu_isIE ? in_this : eventObj.currentTarget; var basename = currentTarget.data.items['basename']; var relatedTarget = domMenu_getElement(eventObj[domMenu_eventTo], basename); // if the related target is not a menu element then we left the menu system // at this point (or cannot discern where we are in the menu) if (domMenu_activeElement.items[basename]) { if (!relatedTarget) { domMenu_changeActivePath(false, domMenu_activeElement.items[basename]); } } // we are highlighting the top level, but menu is not yet 'active' else { if (currentTarget != relatedTarget) { domMenu_cancelTimeout(currentTarget.id, 'open'); domMenu_toggleHighlight(currentTarget, false); } }} // }}}// {{{ domMenu_getElement()function domMenu_getElement(in_object, in_basename){ while (in_object) { try { if (in_object.id && in_object.id.search(new RegExp('^' + in_basename + '(\\[[0-9]\\])*\\[[0-9]\\]$')) == 0) { return in_object; } else { in_object = in_object.parentNode; } } catch(e) { return false; } }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?