Please help! Two simple javascripts are conflicting but I need them both to work!

Discussion in 'JavaScript' started by cscott5288, Jul 9, 2010.

  1. #1
    I have two Javascripts working on one HTML element. One works by using the 'rel' attribute as a selector and executing an external script and the other is a simple onMouseOver, onMouseOut, right on the HMTL element:

    <li id="about_us"><a href="http://www.google.com" rel="dropmenu1_b" onMouseOver="document.MyImage2.src='images/TBC_Banner_Nav_02_MO.gif';" onMouseOut="document.MyImage2.src='images/TBC_Banner_Nav_02_OFF.gif';">
    <img src="images/TBC_Banner_Nav_02_OFF.gif" name="MyImage2"></a>
    </li>

    The two won't work together but each will work fine when the other is not present. Here is the script that the rel="dropmenu1_b" is acting as a selector for. I'm guessing I need to combine the two scripts? I have no idea how to do that and know very little about client side scripting. Please help!
     
    cscott5288, Jul 9, 2010 IP
  2. Imozeb

    Imozeb Peon

    Messages:
    666
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    0
    #2
    onMouseOver, onMouseOut should have no capital letters. (onmouseover, onmouseout)
     
    Imozeb, Jul 9, 2010 IP
  3. cscott5288

    cscott5288 Active Member

    Messages:
    912
    Likes Received:
    5
    Best Answers:
    0
    Trophy Points:
    60
    #3
    that's true but it doesn't solve the problem unfortunately :(
     
    cscott5288, Jul 9, 2010 IP
  4. meloncholy

    meloncholy Peon

    Messages:
    22
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    0
    #4
    First, a caveat: I haven't tried the scripts and I haven't read most of the menu script, so what follows may be wrong. :)

    I'm guessing that, when you use the scripts together, the menu works and the banner switching code doesn't? If not, the following may not solve things for you, but if it does then the menu script also adds a handler to onmouseover, which replaces the handler you've added.

    
    if (menuitems[i].getAttribute("rel")){
    ...
      menuitems[i].onmouseover=function(e){
        var event=typeof e!="undefined"? e : window.event;
        tabdropdown.dropit(this, event, this.getAttribute("rel"));
      }
    
    Code (markup):
    The script should really have been written to take account of situations like yours by using a different registration model that allows multiple handlers for each event. You *should* be able to use something like this instead (again untested). More on this from PPK.

    
    if (menuitems[i].getAttribute("rel")){
    ...
      menuitems[i].addEventListener("onmouseover",function(e)
      {
         var event=typeof e!="undefined"? e : window.event;
         tabdropdown.dropit(this, event, this.getAttribute("rel"));
      }, false);
    
    Code (markup):
    Edit: Just seen there's another mouseover and mouseout handler in the menu. You may want that one instead.
     
    meloncholy, Jul 9, 2010 IP
  5. cscott5288

    cscott5288 Active Member

    Messages:
    912
    Likes Received:
    5
    Best Answers:
    0
    Trophy Points:
    60
    #5
    So are you saying I can't use the script you provided? Where do I place the script you provided -- I am getting syntax errors when I place it between <script type="text/javascript"> and </script>. Appreciate the help! Let's pretend i know absolutely nothing about client side scripting!
     
    cscott5288, Jul 9, 2010 IP
  6. meloncholy

    meloncholy Peon

    Messages:
    22
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    0
    #6
    The code I gave was supposed to replace part of the code in the menu JS file. I thought I'd said that above, though rereading what I wrote I don't actually think I said it very clearly at all. Sorry. I've tried it now and, after correcting a mistake :), it seems to work. (Full code below.)

    I hope you don't mind me saying - and I obviously don't know your full situation - but I think there are easier ways to solve your problem. You appear to be changing the image behind a menu item when the mouse hovers over it. You can do this (with no JavaScript in browsers that aren't IE 6) by changing the background image through CSS with the :hover pseudoclass.

    The menu script looks pretty poor too. The HTML menu structure is completely unrelated to the on screen menu structure, and the JavaScript is overly complicated as a result. Suckerfish is a cleaner (and, except in IE 6, JavaScript-free) way of making dropdown menus.

    I'd certainly recommend taking a look at these options.

    
    //Drop Down Tabs Menu- Author: Dynamic Drive (http://www.dynamicdrive.com)
    //Created: May 16th, 07'
    
    var tabdropdown = {
    	disappeardelay: 200, //set delay in miliseconds before menu disappears onmouseout
    	disablemenuclick: false, //when user clicks on a menu item with a drop down menu, disable menu item's link?
    	enableiframeshim: 1, //1 or 0, for true or false
    
    	//No need to edit beyond here////////////////////////
    	dropmenuobj: null, ie: document.all, firefox: document.getElementById && !document.all, previousmenuitem: null,
    	currentpageurl: window.location.href.replace("http://" + window.location.hostname, "").replace(/^\//, ""), //get current page url (minus hostname, ie: http://www.dynamicdrive.com/)
    
    	getposOffset: function (what, offsettype) {
    		var totaloffset = (offsettype == "left") ? what.offsetLeft : what.offsetTop;
    		var parentEl = what.offsetParent;
    		while (parentEl != null) {
    			totaloffset = (offsettype == "left") ? totaloffset + parentEl.offsetLeft : totaloffset + parentEl.offsetTop;
    			parentEl = parentEl.offsetParent;
    		}
    		return totaloffset;
    	},
    
    	showhide: function (obj, e, obj2) { //obj refers to drop down menu, obj2 refers to tab menu item mouse is currently over
    		if (this.ie || this.firefox)
    			this.dropmenuobj.style.left = this.dropmenuobj.style.top = "-500px"
    		if (e.type == "click" && obj.visibility == hidden || e.type == "mouseover") {
    			if (obj2.parentNode.className.indexOf("default") == -1) //if tab isn't a default selected one
    				obj2.parentNode.className = "selected"
    			obj.visibility = "visible"
    		}
    		else if (e.type == "click")
    			obj.visibility = "hidden"
    	},
    
    	iecompattest: function () {
    		return (document.compatMode && document.compatMode != "BackCompat") ? document.documentElement : document.body
    	},
    
    	clearbrowseredge: function (obj, whichedge) {
    		var edgeoffset = 0
    		if (whichedge == "rightedge") {
    			var windowedge = this.ie && !window.opera ? this.standardbody.scrollLeft + this.standardbody.clientWidth - 15 : window.pageXOffset + window.innerWidth - 15
    			this.dropmenuobj.contentmeasure = this.dropmenuobj.offsetWidth
    			if (windowedge - this.dropmenuobj.x < this.dropmenuobj.contentmeasure)  //move menu to the left?
    				edgeoffset = this.dropmenuobj.contentmeasure - obj.offsetWidth
    		}
    		else {
    			var topedge = this.ie && !window.opera ? this.standardbody.scrollTop : window.pageYOffset
    			var windowedge = this.ie && !window.opera ? this.standardbody.scrollTop + this.standardbody.clientHeight - 15 : window.pageYOffset + window.innerHeight - 18
    			this.dropmenuobj.contentmeasure = this.dropmenuobj.offsetHeight
    			if (windowedge - this.dropmenuobj.y < this.dropmenuobj.contentmeasure) { //move up?
    				edgeoffset = this.dropmenuobj.contentmeasure + obj.offsetHeight
    				if ((this.dropmenuobj.y - topedge) < this.dropmenuobj.contentmeasure) //up no good either?
    					edgeoffset = this.dropmenuobj.y + obj.offsetHeight - topedge
    			}
    			this.dropmenuobj.firstlink.style.borderTopWidth = (edgeoffset == 0) ? 0 : "1px" //Add 1px top border to menu if dropping up
    		}
    		return edgeoffset
    	},
    
    	dropit: function (obj, e, dropmenuID) {
    		if (this.dropmenuobj != null) { //hide previous menu
    			this.dropmenuobj.style.visibility = "hidden" //hide menu
    			if (this.previousmenuitem != null && this.previousmenuitem != obj) {
    				if (this.previousmenuitem.parentNode.className.indexOf("default") == -1) //If the tab isn't a default selected one
    					this.previousmenuitem.parentNode.className = ""
    			}
    		}
    		this.clearhidemenu()
    		if (this.ie || this.firefox) {
    			obj.onmouseout = function () { tabdropdown.delayhidemenu(obj) }
    			obj.onclick = function () { return !tabdropdown.disablemenuclick } //disable main menu item link onclick?
    			this.dropmenuobj = document.getElementById(dropmenuID)
    			this.dropmenuobj.addEventListener("mouseover", function () { tabdropdown.clearhidemenu() }, false);
    			this.dropmenuobj.addEventListener("mouseout", function (e) { tabdropdown.dynamichide(e, obj) }, false);
    			this.dropmenuobj.addEventListener("click", function () { tabdropdown.delayhidemenu(obj) }, false);
    			this.showhide(this.dropmenuobj.style, e, obj)
    			this.dropmenuobj.x = this.getposOffset(obj, "left")
    			this.dropmenuobj.y = this.getposOffset(obj, "top")
    			this.dropmenuobj.style.left = this.dropmenuobj.x - this.clearbrowseredge(obj, "rightedge") + "px"
    			this.dropmenuobj.style.top = this.dropmenuobj.y - this.clearbrowseredge(obj, "bottomedge") + obj.offsetHeight + 1 + "px"
    			this.previousmenuitem = obj //remember main menu item mouse moved out from (and into current menu item)
    			this.positionshim() //call iframe shim function
    		}
    	},
    
    	contains_firefox: function (a, b) {
    		while (b.parentNode)
    			if ((b = b.parentNode) == a)
    				return true;
    		return false;
    	},
    
    	dynamichide: function (e, obj2) { //obj2 refers to tab menu item mouse is currently over
    		var evtobj = window.event ? window.event : e
    		if (this.ie && !this.dropmenuobj.contains(evtobj.toElement))
    			this.delayhidemenu(obj2)
    		else if (this.firefox && e.currentTarget != evtobj.relatedTarget && !this.contains_firefox(evtobj.currentTarget, evtobj.relatedTarget))
    			this.delayhidemenu(obj2)
    	},
    
    	delayhidemenu: function (obj2) {
    		this.delayhide = setTimeout(function () { tabdropdown.dropmenuobj.style.visibility = 'hidden'; if (obj2.parentNode.className.indexOf('default') == -1) obj2.parentNode.className = '' }, this.disappeardelay) //hide menu
    	},
    
    	clearhidemenu: function () {
    		if (this.delayhide != "undefined")
    			clearTimeout(this.delayhide)
    	},
    
    	positionshim: function () { //display iframe shim function
    		if (this.enableiframeshim && typeof this.shimobject != "undefined") {
    			if (this.dropmenuobj.style.visibility == "visible") {
    				this.shimobject.style.width = this.dropmenuobj.offsetWidth + "px"
    				this.shimobject.style.height = this.dropmenuobj.offsetHeight + "px"
    				this.shimobject.style.left = this.dropmenuobj.style.left
    				this.shimobject.style.top = this.dropmenuobj.style.top
    			}
    			this.shimobject.style.display = (this.dropmenuobj.style.visibility == "visible") ? "block" : "none"
    		}
    	},
    
    	hideshim: function () {
    		if (this.enableiframeshim && typeof this.shimobject != "undefined")
    			this.shimobject.style.display = 'none'
    	},
    
    	isSelected: function (menuurl) {
    		var menuurl = menuurl.replace("http://" + menuurl.hostname, "").replace(/^\//, "")
    		return (tabdropdown.currentpageurl == menuurl)
    	},
    
    	init: function (menuid, dselected) {
    		this.standardbody = (document.compatMode == "CSS1Compat") ? document.documentElement : document.body //create reference to common "body" across doctypes
    		var menuitems = document.getElementById(menuid).getElementsByTagName("a")
    		for (var i = 0; i < menuitems.length; i++) {
    			if (menuitems[i].getAttribute("rel")) {
    				var relvalue = menuitems[i].getAttribute("rel")
    				document.getElementById(relvalue).firstlink = document.getElementById(relvalue).getElementsByTagName("a")[0];
    				menuitems[i].addEventListener("mouseover", function (e) {
    					var event = typeof e != "undefined" ? e : window.event;
    					tabdropdown.dropit(this, event, this.getAttribute("rel"));
    				}, false);
    			}
    			if (dselected == "auto" && typeof setalready == "undefined" && this.isSelected(menuitems[i].href)) {
    				menuitems[i].parentNode.className += " selected default"
    				var setalready = true
    			}
    			else if (parseInt(dselected) == i)
    				menuitems[i].parentNode.className += " selected default"
    		}
    	}
    
    }
    
    Code (markup):
     
    meloncholy, Jul 10, 2010 IP
  7. cscott5288

    cscott5288 Active Member

    Messages:
    912
    Likes Received:
    5
    Best Answers:
    0
    Trophy Points:
    60
    #7
    Thanks a lot. You're definitely right about the Javascript being overly complicated.

    For some reason I thought that the hover pseudo class could only be used on the a element and not other elements like the li element ... I definitely want to use the hover pseudo element rather than a Javascript, I do have one question though. How can I make it so the menu button that is hovered over (the one that activates the javascript that shows the drop down menu) will continue to show the hovered background image (specified by the :hover pseudo class) when the mouse is hovering over menu items in the drop down menu rather than the button itself?

    So if I have like: Home - About - Contact
    When I hover over "About," the background image is replaced with CSS and a drop down menu appears. But when I hover over the drop down menu items, the background image for 'About' will revert back to the default.
     
    cscott5288, Jul 10, 2010 IP
  8. meloncholy

    meloncholy Peon

    Messages:
    22
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    0
    #8
    That's true for IE 6; more recent browsers support :hover on all (almost all?) elements.

    Again :) you won't have this problem if you start with a properly structured menu. Because Suckerfish nests submenus as lists within the main list, :hover stays on while the mouse is over the submenu items too. (In fact Suckerfish needs this behaviour to work.) In this example, you can add something like the CSS below to change the hover colour of the main menu items to red (not IE 6). For individual images per item, you can obviously add IDs to the lis and style that instead.

    
    #nav > li:hover { background-color: #f00; }
    
    Code (markup):
     
    meloncholy, Jul 10, 2010 IP
  9. cscott5288

    cscott5288 Active Member

    Messages:
    912
    Likes Received:
    5
    Best Answers:
    0
    Trophy Points:
    60
    #9
    Nice! I think I will go with the suckerfish menu. Thanks! Rep added.
     
    cscott5288, Jul 12, 2010 IP
  10. cscott5288

    cscott5288 Active Member

    Messages:
    912
    Likes Received:
    5
    Best Answers:
    0
    Trophy Points:
    60
    #10
    EDIT:
    HA! Just seconds before posting this, I figured it out. Why not apply the onMouseOver attribute to every item on the drop down list? That way the image up top will remain the proper hovered image! Eureka!!


    Alright, here is just one problem that I have.

    The top-level menu items MUST be images.
    Top-level menu items must contain links (the 'a' element), otherwise they could not link anywhere

    The reason why I can't use the background property in the CSS to display different background (when hovering and when not hovering), is because the button must be linkable. In order for it to be linkable, the 'a' element must contain either text or an img... but if I have either of those two things then I cannot control the background via CSS (using the hover pseudo element)!

    So what I am stuck with is a fully functioning CSS drop down menu, the proper hover images (using a javascript to replace the top-level menu buttons) but I am not able to keep the top-level image the correct hover image when mousing over the drop down menu .. it's just that one thing that I need to fix!
     
    cscott5288, Jul 12, 2010 IP