📄 dommenu.js
字号:
menuTable.cellSpacing = 0; } menuTable.style.border = 0; menuTable.style.borderCollapse = 'collapse'; var menuTableBody = menuTable.appendChild(targetDoc.createElement('tbody')); var numSiblings = in_parentElement.data.get('numChildren'); for (var index = 1; index <= numSiblings; index++) { var dataIndex = in_parentElement.data.get('level') == 1 && settings.get('verticalExpand') == 'north' && settings.get('axis') == 'horizontal' ? numSiblings + 1 - index : index; var menuTableCell = menuTableBody.appendChild(targetDoc.createElement('tr')).appendChild(targetDoc.createElement('td')); menuTableCell.style.padding = 0; menuTableCell.id = in_parentElement.id + '-' + dataIndex; // add element to list of parent children in_parentElement.data.get('childElements').set(menuTableCell.id, menuTableCell); // assign the settings to nth level element menuTableCell.data = in_parentElement.data.get(dataIndex); menuTableCell.data.merge(new Hash( 'basename', in_parentElement.data.get('basename'), 'parentElement', in_parentElement, 'numChildren', menuTableCell.data.numericLength, 'childElements', new Hash(), 'offsets', new Hash(), 'level', in_parentElement.data.get('level') + 1, 'index', index )); // assign the styles menuTableCell.style.cursor = 'default'; var element = menuTableCell.appendChild(targetDoc.createElement('div')); var outerElement = element; outerElement.className = settings.get('subMenuElementClass'); if (menuTableCell.data.get('numChildren')) { element = outerElement.appendChild(targetDoc.createElement('div')); element.style.backgroundImage = 'url(' + settings.get('expandMenuArrowUrl') + ')'; element.style.backgroundRepeat = 'no-repeat'; if (settings.get('horizontalExpand') == 'east') { element.style.backgroundPosition = 'right center'; element.style.paddingRight = '12px'; } else { element.style.backgroundPosition = 'left center'; element.style.paddingLeft = '12px'; } } // fill in the menu item contents if (domLib_isMacIE) { // we don't support images in sub-menu elements in MacIE because in order for // the menu to work consistently the data has to be added with createTextNode() element.appendChild(targetDoc.createTextNode(menuTableCell.data.get('contents'))); // MacIE has to have a newline and it has to be added with createTextNode! menuTableCell.appendChild(targetDoc.createTextNode("\n")); } else { element.innerHTML = menuTableCell.data.get('contents'); } // attach the events menuTableCell.onmouseover = domMenu_openSubMenuOnmouseoverHandler; menuTableCell.onmouseout = domMenu_closeMenuHandler; if (settings.get('openClickSubMenuDelay') >= 0 && menuTableCell.data.get('numChildren')) { menuTableCell.onmousedown = domMenu_openSubMenuOnclickHandler; menuTableCell.onmouseup = domLib_cancelBubble; if (domLib_isIE) { menuTableCell.ondblclick = domMenu_openSubMenuOnclickHandler; } } else if (menuTableCell.data.get('uri')) { menuTableCell.style.cursor = domMenu_pointerStyle; menuTableCell.onclick = domMenu_resolveLinkHandler; } else if (!menuTableCell.data.get('numChildren')) { outerElement.className += ' ' + settings.get('subMenuElementHeadingClass'); } // prevent highlighting of text if (domLib_isIE) { menuTableCell.onselectstart = makeFalse; } menuTableCell.oncontextmenu = makeFalse; } menu = targetDoc.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) * NOTE: If the new active element is not set (false), 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'].elementData) { domLib_clearTimeout(domMenu_timeouts['open'].get(i)); } // grab some info about this menu system...will this ever be null? var basename = in_oldActiveElement ? in_oldActiveElement.data.get('basename') : in_newActiveElement.data.get('basename'); var settings = domMenu_settings.get(basename); // build the old active path and unhighlight previously selected element, if appropriate var oldActivePath = new Hash(); if (in_oldActiveElement) { var tmp_newActiveLevel = in_newActiveElement ? in_newActiveElement.data.get('level') : -1; var tmp_oldActivePathElement = in_oldActiveElement; do { // NOTE: using set() causes IE to lag and leaves behind highlighted artifacts! oldActivePath.elementData[tmp_oldActivePathElement.id] = tmp_oldActivePathElement; // unhighlight if sibling of new element, even if it has open submenus if (tmp_newActiveLevel >= 0 && tmp_oldActivePathElement.data.get('level') == tmp_newActiveLevel) { domMenu_toggleHighlight(tmp_oldActivePathElement, false); } } while ((tmp_oldActivePathElement = tmp_oldActivePathElement.data.get('parentElement')) && tmp_oldActivePathElement.id != basename); // unhighlight element immediately if no submenu (or submenu is closed) if (!in_oldActiveElement.data.get('subMenu') || in_oldActiveElement.data.get('subMenu').style.visibility == 'hidden') { domMenu_toggleHighlight(in_oldActiveElement, false); } } // build the new path and...(explain me!) var newActivePath = new Hash(); var intersectPoint; if (in_newActiveElement) { var actualActiveElement = in_newActiveElement; window.status = in_newActiveElement.data.get('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) { domLib_clearTimeout(domMenu_timeouts['close'].get(in_newActiveElement.id)); 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.has(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.has(tmp_newActivePathElement.id)) { intersectPoint = tmp_newActivePathElement; } newActivePath.set(tmp_newActivePathElement.id, tmp_newActivePathElement); domLib_clearTimeout(domMenu_timeouts['close'].get(tmp_newActivePathElement.id)); // FIXME: this is ugly! if (tmp_newActivePathElement != in_oldActiveElement || actualActiveElement == in_oldActiveElement) { domMenu_toggleHighlight(tmp_newActivePathElement, true); } } while ((tmp_newActivePathElement = tmp_newActivePathElement.data.get('parentElement')) && tmp_newActivePathElement.id != basename); // if we move to the child of the old active element if (in_newActiveElement.data.get('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 && oldActivePath.length > 0) { for (var i in oldActivePath.elementData) { if (oldActivePath.get(i).data.get('parentElement') == intersectPoint) { intersectSibling = oldActivePath.get(i); break; } } } var isRootLevel = in_newActiveElement.data.get('level') == 1 ? true : false; var closeDelay = isRootLevel ? settings.get('closeMouseoutMenuDelay') : settings.get('closeMouseoutSubMenuDelay'); } else { var isRootLevel = false; var closeDelay = settings.get('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 // FIXME: clean this up else { // add lingering menus outside of old active path to active path for (var i in domMenu_timeouts['close'].elementData) { if (!oldActivePath.has(i)) { var tmp_element = document.getElementById(i); if (tmp_element.data.get('basename') == basename) { oldActivePath.set(i, tmp_element); } } } } } // schedule the old active path to be closed for (var i in oldActivePath.elementData) { if (newActivePath.has(i)) { continue; } // make sure we don't double schedule here domLib_clearTimeout(domMenu_timeouts['close'].get(i)); if (isRootLevel) { domMenu_toggleHighlight(oldActivePath.get(i), false); domMenu_toggleSubMenu(oldActivePath.get(i), 'hidden'); } else { domMenu_timeouts['close'].set(i, domLib_setTimeout(domMenu_closeMenuCallback, closeDelay, [oldActivePath.get(i), basename])); } } return in_newActiveElement;}// }}}// {{{ domMenu_deactivate()function domMenu_deactivate(in_basename, in_delay){ if (!in_delay) { in_delay = 0; } domMenu_changeActivePath(false, domMenu_activeElement.get(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_delayType){ if (domLib_isGecko) { window.getSelection().removeAllRanges(); } // setup the cross-browser event object and target var eventObj = domLib_isIE ? event : in_event; // ensure the event is from the correct frame if (domLib_isIE && in_this.data.get('level') > 1) { var targetFrame = domMenu_settings.get(in_this.data.get('basename')).get('subMenuTargetFrame'); if (targetFrame) { eventObj = targetFrame.event; } } var currentTarget = domLib_isIE ? in_this : eventObj.currentTarget; var basename = currentTarget.data.get('basename'); var settings = domMenu_settings.get(basename); // if we are moving amoungst DOM 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.get(basename)) { domMenu_changeActivePath(false, domMenu_activeElement.get(basename), currentTarget.data.get('level') == 1 ? settings.get('closeClickMenuDelay') : settings.get('closeClickSubMenuDelay')); return; } // if this element has children, popup the child menu if (currentTarget.data.get('numChildren')) { // the top level menus have no delay when moving between them // so activate submenu immediately if (currentTarget.data.get('level') == 1 && domMenu_activeElement.get(basename)) { // ** I place changeActivePath() call here so the hiding of selects does not flicker ** // THOUGHT: 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.set(basename, domMenu_changeActivePath(currentTarget, domMenu_activeElement.get(basename))); } else { // clear the active path and initialize the new one domMenu_activeElement.set(basename, domMenu_changeActivePath(currentTarget, domMenu_activeElement.get(basename))); domMenu_timeouts['open'].set(currentTarget.id, domLib_setTimeout(domMenu_openMenuCallback, settings.get(in_delayType), [currentTarget, basename])); } } else { // clear the active path and initialize the new one domMenu_activeElement.set(basename, domMenu_changeActivePath(currentTarget, domMenu_activeElement.get(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 = domLib_isIE ? event : in_event; // ensure the event is from the correct frame if (domLib_isIE && in_this.data.get('level') > 1) { var targetFrame = domMenu_settings.get(in_this.data.get('basename')).get('subMenuTargetFrame'); if (targetFrame) { eventObj = targetFrame.event; } } var currentTarget = domLib_isIE ? in_this : eventObj.currentTarget; var basename = currentTarget.data.get('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.get(basename)) { if (!relatedTarget) { domMenu_changeActivePath(false, domMenu_activeElement.get(basename)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -