dommenu.js

来自「IPcop软路由防火墙 FREE 开源源代码」· JavaScript 代码 · 共 1,168 行 · 第 1/3 页

JS
1,168
字号
// {{{ docs <-- this is a VIM (text editor) text fold/** * DOM Menu 0.3.2 * * Summary: Allows developers to add dynamic drop down menus on webpages.  The *          menu can either be horizontal or vertical, and can open in either *          direction.  It has both edge detection and <select> tag detection *          (for browsers that cannot hide these form elements).  The styles *          for the menu items are controlled almost entirely through CSS and *          the menus are created and destroyed using the DOM.  Menu configuration *          is done using a custom Hash() class and is very portable from a PHP *          type array structure. * * Maintainer: Dan Allen <dan@mojavelinux.com> * * License: LGPL - however, if you use this library, please post to my forum where you *          use it so that I get a chance to see my baby in action.  If you are doing *          this for commercial work perhaps you could send me a few Starbucks Coffee *          gift dollars to encourage future developement (NOT REQUIRED).  E-mail me *          for and address. * * Homepage: http://www.mojavelinux.com/forum/viewtopic.php * * Freshmeat Project: http://freshmeat.net/projects/dommenu/?topic_id=92 * * Updated: 2003/01/04 * * Supported Browsers: Mozilla (Gecko), IE 5+, Konqueror, (not finished Opera 7), Netscape 4 * * Usage:  * * Menu Options: Each option is followed by the value for that option. The options avaiable are: *            'contents' *            'rolloverContents', *            'uri' (may be javascript) *            'statusText' *            'target' *            [0-9] an index to create a submenu item * * API: * * menuElementObject { *     ** properties ** *     data *       contents *       uri *       target *       statusText *       parentElement *       subMenu *       childElements *       level *       index (index within this level) *     id *     className *     style *     cellSpacing (Konq only) *      *     ** events ** *     mouseover/click -> domMenu_openEvent *     mouseout        -> domMenu_closeEvent *     click           -> domMenu_resolveLink * } * * If there is a non-negative click open delay, then any uri of the element will be ignored * * The alternate contents for a hover element are treated by creating to <span> wrapper elements * and then alternating the display of them.  This avoids the need for innerHTML, which can * do nasty things to the browsers.  If <span> turns out to be a bad choice for tags, then a * non-HTML element can be used instead. ***/// }}}// {{{ settings (editable)var domMenu_data = new domMenu_Hash();var domMenu_settings = new domMenu_Hash();domMenu_settings.setItem('global', new domMenu_Hash(    'menuBarClass', 'domMenu_menuBar',    'menuElementClass', 'domMenu_menuElement',    'menuElementHoverClass', 'domMenu_menuElementHover',    'menuElementActiveClass', 'domMenu_menuElementHover',    'subMenuBarClass', 'domMenu_subMenuBar',    'subMenuElementClass', 'domMenu_subMenuElement',    'subMenuElementHoverClass', 'domMenu_subMenuElementHover',    'subMenuElementActiveClass', 'domMenu_subMenuElementHover',    'subMenuElementHeadingClass', 'domMenu_subMenuElementHeading',    'menuBarWidth', '100%',    'subMenuMinWidth', 'inherit',    'distributeSpace', true,    'axis', 'horizontal',    'verticalExpand', 'south',    'horizontalExpand', 'east',    'subMenuWidthCorrection', 0,    'verticalSubMenuOffsetY', 0,    'verticalSubMenuOffsetX', 0,    'horizontalSubMenuOffsetX', 0,    'horizontalSubMenuOffsetY', 0,    'screenPadding', 0,    'openMouseoverMenuDelay', 300,    'openMousedownMenuDelay', -1,    'closeMouseoutMenuDelay', 800,    'closeClickMenuDelay', -1,    'openMouseoverSubMenuDelay', 300,    'openClickSubMenuDelay', -1,    'closeMouseoutSubMenuDelay', 300,    'closeClickSubMenuDelay', -1,    'baseZIndex', 100));// }}}// {{{ global variables/** * Browser variables * @var domMenu_is{Browser} */var domMenu_userAgent = navigator.userAgent.toLowerCase();var domMenu_isOpera = domMenu_userAgent.indexOf('opera 7') != -1 ? 1 : 0;var domMenu_isKonq = domMenu_userAgent.indexOf('konq') != -1 ? 1 : 0;var domMenu_isIE = !domMenu_isKonq && !domMenu_isOpera && document.all ? 1 : 0;var domMenu_isIE50 = domMenu_isIE && domMenu_userAgent.indexOf('msie 5.0') != -1;var domMenu_isIE55 = domMenu_isIE && domMenu_userAgent.indexOf('msie 5.5') != -1;var domMenu_isIE5 = domMenu_isIE50 || domMenu_isIE55;var domMenu_isGecko = !domMenu_isKonq && domMenu_userAgent.indexOf('gecko') != -1 ? 1 : 0;/** * Passport to use the menu system, checked before performing menu manipulation * @var domMenu_useLibrary */var domMenu_useLibrary = domMenu_isIE || domMenu_isGecko || domMenu_isKonq || domMenu_isOpera ? 1 : 0;/** * The data for the menu is stored here, loaded from an external file * @hash domMenu_data */var domMenu_data;var domMenu_selectElements;var domMenu_scrollbarWidth = 14;var domMenu_eventTo = domMenu_isIE ? 'toElement' : 'relatedTarget';var domMenu_eventFrom = domMenu_isIE ? 'fromElement' : 'relatedTarget';var domMenu_activeElement = new domMenu_Hash();/** * Array of hashes listing the timouts currently running for opening/closing menus * @array domMenu_timeouts */var domMenu_timeouts = new Array();domMenu_timeouts['open'] = new domMenu_Hash();domMenu_timeouts['close'] = new domMenu_Hash();var domMenu_timeoutStates = new Array();domMenu_timeoutStates['open'] = new domMenu_Hash();domMenu_timeoutStates['close'] = new domMenu_Hash();/** * Style to use for a link pointer, which is different between Gecko and IE * @var domMenu_pointerStyle */var domMenu_pointerStyle = domMenu_isIE ? 'hand' : 'pointer';// }}}// {{{ domMenu_Hash()function domMenu_Hash() {    var argIndex = 0;    this.length = 0;    this.numericLength = 0;     this.items = new Array();    while (arguments.length > argIndex) {        this.items[arguments[argIndex]] = arguments[argIndex + 1];        if (arguments[argIndex] == parseInt(arguments[argIndex])) {            this.numericLength++;        }        this.length++;        argIndex += 2;    }    this.removeItem = function(in_key)    {        var tmp_value;        if (typeof(this.items[in_key]) != 'undefined') {            this.length--;            if (in_key == parseInt(in_key)) {                this.numericLength--;            }            tmp_value = this.items[in_key];            delete this.items[in_key];        }                return tmp_value;    }    this.getItem = function(in_key)    {        return this.items[in_key];    }    this.setItem = function(in_key, in_value)    {        if (typeof(this.items[in_key]) == 'undefined') {            this.length++;            if (in_key == parseInt(in_key)) {                this.numericLength++;            }        }                this.items[in_key] = in_value;    }    this.hasItem = function(in_key)    {        return typeof(this.items[in_key]) != 'undefined';    }        this.merge = function(in_hash)    {        for (var tmp_key in in_hash.items) {            if (typeof(this.items[tmp_key]) == 'undefined') {                this.length++;                if (tmp_key == parseInt(tmp_key)) {                    this.numericLength++;                }            }            this.items[tmp_key] = in_hash.items[tmp_key];        }    }    this.compare = function(in_hash)    {        if (this.length != in_hash.length) {            return false;        }        for (var tmp_key in this.items) {            if (this.items[tmp_key] != in_hash.items[tmp_key]) {                return false;            }        }                return true;    }}// }}}// {{{ domMenu_activate()function domMenu_activate(in_containerId){    var container;    var data;    // make sure we can use the menu system and this is a valid menu    if (!domMenu_useLibrary || !(container = document.getElementById(in_containerId)) || !(data = domMenu_data.items[in_containerId])) {        return;    }    // start with the global settings and merge in the local changes    if (!domMenu_settings.hasItem(in_containerId)) {        domMenu_settings.setItem(in_containerId, new domMenu_Hash());    }    var settings = domMenu_settings.items[in_containerId];    for (var i in domMenu_settings.items['global'].items) {        if (!settings.hasItem(i)) {            settings.setItem(i, domMenu_settings.items['global'].items[i]);        }    }    // populate the zero level element    container.data = new domMenu_Hash(        'parentElement', false,        'numChildren', data.numericLength,        'childElements', new domMenu_Hash(),        'level', 0,        'index', 1    );        // if we choose to distribute either height or width, determine ratio of each cell    var distributeRatio = Math.round(100/container.data.items['numChildren']) + '%';        // the first menu is the rootMenu, which is a child of the zero level element    var rootMenu = document.createElement('div');    rootMenu.id = in_containerId + '[0]';    rootMenu.className = settings.items['menuBarClass'];    container.data.setItem('subMenu', rootMenu);    var rootMenuTable = rootMenu.appendChild(document.createElement('table'));    if (domMenu_isKonq) {        rootMenuTable.cellSpacing = 0;    }    rootMenuTable.style.border = 0;    rootMenuTable.style.borderCollapse = 'collapse';    rootMenuTable.style.width = settings.items['menuBarWidth'];    var rootMenuTableBody = rootMenuTable.appendChild(document.createElement('tbody'));    var numSiblings = container.data.items['numChildren'];    for (var index = 1; index <= numSiblings; index++) {        // create a row the first time if horizontal or each time if vertical        if (index == 1 || settings.items['axis'] == 'vertical') {            var rootMenuTableRow = rootMenuTableBody.appendChild(document.createElement('tr'));        }        // create an instance of the root level menu element        var rootMenuTableCell = rootMenuTableRow.appendChild(document.createElement('td'));        rootMenuTableCell.style.padding = 0;        rootMenuTableCell.id = in_containerId + '[' + index + ']';        // add element to list of parent children        container.data.items['childElements'].setItem(rootMenuTableCell.id, rootMenuTableCell);        // assign the settings to the root level element        // {!} this is a problem if two menus are using the same data {!}        rootMenuTableCell.data = data.items[index];        rootMenuTableCell.data.merge(new domMenu_Hash(            'basename', in_containerId,            'parentElement', container,            'numChildren', rootMenuTableCell.data.numericLength,            'childElements', new domMenu_Hash(),            'offsets', new domMenu_Hash(),            'level', container.data.items['level'] + 1,            'index', index        ));        // assign the styles        rootMenuTableCell.style.cursor = 'default';        if (settings.items['axis'] == 'horizontal') {            if (settings.items['distributeSpace']) {                rootMenuTableCell.style.width = distributeRatio;            }        }        var rootElement = rootMenuTableCell.appendChild(document.createElement('div'));        rootElement.className = settings.items['menuElementClass'];        // fill in the menu element contents        rootElement.innerHTML = '<span>' + rootMenuTableCell.data.items['contents'] + '</span>' + (rootMenuTableCell.data.hasItem('contentsHover') ? '<span style="display: none;">' + rootMenuTableCell.data.items['contentsHover'] + '</span>' : '');        // attach the events        rootMenuTableCell.onmouseover = function(in_event) { domMenu_openEvent(this, in_event, settings.items['openMouseoverMenuDelay']); };        rootMenuTableCell.onmouseout = function(in_event) { domMenu_closeEvent(this, in_event); };        if (settings.items['openMousedownMenuDelay'] >= 0 && rootMenuTableCell.data.items['numChildren']) {            rootMenuTableCell.onmousedown = function(in_event) { domMenu_openEvent(this, in_event, settings.items['openMousedownMenuDelay']); };            // cancel mouseup so that it doesn't propogate to global mouseup event            rootMenuTableCell.onmouseup = function(in_event) { var eventObj = domMenu_isIE ? event : in_event; eventObj.cancelBubble = true; };            if (domMenu_isIE) {                rootMenuTableCell.ondblclick = function(in_event) { domMenu_openEvent(this, in_event, settings.items['openMousedownMenuDelay']); };            }        }        else if (rootMenuTableCell.data.items['uri']) {            rootMenuTableCell.style.cursor = domMenu_pointerStyle;            rootMenuTableCell.onclick = function(in_event) { domMenu_resolveLink(this, in_event); };        }        // prevent highlighting of text        if (domMenu_isIE) {            rootMenuTableCell.onselectstart = function() { return false; };        }        rootMenuTableCell.oncontextmenu = function() { return false; };    }        // add the menu rootMenu to the zero level element    rootMenu = container.appendChild(rootMenu);    // even though most cases the top level menu does not go away, it could    // if this menu system is used by another process    domMenu_detectCollisions(rootMenu);}// }}}// {{{ domMenu_activateSubMenu()function domMenu_activateSubMenu(in_parentElement){    // see if submenu already exists    if (in_parentElement.data.hasItem('subMenu')) {        domMenu_toggleSubMenu(in_parentElement, 'visible');        return;    }    var settings = domMenu_settings.items[in_parentElement.data.items['basename']];

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?