📄 dommenu.js
字号:
/** $Id: domMenu.js,v 1.1 2006/12/26 08:24:23 linhdh Exp $ */
// {{{ license
/*
* Copyright 2002-2005 Dan Allen, Mojavelinux.com (dan.allen@mojavelinux.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// }}}
// {{{ intro
/**
* Title: DOM Menu Library
* Version: 0.3.7
*
* Summary:
* A widget library for creating dynamic "popout" menus on webpages. The menu can
* either be horizontal or vertical, and can open in either direction. It has
* both edge detection and obstruction detection (for browsers that cannot
* hide select boxes or flash animations). The styles for the menu items are
* controlled entirely through CSS. The menus are created and destroyed using
* the DOM. Menu configuration is done using a custom Hash() class.
*
* Dependency: domLib.js version 0.72
*
* Maintainer: Dan Allen <dan@mojavelinux.com>
* Contributors:
* Jason Rust <jrust@rustyparts.com>
*
* License: Apache 2.0
* However, if you use this library, you earn the position of official bug
* reporter :) Please post questions or problem reports to the newsgroup:
*
* http://groups.google.com/group/dom-menu
*
* If you are doing this for commercial work, perhaps you could send me a few
* Starbucks Coffee gift dollars or PayPal bucks to encourage future
* developement (NOT REQUIRED). E-mail me for my snail mail address.
*
* Homepage: http://www.mojavelinux.com/projects/dommenu/
*
* Freshmeat Project: http://freshmeat.net/projects/dommenu/?topic_id=92
*
* Updated: $Date: 2006/12/26 08:24:23 $
*
* Supported Browsers:
* Mozilla (Gecko), IE 5.0+, IE on Mac, Safari, Konqueror, Opera 7+
*
* 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.
*
* Dev Notes:
* - added cellSpacing = 0 for domLib_isMacIE (two places)
* - seems that Safari and Firefox share an offset problem of menu under parent (pmp example)
* - must use createTextNode() to add the "\n" that is required for Mac to
* render the appendChild element (two places); this might be the solution for
* the sub menus as well
* - Safari seems to have a problem with offsetTop if a descendent of body has a margin; solution
* is to use padding on the body
*/
// }}}
// {{{ settings (editable)
var domMenu_data = new Hash();
var domMenu_settings = new Hash();
domMenu_settings.set('global', new 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',
'subMenuTargetFrame', false,
'targetDocumentXOrigin', 0,
'targetDocumentYOrigin', 0,
'menuBarWidth', '100%',
'subMenuMinWidth', 'inherit',
'distributeSpace', true,
'axis', 'horizontal',
'verticalExpand', 'south',
'horizontalExpand', 'east',
'expandMenuArrowUrl', 'arrow.gif',
'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,
'baseUri', ''
));
// }}}
// {{{ globals (DO NOT EDIT)
/**
* 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 = domLib_isIE ? 'toElement' : 'relatedTarget';
var domMenu_eventFrom = domLib_isIE ? 'fromElement' : 'relatedTarget';
var domMenu_activeElement = new Hash();
/**
* Array of hashes listing the timouts currently running for opening/closing menus
* @array domMenu_timeouts
*/
var domMenu_timeouts = [];
domMenu_timeouts['open'] = new Hash();
domMenu_timeouts['close'] = new Hash();
/**
* Style to use for a link pointer, which is different between Gecko and IE
* @var domMenu_pointerStyle
*/
var domMenu_pointerStyle = domLib_isIE ? 'hand' : 'pointer';
// }}}
// {{{ domMenu_activate()
function domMenu_activate(in_containerId, in_disableWarning)
{
var container;
var data;
// make sure we can use the menu system
if (!domLib_useLibrary)
{
if (!in_disableWarning)
{
alert('domMenu: Browser not supported. Menu will be disabled.');
}
return;
}
// make sure that this is a valid menu,
// and that the menu actually has data
if (!(container = document.getElementById(in_containerId)) ||
!(data = domMenu_data.get(in_containerId)) ||
data.numericLength == 0) {
if (!in_disableWarning) {
alert('domMenu: Menu failed to load.');
}
return;
}
if (domLib_isIE && window.attachEvent) {
window.attachEvent('onunload', domMenu_unloadEventCache);
}
// start with the global settings and merge in the local changes
if (!domMenu_settings.has(in_containerId)) {
domMenu_settings.set(in_containerId, new Hash());
}
var settings = domMenu_settings.get(in_containerId);
for (var i in domMenu_settings.get('global').elementData) {
if (!settings.has(i)) {
settings.set(i, domMenu_settings.get('global').get(i));
}
}
// populate the zero level element
container.data = new Hash(
'parentElement', false,
'numChildren', data.numericLength,
'childElements', new 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.get('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.get('menuBarClass');
container.data.set('subMenu', rootMenu);
var rootMenuTable = rootMenu.appendChild(document.createElement('table'));
if (domLib_isKonq || domLib_isMacIE) {
rootMenuTable.cellSpacing = 0;
}
rootMenuTable.style.border = 0;
rootMenuTable.style.borderCollapse = 'collapse';
rootMenuTable.style.width = settings.get('menuBarWidth');
var rootMenuTableBody = rootMenuTable.appendChild(document.createElement('tbody'));
var numSiblings = container.data.get('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.get('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.get('childElements').set(rootMenuTableCell.id, rootMenuTableCell);
// assign the settings to the root level element
// NOTE: this is a problem if two menus are using the same data
rootMenuTableCell.data = data.get(index);
rootMenuTableCell.data.merge(new Hash(
'basename', in_containerId,
'parentElement', container,
'numChildren', rootMenuTableCell.data.numericLength,
'childElements', new Hash(),
'offsets', new Hash(),
'level', container.data.get('level') + 1,
'index', index
));
// assign the styles
rootMenuTableCell.style.cursor = 'default';
if (settings.get('axis') == 'horizontal') {
if (settings.get('distributeSpace')) {
rootMenuTableCell.style.width = distributeRatio;
}
}
// Needed for when the text wraps
rootMenuTableCell.style.verticalAlign = 'top';
var rootElement = rootMenuTableCell.appendChild(document.createElement('div'));
rootElement.className = settings.get('menuElementClass');
// fill in the menu element contents
var spanElement = rootElement.appendChild(document.createElement('span'));
// can't use createTextNode() because there might be img tags in the contents
spanElement.innerHTML = rootMenuTableCell.data.get('contents').replace(/\/\/\//, settings.get('baseUri'));
// add hover contents if needed
if (rootMenuTableCell.data.has('contentsHover')) {
spanElement = rootElement.appendChild(document.createElement('span'));
spanElement.style.display = 'none';
spanElement.innerHTML = rootMenuTableCell.data.get('contentsHover').replace(/\/\/\//, settings.get('baseUri'));
}
// MacIE has to have a newline at the end or else it barfs
// additionally, it MUST be added using createTextNode() or IE will crash!
if (domLib_isMacIE) {
rootMenuTableCell.appendChild(document.createTextNode("\n"));
}
// attach the events
rootMenuTableCell.onmouseover = domMenu_openMenuOnmouseoverHandler;
rootMenuTableCell.onmouseout = domMenu_closeMenuHandler;
if (settings.get('openMousedownMenuDelay') >= 0 && rootMenuTableCell.data.get('numChildren')) {
rootMenuTableCell.onmousedown = domMenu_openMenuOnmousedownHandler;
// cancel mouseup so that it doesn't propogate to global mouseup event
rootMenuTableCell.onmouseup = domLib_cancelBubble;
if (domLib_isIE) {
rootMenuTableCell.ondblclick = domMenu_openMenuOnmousedownHandler;
}
}
else if (rootMenuTableCell.data.get('uri')) {
rootMenuTableCell.style.cursor = domMenu_pointerStyle;
rootMenuTableCell.onclick = domMenu_resolveLinkHandler;
}
// prevent highlighting of text
if (domLib_isIE) {
rootMenuTableCell.onselectstart = makeFalse;
}
rootMenuTableCell.oncontextmenu = makeFalse;
}
// add the menu rootMenu to the zero level element
rootMenu = container.appendChild(rootMenu);
if (domLib_detectObstructionsEnabled) {
// even though most cases the top level menu does not go away, it could
// if this menu system is used by another process
domLib_detectObstructions(rootMenu, false, false);
}
}
// }}}
// {{{ domMenu_activateSubMenu()
function domMenu_activateSubMenu(in_parentElement)
{
// NOTE: submenus not supported in MacIE because of problems using
// appendChild on document.body
if (domLib_isMacIE) {
return;
}
// see if submenu already exists
if (in_parentElement.data.has('subMenu')) {
domMenu_toggleSubMenu(in_parentElement, 'visible');
return;
}
var settings = domMenu_settings.get(in_parentElement.data.get('basename'));
var targetDoc = document;
var targetFrame = settings.get('subMenuTargetFrame');
if (targetFrame) {
targetDoc = targetFrame.document;
}
// build the submenu
var menu = targetDoc.createElement('div');
menu.id = in_parentElement.id + '-0';
menu.className = settings.get('subMenuBarClass');
menu.style.zIndex = settings.get('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.set('subMenu', menu);
var menuTable = menu.appendChild(targetDoc.createElement('table'));
// ** opera wants to make absolute tables width 100% **
if (domLib_isOpera) {
menuTable.style.width = '1px';
menuTable.style.whiteSpace = 'nowrap';
}
if (domLib_isKonq || domLib_isMacIE) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -