MyBB Community Forums

Full Version: DHTML Menus
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
YOU NEED TO KNOW INTERMEDIATE HTML TO BE ABLE TO PERFORM THIS MOD!
example: http://www.otaku-networks.net (THEME: TECHBLUE, in Menubar[Search], and in the board headers[viewforum.php])

Code from OPEN SOURCE PROJECT: K4BB (Another BB System - I prefer MyBB)
See license below.
/**
* k4 Bulletin Board, (Mixed JS Files)
* Javascript codes for the Menu
*
* Copyright (c) 2005, Peter Goodman
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @author Peter Goodman
* @version $Id: javascript.js 144 2005-07-05 02:29:07Z Peter Goodman $
* @package k42
*/

function k4lib() {
	
	/**
	 * Get browser information
	 */
	this.userAgent = navigator.userAgent.toLowerCase();
	this.is_opera  = (this.userAgent.indexOf('opera') != -1);
	this.is_saf    = ((this.userAgent.indexOf('applewebkit') != -1) || (navigator.vendor == 'Apple Computer, Inc.'));
	this.is_webtv  = (this.userAgent.indexOf('webtv') != -1);
	this.is_ie     = ((this.userAgent.indexOf('msie') != -1) && (!this.is_opera) && (!this.is_saf) && (!this.is_webtv));
	this.is_ie4    = ((this.is_ie) && (this.userAgent.indexOf('msie 4.') != -1));
	this.is_ie5    = ((this.is_ie) && (this.userAgent.indexOf('msie 5') != -1));
	this.is_moz    = ((navigator.product == 'Gecko') && (!this.is_saf));
	this.is_kon    = (this.userAgent.indexOf('konqueror') != -1);
	this.is_ns     = ((this.userAgent.indexOf('compatible') == -1) && (this.userAgent.indexOf('mozilla') != -1) && (!this.is_opera) && (!this.is_webtv) && (!this.is_saf));
	this.is_ns6    = ((this.is_ns) && (parseInt(navigator.appVersion) == 6));
	this.is_mac    = (this.userAgent.indexOf('mac') != -1);
}	

/**
 * Get an object by its ID 
 */
k4lib.prototype.getElementById			= function(id) {
	
	if (document.getElementById) {
		return document.getElementById(id);
	} else if (document.all) {
		return document.all[id];
	} else if (document.layers) {
		return document.layers[id];
	} else {
		return false;
	}
}

/**
 * Get an object by its tag name 
 */
k4lib.prototype.getElementsByTagName	= function(parentobj, tagname) {
	
	var elements			= false;

	if (typeof parentobj.getElementsByTagName != 'undefined') {
		elements			= parentobj.getElementsByTagName(tagname);
	} else if (parentobj.all && parentobj.all.tags) {
		elements			= parentobj.all.tags(tagname);
	}

	return elements;
}

/**
 * Array functions
 */

k4lib.prototype.array_key				= function(thearray, needle) {
	
	var key				= 0;
	
	for (var i = 0; i < this.sizeof(thearray); i++) {
		
		if (thearray[i] == needle) {
			key			= i;
		}
	}

	return key;
}

k4lib.prototype.sizeof					= function(thearray) {
	
	array_length		= 0;

	if(thearray != null && thearray != 'undefined') {

		for (i = 0; i < thearray.length; i++) {
			if ((thearray[i] == "undefined") || (thearray[i] == "") || (thearray[i] == null)) {
				return i;
			}
		}
	
		array_length	= thearray.length;
	} else {
		array_length	= 0;
	}

	return array_length;
}

/**
 * Position functions
 */

/* Get the top position of an object */
k4lib.prototype.top				= function(obj) {
	
	var postop	= 0;
	
	while (obj && obj != null){
		postop	+= obj.offsetTop; //  - obj.scrollTop
		obj		= obj.offsetParent;
	}

	return postop;
}

/* get the left position of an object */
k4lib.prototype.left				= function(obj) {
	
	var posleft			= 0;

	if(obj) {
	
		posleft			= obj.offsetLeft;
		while((obj = obj.offsetParent) != null) {
			
			posleft		+= obj.offsetLeft;
		}
	}

	return posleft;
}

/* get the bottom position of an object */
k4lib.prototype.bottom				= function(obj) {
	return (this.top(obj) + this.height(obj));
}

/* get the right position of an object */
k4lib.prototype.right				= function(obj) {
	return (this.left(obj) + this.width(obj));
}
	
/* Get the width of an object */
k4lib.prototype.width				= function(obj) {
	
	var objwidth		= 0;

	if(obj) {
		objwidth			= obj.offsetWidth;
	}

	return objwidth;
}

/* get the height of an object */
k4lib.prototype.height				= function(obj) {
	
	var objheight		= 0;
	
	if(obj) {
		objheight			= obj.offsetHeight;
	}

	return objheight;
}
		
/* Check if 'over' overlaps 'under' */
k4lib.prototype.overlaps			= function(over, under) {

	var does_overlap	= true;
	
	if(this.left(under) > this.right(over)) does_overlap = false;
	if(this.right(under) < this.left(over)) does_overlap = false;
	if(this.top(under) > this.bottom(over)) does_overlap = false;
	if(this.bottom(under) < this.top(over)) does_overlap = false;
	
	return does_overlap;
}

/**
 * Aesthetics
 */

/* Make the object's cursor look like a link */
k4lib.prototype.forceCursor		= function(obj) {
	
	if(obj) {
		try {
			obj.style.cursor = 'pointer';
		} catch(e) {
			obj.style.cursor = 'hand';
		}
	}
}

var d			= new k4lib()
var open_menu				= false;
var hidden_selects			= new Array()
var tempX					= 0;
var tempY					= 0;
var use_click				= true; // should the menus be opened by clicking them, or hovering?


/* Initialize a menu object */
function menu_init(menuname,arrow) {
	if (arrow==1)
	{
		document.write('<img border="0" src="techblue/menu_open.gif"/>')
		}
	var menu				= d.getElementById(menuname + "_menu");
	var link				= d.getElementById(menuname + "_link");
	
	if(menu && link) {
		
		//menu_positions(menu, link);

		menu.style.display	= 'none';
		menu.style.zIndex	= 1000;
		link.unselectable	= true;
		
		/* Add the link cursor */
		d.forceCursor(link);
		
		/* Onclick function for the current link */
		link.onclick = function() {
			
			if(link.href)
				link.href = '#' + link.id;

			// enforce the link id
			menu.link_id		= this.id;

			/* Open or close the menu */
			if(menu.style.display == 'none') {
				openmenu(menu, this);
			} else {
				closemenu(menu);
			}

			return false;
		}

		/* Onmouseover for a link object */
		link.onmouseover = function() {
			
			if(open_menu) {
				
				if(open_menu.link_id != this.id) {
					
					/* Close the current open menu */
					closemenu(open_menu);

					/* Open this new menu */
					openmenu(menu, this);
				}
			}

			if(!use_click) {
				
				// enforce the link id
				menu.link_id		= this.id;

				/* Open or close the menu */
				if(menu.style.display == 'none') {
					openmenu(menu, this);
				} else {
					if(menu.link_id != open_menu.link_id) {
						closemenu(menu);
					}
				}
			}
		}
		
		if(!use_click) {
			link.onmouseout = function(event) {
				hidemenuclick(event);
			}
			menu.onmouseout = function(event) {
				hidemenuclick(event);
			}
		}
		
		highlightmenurows(menu);
	}
}


/* Open a menu */
function openmenu(menu, link) {
	
	if(menu && link) {
		
		/* If the menu is currently closed */
		if(menu.style.display == 'none') {
			
			menu.style.display	= 'block';
			menu_positions(menu, link);

			/* Loop through all of the <select>'s on a page */
			selects				= d.getElementsByTagName(document, 'select');
			
			if(selects) {
				for (var s = 0; s < d.sizeof(selects); s++) {
					
					if(selects[s]) {

						/* If the menu overlaps the select menu, hide the select */
						if (d.overlaps(menu, selects[s])) {
							
							selects[s].style.display = 'none';
							d.array_push(hidden_selects, selects[s]);
						}
					}
				}
			}
			
			open_menu			= menu;
			
		/* Assume that the menu is open */
		} else {
			close_menu(menu);
		}
	}

	return true;
}


/* Close a menu */
function closemenu(menu) {
	
	if(menu && typeof(menu) == 'object') {
		menu.style.display		= 'none';
		open_menu				= false;
		
		/* Show any hidden select menus */
		if(d.sizeof(hidden_selects) > 0) {
			
			for(var i = 0; i < d.sizeof(hidden_selects); i++) {
				
				hidden_selects[i].style.display = 'block';
			}

			hidden_selects		= new Array()
		}
	}
}


/* show/hide a menu when someone clicks the page */

if(!use_click)
	document.onmousemove	= hidemenuclick;
document.onclick		= hidemenuclick;

function hidemenuclick(e) {
	
	var posX = 0, posY = 0;
	if(!e) { 
		e = window.event; 
	}

	if(e) {
		if( typeof( e.pageX ) == 'number' ) {
			posX = e.pageX; 
			posY = e.pageY;
		} else {
			if( typeof( e.clientX ) == 'number' ) {
				posX = e.clientX; 
				posY = e.clientY;
				if( document.body && !( window.opera || window.debug || navigator.vendor == 'KDE' ) ) {
					if( typeof( document.body.scrollTop ) == 'number' ) {
						posX += document.body.scrollLeft; 
						posY += document.body.scrollTop;
					}
				}
				if( document.documentElement && !( window.opera || window.debug || navigator.vendor == 'KDE' ) ) {
					if( typeof( document.documentElement.scrollTop ) == 'number' ) {
						posX += document.documentElement.scrollLeft; 
						posY += document.documentElement.scrollTop;
					}
				}
			}
		}
	}

//	var posx = 0;
//	var posy = 0;
//	if (!e) var e = window.event;
//	if (e.pageX || e.pageY) {
//		posx = e.pageX;
//		posy = e.pageY;
//	} else if (e.clientX || e.clientY) {
//		posx = e.clientX + document.body.scrollLeft;
//		posy = e.clientY + document.body.scrollTop;
//	}
	/* Deal with the menu */
	if(open_menu) {
		
		open_menulink	= d.getElementById(open_menu.link_id);
		
		keep_open		= true;
		
		if(posY > d.bottom(open_menu)) { keep_open = false; }
		if(posY < d.top(open_menulink)) keep_open = false;
		if(posX < d.left(open_menu)) keep_open = false;
		if(posX > d.right(open_menu)) keep_open = false;

		if(!keep_open && open_menu) {
			open_menu.style.display = 'none';
			open_menu				= false;
		}
		
	}
}


/* Highlight the rows (tr's) of the menu tables */
function highlightmenurows(menu) {
	if(menu) {
		
		var rows		= d.getElementsByTagName(menu, 'td');
		
		if(rows) {

			for(var i = 0; i < d.sizeof(rows); i++) {
				
				if(rows[i].className == 'dm1') {

					/* Apply styling to each of these rows */
					rows[i].onmouseover = function() {
						this.className = 'dm2';
					}

					rows[i].onmouseout = function() {
						this.className = 'dm1';
					}

				}
			}
		}
	}
}


/* Apply menu positioning */
function menu_positions(menu, link) {
	
	if(menu && link) {
		
		//if(parseInt(d.width(menu) - document.body.clientWidth) == 0) {
		//	menu.style.position	= 'absolute';
		//}
		
		menu.style.position	= 'absolute';

		/* set some menu position stuff */
		force_right			= parseInt(d.left(link) + d.width(menu)) >= document.body.clientWidth ? true : false;
		
		menu.style.left		= (force_right ? (d.left(link) - (d.width(menu) - d.width(link))) : d.left(link)) + 'px';
		menu.style.top		= parseInt(d.top(link) + d.height(link)) + 'px';
	}
}


/**
 * Deal with the events
 */

if(document.addEventListener ) {
	
	document.addEventListener('click', hidemenuclick, false);
	
	if(!use_click)
		document.addEventListener('mousemove', hidemenuclick, false);

} else if(document.attachEvent ) {
	
	document.attachEvent('onclick', hidemenuclick);
	
	if(!use_click)
		document.attachEvent('onmousemove', hidemenuclick);

}
put the code below in a file like menus.js , include this file in your headerinclude bit

Example code...
SEARCH in DHTML MENU - vBulletin Style:
Add this anywhere in the <body> of your html.
<div id="search_menu" style="display: none;">
	<table class="dmenu_border" width="172" border="0" cellspacing="1">
		<tr>
			<td class="thead">
				<strong>Search Forums</strong>
			</td>
		</tr>

		<tr>
			<td class="dm1b">
				<form action="search.php" method="post"> <input type="text" name="keywords" /> <!-- start: gobutton -->
<input type="submit" value="Go" />
<!-- end: gobutton -->
<input type="hidden" name="action" value="do_search" />
</form>
			</td>
		</tr>
<tr>

			<td class="dm1" onclick="window.location.href='search.php'">
				Advanced Search
			</td>
		</tr>
</table>
</div>

Add the code below wherever you want the control to be in.
<td class="mbmenu" id="search_link"><a href="http://www.otaku-networks.net/forums/search.php">Search</a> <script type="text/javascript">
	menu_init('search',1);</script></td>

Add the code below to your CSS
.dmenu_border
{
background: #b0d1ff;
padding: 0px;
border: 1px solid #3266ad;
}
.dm1, .dm1b, .dm2
{
padding:4px;
font-size: 11px;
}
.dm1, .dm1b
{
color: #5087d1;
cursor: pointer;
background: #F5F9FF;
}
.dm2
{
color: #fff;
cursor: pointer;
background: #92b4e2;
}
.dm1b
{
cursor: default;
}

_____________________________________________________

Tutorial:
Let your menu's base name be "MENUNAME"
The menu will be inputted in...
<div id="MENUNAME_menu"></div>
( Base Name + "_menu")
The menu's control(The link to the menu) will be
<(ANY TAG) ID="MENUNAME_link"></(ANY TAG)>
( Base Name + "_link")
To activate these two, you must rem. to put this after the expected menu link.
<script type="text/javascript">menu_init('MENUNAME');</script>
( Base Name )
To put a MENU OPEN IMAGE (An Arrow for vBulletin) after the expected menu link, instead of placing the code above, place the code below.
<script type="text/javascript">menu_init('MENUNAME',1);</script>
( 'Base Name',1 )
_____________________________________
*NOTE - In the code above, the image written by the script is in "techblue/menu_open.gif", replace this for your own button.
Very nice, keep up the good work. Maybe actually write a plugin for the new MyBB plugin system with this information in it so we dont have to edit the code? Smile
I think it would be hard to put it in a plugin system. Especially with my little knowledge of the MyBB Coding Style, and the plugin system itself.
paolo90 Wrote:I think it would be hard to put it in a plugin system. Especially with my little knowledge of the MyBB Coding Style, and the plugin system itself.

Still don't want to add this to the plugin system? I'd like this, but unable to add it. It's confusing. Rolleyes
I'm a designer - not a coder Smile
I'm not good in PHP Coding Toungue
can u make a full vbulletin theme for us? Cool
Your implementation of my menu script is flawed. Though there's nothing illegal with using a competing open-source butteling board's code, it doesn't do anything for the MyBB image. The least you could do is use the menu properly Toungue
I edited it a little for the image
Ah, I was on IE when I went to look at your mod site. The menu system wasn't working there. On firefox it works nicely though. It would be a shame if you let it go 'unworking' Wink
Instead of taking k4st's - even though it generally isn't breaking his license agreement, feel free to use a copy of the preliminary version we'll hopefully be using in MyBB in the future.

Grab the two JS files from here:

http://mybboard.com/global/jscripts/general.js
http://mybboard.com/global/jscripts/menu.js

Combine them into one file too if you wish.

Usage is as follows: (an example i've lifted directly from something i'm working on)

The button:
<a href="#" id="reportlist" onclick="return openMenu(this)" class="popup_button">Generic Reports <img src="images/popup_down.gif" border="0" /></a>

The menu items:
<div id="reportlist-popup" class="popup_menu" style="width:150px; display:none">
	<ul>

				<li><a href="browse.php?report=1">Active Tickets</a></li>
				<li><a href="browse.php?report=2">My Tickets</a></li>
				<li><a href="browse.php?report=3">My Active Tickets</a></li>
			</ul>
</div>

You can see all you need to do is basically change the id of each of the button and menu.

The CSS i'm using is as follows:
/* Popup Menus */

.popup_button {
	color: #000;
	text-align: right;
	background: #B3CEE8;
	border: 1px solid #000;
	font-weight: bold;
	padding: 3px;
	margin-top: 3px;
	margin-bottom: 3px;
	margin-left: 3px;
}

a.popup_button:link,
a.popup_button:visited,
a.popup_button:active,
a.popup_button:hover {
	text-decoration: none;
	color: #000;
}

.popup_menu {
	position: absolute;
	border: 1px solid #000;
	background: #ccc;
}

.popup_menu ul
{
	margin:0px;
	padding:0px;
	list-style-type:none;
}

.popup_menu li
{
	background: #fff;
	margin: 1px;
	padding: 0;

}

.popup_menu ul li a
{
	display: block;
	padding: 3px;
	color: #000;
	text-decoration: none;
}

* html .popup_menu ul li a {
	display: visible;
	width: 100%;
}

.popup_menu a:hover {
	background: #C7DBEE;
	text-decoration: none;
	color: #000;
}

Enjoy.
Pages: 1 2