diff options
Diffstat (limited to 'httemplate/elements/xmenu.js')
-rw-r--r-- | httemplate/elements/xmenu.js | 668 |
1 files changed, 668 insertions, 0 deletions
diff --git a/httemplate/elements/xmenu.js b/httemplate/elements/xmenu.js new file mode 100644 index 000000000..134265f53 --- /dev/null +++ b/httemplate/elements/xmenu.js @@ -0,0 +1,668 @@ +//<script> +/* + * This script was created by Erik Arvidsson (erik@eae.net) + * for WebFX (http://webfx.eae.net) + * Copyright 2001 + * + * For usage see license at http://webfx.eae.net/license.html + * + * Created: 2001-01-12 + * Updates: 2001-11-20 Added hover mode support and removed Opera focus hacks + * 2001-12-20 Added auto positioning and some properties to support this + * 2002-08-13 toString used ' for attributes. Changed to " to allow in args + */ + +// check browsers +var ua = navigator.userAgent; +var opera = /opera [56789]|opera\/[56789]/i.test(ua); +var ie = !opera && /MSIE/.test(ua); +var ie50 = ie && /MSIE 5\.[01234]/.test(ua); +var ie6 = ie && /MSIE [6789]/.test(ua); +var ieBox = ie && (document.compatMode == null || document.compatMode != "CSS1Compat"); +var moz = !opera && /gecko/i.test(ua); +var nn6 = !opera && /netscape.*6\./i.test(ua); +var khtml = /KHTML/i.test(ua); + +// define the default values + +webfxMenuDefaultWidth = 154; + +webfxMenuDefaultBorderLeft = 1; +webfxMenuDefaultBorderRight = 1; +webfxMenuDefaultBorderTop = 1; +webfxMenuDefaultBorderBottom = 1; + +webfxMenuDefaultPaddingLeft = 1; +webfxMenuDefaultPaddingRight = 1; +webfxMenuDefaultPaddingTop = 1; +webfxMenuDefaultPaddingBottom = 1; + +webfxMenuDefaultShadowLeft = 0; +webfxMenuDefaultShadowRight = ie && !ie50 && /win32/i.test(navigator.platform) ? 4 :0; +webfxMenuDefaultShadowTop = 0; +webfxMenuDefaultShadowBottom = ie && !ie50 && /win32/i.test(navigator.platform) ? 4 : 0; + + +webfxMenuItemDefaultHeight = 18; +webfxMenuItemDefaultText = "Untitled"; +webfxMenuItemDefaultHref = "javascript:void(0)"; + +webfxMenuSeparatorDefaultHeight = 6; + +webfxMenuDefaultEmptyText = "Empty"; + +webfxMenuDefaultUseAutoPosition = nn6 ? false : true; + + + +// other global constants + +webfxMenuImagePath = ""; + +webfxMenuUseHover = opera ? true : false; +webfxMenuHideTime = 500; +webfxMenuShowTime = 200; + + + +var webFXMenuHandler = { + idCounter : 0, + idPrefix : "webfx-menu-object-", + all : {}, + getId : function () { return this.idPrefix + this.idCounter++; }, + overMenuItem : function (oItem) { + if (this.showTimeout != null) + window.clearTimeout(this.showTimeout); + if (this.hideTimeout != null) + window.clearTimeout(this.hideTimeout); + var jsItem = this.all[oItem.id]; + if (webfxMenuShowTime <= 0) + this._over(jsItem); + else if ( jsItem ) + //this.showTimeout = window.setTimeout(function () { webFXMenuHandler._over(jsItem) ; }, webfxMenuShowTime); + // I hate IE5.0 because the piece of shit crashes when using setTimeout with a function object + this.showTimeout = window.setTimeout("webFXMenuHandler._over(webFXMenuHandler.all['" + jsItem.id + "'])", webfxMenuShowTime); + }, + outMenuItem : function (oItem) { + if (this.showTimeout != null) + window.clearTimeout(this.showTimeout); + if (this.hideTimeout != null) + window.clearTimeout(this.hideTimeout); + var jsItem = this.all[oItem.id]; + if (webfxMenuHideTime <= 0) + this._out(jsItem); + else if ( jsItem ) + //this.hideTimeout = window.setTimeout(function () { webFXMenuHandler._out(jsItem) ; }, webfxMenuHideTime); + this.hideTimeout = window.setTimeout("webFXMenuHandler._out(webFXMenuHandler.all['" + jsItem.id + "'])", webfxMenuHideTime); + }, + blurMenu : function (oMenuItem) { + window.setTimeout("webFXMenuHandler.all[\"" + oMenuItem.id + "\"].subMenu.hide();", webfxMenuHideTime); + }, + _over : function (jsItem) { + if (jsItem.subMenu) { + jsItem.parentMenu.hideAllSubs(); + jsItem.subMenu.show(); + } + else + jsItem.parentMenu.hideAllSubs(); + }, + _out : function (jsItem) { + // find top most menu + var root = jsItem; + var m; + if (root instanceof WebFXMenuButton) + m = root.subMenu; + else { + m = jsItem.parentMenu; + while (m.parentMenu != null && !(m.parentMenu instanceof WebFXMenuBar)) + m = m.parentMenu; + } + if (m != null) + m.hide(); + }, + hideMenu : function (menu) { + if (this.showTimeout != null) + window.clearTimeout(this.showTimeout); + if (this.hideTimeout != null) + window.clearTimeout(this.hideTimeout); + + this.hideTimeout = window.setTimeout("webFXMenuHandler.all['" + menu.id + "'].hide()", webfxMenuHideTime); + }, + showMenu : function (menu, src, dir) { + if (this.showTimeout != null) + window.clearTimeout(this.showTimeout); + if (this.hideTimeout != null) + window.clearTimeout(this.hideTimeout); + + if (arguments.length < 3) + dir = "vertical"; + + menu.show(src, dir); + } +}; + +function WebFXMenu() { + this._menuItems = []; + this._subMenus = []; + this.id = webFXMenuHandler.getId(); + this.top = 0; + this.left = 0; + this.shown = false; + this.parentMenu = null; + webFXMenuHandler.all[this.id] = this; +} + +WebFXMenu.prototype.width = webfxMenuDefaultWidth; +WebFXMenu.prototype.emptyText = webfxMenuDefaultEmptyText; +WebFXMenu.prototype.useAutoPosition = webfxMenuDefaultUseAutoPosition; + +WebFXMenu.prototype.borderLeft = webfxMenuDefaultBorderLeft; +WebFXMenu.prototype.borderRight = webfxMenuDefaultBorderRight; +WebFXMenu.prototype.borderTop = webfxMenuDefaultBorderTop; +WebFXMenu.prototype.borderBottom = webfxMenuDefaultBorderBottom; + +WebFXMenu.prototype.paddingLeft = webfxMenuDefaultPaddingLeft; +WebFXMenu.prototype.paddingRight = webfxMenuDefaultPaddingRight; +WebFXMenu.prototype.paddingTop = webfxMenuDefaultPaddingTop; +WebFXMenu.prototype.paddingBottom = webfxMenuDefaultPaddingBottom; + +WebFXMenu.prototype.shadowLeft = webfxMenuDefaultShadowLeft; +WebFXMenu.prototype.shadowRight = webfxMenuDefaultShadowRight; +WebFXMenu.prototype.shadowTop = webfxMenuDefaultShadowTop; +WebFXMenu.prototype.shadowBottom = webfxMenuDefaultShadowBottom; + + + +WebFXMenu.prototype.add = function (menuItem) { + this._menuItems[this._menuItems.length] = menuItem; + if (menuItem.subMenu) { + this._subMenus[this._subMenus.length] = menuItem.subMenu; + menuItem.subMenu.parentMenu = this; + } + + menuItem.parentMenu = this; +}; + +WebFXMenu.prototype.show = function (relObj, sDir) { + if (this.useAutoPosition) + this.position(relObj, sDir); + + var divElement = document.getElementById(this.id); + if ( divElement ) { + + divElement.style.left = opera ? this.left : this.left + "px"; + divElement.style.top = opera ? this.top : this.top + "px"; + divElement.style.visibility = "visible"; + + if ( ie ) { + var shimElement = document.getElementById(this.id + "Shim"); + if ( shimElement ) { + shimElement.style.width = divElement.offsetWidth; + shimElement.style.height = divElement.offsetHeight; + shimElement.style.top = divElement.style.top; + shimElement.style.left = divElement.style.left; + /*shimElement.style.zIndex = divElement.style.zIndex - 1; */ + shimElement.style.display = "block"; + shimElement.style.filter='progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)'; + } + } + + } + + this.shown = true; + + if (this.parentMenu) + this.parentMenu.show(); +}; + +WebFXMenu.prototype.hide = function () { + this.hideAllSubs(); + var divElement = document.getElementById(this.id); + if ( divElement ) { + divElement.style.visibility = "hidden"; + if ( ie ) { + var shimElement = document.getElementById(this.id + "Shim"); + if ( shimElement ) { + shimElement.style.display = "none"; + } + } + } + + this.shown = false; +}; + +WebFXMenu.prototype.hideAllSubs = function () { + for (var i = 0; i < this._subMenus.length; i++) { + if (this._subMenus[i].shown) + this._subMenus[i].hide(); + } +}; + +WebFXMenu.prototype.toString = function () { + var top = this.top + this.borderTop + this.paddingTop; + var str = "<div id='" + this.id + "' class='webfx-menu' style='" + + "width:" + (!ieBox ? + this.width - this.borderLeft - this.paddingLeft - this.borderRight - this.paddingRight : + this.width) + "px;" + + (this.useAutoPosition ? + "left:" + this.left + "px;" + "top:" + this.top + "px;" : + "") + + (ie50 ? "filter: none;" : "") + + "'>"; + + if (this._menuItems.length == 0) { + str += "<span class='webfx-menu-empty'>" + this.emptyText + "</span>"; + } + else { + str += '<span class="webfx-menu-title" onmouseover="webFXMenuHandler.overMenuItem(this)"' + + (webfxMenuUseHover ? " onmouseout='webFXMenuHandler.outMenuItem(this)'" : "") + + '>' + this.emptyText + '</span>'; + // str += '<div id="' + this.id + '-title">' + this.emptyText + '</div>'; + // loop through all menuItems + for (var i = 0; i < this._menuItems.length; i++) { + var mi = this._menuItems[i]; + str += mi; + if (!this.useAutoPosition) { + if (mi.subMenu && !mi.subMenu.useAutoPosition) + mi.subMenu.top = top - mi.subMenu.borderTop - mi.subMenu.paddingTop; + top += mi.height; + } + } + + } + + str += "</div>"; + + if ( ie ) { + str += "<iframe id='" + this.id + "Shim' src='javascript:false;' scrolling='no' frameBorder='0' style='position:absolute; top:0px; left: 0px; display:none;'></iframe>"; + } + + for (var i = 0; i < this._subMenus.length; i++) { + this._subMenus[i].left = this.left + this.width - this._subMenus[i].borderLeft; + str += this._subMenus[i]; + } + + return str; +}; +// WebFXMenu.prototype.position defined later + +function WebFXMenuItem(sText, sHref, sToolTip, oSubMenu) { + this.text = sText || webfxMenuItemDefaultText; + this.href = (sHref == null || sHref == "") ? webfxMenuItemDefaultHref : sHref; + this.subMenu = oSubMenu; + if (oSubMenu) + oSubMenu.parentMenuItem = this; + this.toolTip = sToolTip; + this.id = webFXMenuHandler.getId(); + webFXMenuHandler.all[this.id] = this; +}; +WebFXMenuItem.prototype.height = webfxMenuItemDefaultHeight; +WebFXMenuItem.prototype.toString = function () { + return "<a" + + " id='" + this.id + "'" + + " href=\"" + this.href + "\"" + + (this.toolTip ? " title=\"" + this.toolTip + "\"" : "") + + " onmouseover='webFXMenuHandler.overMenuItem(this)'" + + (webfxMenuUseHover ? " onmouseout='webFXMenuHandler.outMenuItem(this)'" : "") + + (this.subMenu ? " unselectable='on' tabindex='-1'" : "") + + ">" + + (this.subMenu ? "<img class='arrow' src=\"" + webfxMenuImagePath + "arrow.right.black.png\">" : "") + + this.text + + "</a>"; +}; + + +function WebFXMenuSeparator() { + this.id = webFXMenuHandler.getId(); + webFXMenuHandler.all[this.id] = this; +}; +WebFXMenuSeparator.prototype.height = webfxMenuSeparatorDefaultHeight; +WebFXMenuSeparator.prototype.toString = function () { + return "<div" + + " id='" + this.id + "'" + + (webfxMenuUseHover ? + " onmouseover='webFXMenuHandler.overMenuItem(this)'" + + " onmouseout='webFXMenuHandler.outMenuItem(this)'" + : + "") + + "></div>" +}; + +function WebFXMenuBar() { + this._parentConstructor = WebFXMenu; + this._parentConstructor(); +} +WebFXMenuBar.prototype = new WebFXMenu; +WebFXMenuBar.prototype.toString = function () { + var str = "<div id='" + this.id + "' class='webfx-menu-bar'>"; + + // loop through all menuButtons + for (var i = 0; i < this._menuItems.length; i++) + str += this._menuItems[i]; + + str += "</div>"; + + for (var i = 0; i < this._subMenus.length; i++) + str += this._subMenus[i]; + + return str; +}; + +function WebFXMenuButton(sText, sHref, sToolTip, oSubMenu) { + this._parentConstructor = WebFXMenuItem; + this._parentConstructor(sText, sHref, sToolTip, oSubMenu); +} +WebFXMenuButton.prototype = new WebFXMenuItem; +WebFXMenuButton.prototype.toString = function () { + return "<a" + + " id='" + this.id + "'" + + " href='" + this.href + "'" + + (this.toolTip ? " title='" + this.toolTip + "'" : "") + + (webfxMenuUseHover ? + (" onmouseover='webFXMenuHandler.overMenuItem(this)'" + + " onmouseout='webFXMenuHandler.outMenuItem(this)'") : + ( + " onfocus='webFXMenuHandler.overMenuItem(this)'" + + (this.subMenu ? + " onblur='webFXMenuHandler.blurMenu(this)'" : + "" + ) + )) + + ">" + + (this.subMenu ? "<img class='arrow' src='" + webfxMenuImagePath + "arrow.right.png'>" : "") + + this.text + + "</a>"; +}; + + + + + +/* Position functions */ + + +function getInnerLeft(el) { + + if (el == null) return 0; + + if (ieBox && el == document.body || !ieBox && el == document.documentElement) return 0; + + return parseInt( getLeft(el) + parseInt(getBorderLeft(el)) ); + +} + + + +function getLeft(el, debug) { + + if (el == null) return 0; + + //if ( debug ) + // alert ( el.offsetLeft + ' - ' + getInnerLeft(el.offsetParent) ); + + return parseInt( el.offsetLeft + parseInt(getInnerLeft(el.offsetParent)) ); + +} + + + +function getInnerTop(el) { + + if (el == null) return 0; + + if (ieBox && el == document.body || !ieBox && el == document.documentElement) return 0; + + return parseInt( getTop(el) + parseInt(getBorderTop(el)) ); + +} + + + +function getTop(el) { + + if (el == null) return 0; + + return parseInt( el.offsetTop + parseInt(getInnerTop(el.offsetParent)) ); + +} + + + +function getBorderLeft(el) { + + return ie ? + + el.clientLeft : + + ( khtml + ? parseInt(document.defaultView.getComputedStyle(el, null).getPropertyValue("border-left-width")) + : parseInt(window.getComputedStyle(el, null).getPropertyValue("border-left-width")) + ); + +} + + + +function getBorderTop(el) { + + return ie ? + + el.clientTop : + + ( khtml + ? parseInt(document.defaultView.getComputedStyle(el, null).getPropertyValue("border-left-width")) + : parseInt(window.getComputedStyle(el, null).getPropertyValue("border-top-width")) + ); + +} + + + +function opera_getLeft(el) { + + if (el == null) return 0; + + return el.offsetLeft + opera_getLeft(el.offsetParent); + +} + + + +function opera_getTop(el) { + + if (el == null) return 0; + + return el.offsetTop + opera_getTop(el.offsetParent); + +} + + + +function getOuterRect(el, debug) { + + return { + + left: (opera ? opera_getLeft(el) : getLeft(el, debug)), + + top: (opera ? opera_getTop(el) : getTop(el)), + + width: el.offsetWidth, + + height: el.offsetHeight + + }; + +} + + + +// mozilla bug! scrollbars not included in innerWidth/height + +function getDocumentRect(el) { + + return { + + left: 0, + + top: 0, + + width: (ie ? + + (ieBox ? document.body.clientWidth : document.documentElement.clientWidth) : + + window.innerWidth + + ), + + height: (ie ? + + (ieBox ? document.body.clientHeight : document.documentElement.clientHeight) : + + window.innerHeight + + ) + + }; + +} + + + +function getScrollPos(el) { + + return { + + left: (ie ? + + (ieBox ? document.body.scrollLeft : document.documentElement.scrollLeft) : + + window.pageXOffset + + ), + + top: (ie ? + + (ieBox ? document.body.scrollTop : document.documentElement.scrollTop) : + + window.pageYOffset + + ) + + }; + +} + + +/* end position functions */ + +WebFXMenu.prototype.position = function (relEl, sDir) { + var dir = sDir; + // find parent item rectangle, piRect + var piRect; + if (!relEl) { + var pi = this.parentMenuItem; + if (!this.parentMenuItem) + return; + + relEl = document.getElementById(pi.id); + if (dir == null) + dir = pi instanceof WebFXMenuButton ? "vertical" : "horizontal"; + //alert('created RelEl from parent: ' + pi.id); + piRect = getOuterRect(relEl, 1); + } + else if (relEl.left != null && relEl.top != null && relEl.width != null && relEl.height != null) { // got a rect + //alert('passed a Rect as RelEl: ' + typeof(relEl)); + + piRect = relEl; + } + else { + //alert('passed an element as RelEl: ' + typeof(relEl)); + piRect = getOuterRect(relEl); + } + + var menuEl = document.getElementById(this.id); + var menuRect = getOuterRect(menuEl); + var docRect = getDocumentRect(); + var scrollPos = getScrollPos(); + var pMenu = this.parentMenu; + + if (dir == "vertical") { + if (piRect.left + menuRect.width - scrollPos.left <= docRect.width) { + //alert('piRect.left: ' + piRect.left); + this.left = piRect.left; + if ( ! ie ) + this.left = this.left + 138; + } else if (docRect.width >= menuRect.width) { + //konq (not safari though) winds up here by accident and positions the menus all weird + //alert('docRect.width + scrollPos.left - menuRect.width'); + + this.left = docRect.width + scrollPos.left - menuRect.width; + } else { + //alert('scrollPos.left: ' + scrollPos.left); + this.left = scrollPos.left; + } + + if (piRect.top + piRect.height + menuRect.height <= docRect.height + scrollPos.top) + + this.top = piRect.top + piRect.height; + + else if (piRect.top - menuRect.height >= scrollPos.top) + + this.top = piRect.top - menuRect.height; + + else if (docRect.height >= menuRect.height) + + this.top = docRect.height + scrollPos.top - menuRect.height; + + else + + this.top = scrollPos.top; + } + else { + if (piRect.top + menuRect.height - this.borderTop - this.paddingTop <= docRect.height + scrollPos.top) + + this.top = piRect.top - this.borderTop - this.paddingTop; + + else if (piRect.top + piRect.height - menuRect.height + this.borderTop + this.paddingTop >= 0) + + this.top = piRect.top + piRect.height - menuRect.height + this.borderBottom + this.paddingBottom + this.shadowBottom; + + else if (docRect.height >= menuRect.height) + + this.top = docRect.height + scrollPos.top - menuRect.height; + + else + + this.top = scrollPos.top; + + + + var pMenuPaddingLeft = pMenu ? pMenu.paddingLeft : 0; + + var pMenuBorderLeft = pMenu ? pMenu.borderLeft : 0; + + var pMenuPaddingRight = pMenu ? pMenu.paddingRight : 0; + + var pMenuBorderRight = pMenu ? pMenu.borderRight : 0; + + + + if (piRect.left + piRect.width + menuRect.width + pMenuPaddingRight + + + pMenuBorderRight - this.borderLeft + this.shadowRight <= docRect.width + scrollPos.left) + + this.left = piRect.left + piRect.width + pMenuPaddingRight + pMenuBorderRight - this.borderLeft; + + else if (piRect.left - menuRect.width - pMenuPaddingLeft - pMenuBorderLeft + this.borderRight + this.shadowRight >= 0) + + this.left = piRect.left - menuRect.width - pMenuPaddingLeft - pMenuBorderLeft + this.borderRight + this.shadowRight; + + else if (docRect.width >= menuRect.width) + + this.left = docRect.width + scrollPos.left - menuRect.width; + + else + + this.left = scrollPos.left; + } +}; |