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 + -
显示快捷键?