SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 30

Thread: JS bug?

Hybrid View

  1. #1
    SitePoint Guru
    Join Date
    Mar 2004
    Posts
    639
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    JS bug?

    Hi guys,

    I've wrote very simple innerHTML code to show/hide div elements, but it doesn't work properly. When I put mouse over first div, it should show second div inside first one. When I put mouse out of the div, it should ide second div.

    When I put mouse over the first div, I can see second div. The problem is when put mouse over ANY element inside second div (image, link, even <HR /> tag), second div hides.

    My code is here.


    JavaScript part:

    HTML Code:
    var elements = Array([]);
    
    elements['addInformation'] = 'some html 1';
    elements['linkToThisPage'] = 'some html 2';
    elements['bookmarkThisPage'] = 'some html 3';
    
    function showDiv(element){
    	document.getElementById(element).innerHTML = elements[element];
    }
    
    function hideDiv(element){
    	document.getElementById(element).innerHTML = "";
    }

    HTML part:

    HTML Code:
    <div onmouseover="showDiv('addInformation');"  onmouseout="hideDiv('addInformation');">
    
    <table ....>
    
    <div align="center" class="green">Add some information
    
    <div id="addInformation"></div>
    
    <.... /table>
    
    </div>
    
    </div>

  2. #2
    SitePoint Wizard
    Join Date
    Nov 2004
    Location
    Nelson BC
    Posts
    2,310
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Javascript arrays have to be indexed numerically. If you want to use associative arrays then use the Object object instead:
    Code:
    var elements = {
    	'addInformation': 'some html 1',
    	'linkToThisPage': 'some html 2',
    	'bookmarkThisPage': 'some html 3'
    };
    
    alert(elements['addInformation']); // alerts 'some html 1'
    alert(elements.addInformation); // alerts same thing
    Note that objects do not contain the automatic .length property.

  3. #3
    SitePoint Evangelist bals28mjk's Avatar
    Join Date
    Aug 2007
    Posts
    405
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by jimfraser
    Javascript arrays have to be indexed numerically. If you want to use associative arrays then use the Object object instead:
    The way he is creating the associative array is perfectly acceptable. Though, he should be using new Array() or the short hand [] .
    Quote Originally Posted by al9
    When I put mouse over the first div, I can see second div. The problem is when put mouse over ANY element inside second div (image, link, even <HR /> tag), second div hides.
    Wow, I see your problem. This is extremely bizarre. The onmouseover event simply does not think that the element is part of the division. I tested to see if this is true with all other events, but that doesn't seem to be the case e.g onclick recognizes it's nested. It's not only with the innerHTML property; even if you create an element, append it into the div, it still won't recognize it's nested? I never realized what a piece of garbage the onmouseout event is.

    Surprisingly, I could only get it working with onmouseleave for ie:
    Code:
    <html>
    <head>
    <script type="text/javascript">	
    
    var elements = [];
    
    elements['addInformation']  = '<a href="http://www.google.com">google</a>';
    elements['linkToThisPage'] = '<p>Paragrpah Element</p>';
    elements['bookmarkThisPage'] = '<h3>H3 elment</h3>';
    
    function showDiv(element){
    	document.getElementById(element).innerHTML = elements['addInformation'] + elements['linkToThisPage'] + elements['bookmarkThisPage']
    	document.getElementById(element).style.backgroundColor="#3CF"
    }
    
    function hideDiv(element){
    	document.getElementById(element).innerHTML='';
    	document.getElementById(element).style.backgroundColor="#FFF"
    }
    </script>
    </head>
    <body>
    
    <div onmouseover="showDiv('addInformation')"><div align="center" class="green">Add some information</div></div>
    
    <div style="background-color:#33CCFF" align="center" id="addInformation" onmouseleave="hideDiv('addInformation')"></div>
    
    </body>
    </html>
    Another browser anyone?!?

  4. #4
    SitePoint Guru
    Join Date
    Mar 2004
    Posts
    639
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by jimfraser View Post
    Javascript arrays have to be indexed numerically. If you want to use associative arrays then use the Object object instead
    Why I can't use JS associative arrays? It seems they work in JS.

    bals28mjk
    Thanks. But I really want to use cross browser code.

    Is there any way to make first div think second div is a part of it?

  5. #5
    SitePoint Guru
    Join Date
    Mar 2004
    Posts
    639
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    By the way, it seems first div understands that text (simple text without links, images etc) of second div is a part of first one.

  6. #6
    SitePoint Evangelist bals28mjk's Avatar
    Join Date
    Aug 2007
    Posts
    405
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by al9
    Is there any way to make first div think second div is a part of it?
    One way or another, there's a way to accomplish what you are asking to do. All the ways I'm thinking of are very complex. I actually linked to this thread in two other forums and waiting to hear back to see if anyone knows a simple (as this should be) solution. If no one knows I'll see what I can whip up, but in the mean time you can search google to see if you can find anything that could help .

    Quote Originally Posted by al9
    Why I can't use JS associative arrays? It seems they work in JS.
    I'm not quite sure why jimfraser made mention of that (maybe he is confused) since it has nothing to do with your problem, but both ways are acceptable.

    Quote Originally Posted by al9
    By the way, it seems first div understands that text (simple text without links, images etc) of second div is a part of first one.
    You're right, I noticed that too.

  7. #7
    SitePoint Evangelist bals28mjk's Avatar
    Join Date
    Aug 2007
    Posts
    405
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I can't look at it now, but someone pointed me to two links in here.

  8. #8
    SitePoint Guru
    Join Date
    Mar 2004
    Posts
    639
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by bals28mjk View Post
    I can't look at it now, but someone pointed me to two links in here.
    Thanks I will read this now.

  9. #9
    SitePoint Wizard
    Join Date
    Nov 2004
    Location
    Nelson BC
    Posts
    2,310
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Wow - every day's a school day.

    Didn't realize you could create associative arrays (objects) using array constructor. It's kind of counter-intuitive, the created "array" has a .length property that doesn't correspond.

  10. #10
    SitePoint Evangelist bals28mjk's Avatar
    Join Date
    Aug 2007
    Posts
    405
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by jimfraser View Post
    It's kind of counter-intuitive, the created "array" has a .length property that doesn't correspond.
    Yeah, you were correct to say indexing, associative arrays, and js don't mix.

    Al9, it doesn't look like there's an easy way to do this. I'm in the mists of writing a script now. If you find anything useful post it here

  11. #11
    SitePoint Evangelist bals28mjk's Avatar
    Join Date
    Aug 2007
    Posts
    405
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Cheers . I know, the code should be tidied up but it took me awhile to get it like this and it's time for a nap .
    Code:
    <html>
    <head>
    <style type="text/css">
    .tur{background-color:#33CCFF}
    </style>
    <script type="text/javascript">	
    var count=1;
    
    var content='<div .class=tur><a href="http://www.google.com">google</a><p>Paragrpah Element</p><h3>H3 elment</h3></div>'
    window.onload=function(){
    		var x = 0;
    		var y = 0;
    		var offsetPointer = document.getElementById("d1"); 
    		while (offsetPointer) {
    		x += offsetPointer.offsetLeft;
    		y += offsetPointer.offsetTop;
    		offsetPointer = offsetPointer.offsetParent;	
    		}
    		  var el=document.getElementById("d1")
    		 
    		 var thebottom=parseInt(el.offsetHeight)+parseInt(y)
    		 var right=el.offsetWidth+x
    		 
    		 el_top = y
    		 el_bottom = thebottom
    		 el_left = x
    		 el_right = right
    		 
    		 el_top_i = y
    		 el_bottom_i = thebottom
    		 el_left_i = x
    		 el_right_i = right
    		 
    		 		 
    function func(e)
    {
    	e?e:e=event
    	
    	if((e.clientX > el_left) && (e.clientX < el_right) && (e.clientY>el_top) && (e.clientY<el_bottom))
    	{
    		if(count==1)
    		{
    		document.getElementById("d1").innerHTML+=content
    		refreshvalues()
    		}
    		count=0
    	}
    	else
    	{
    		if (count==0)
    		{
    			 el_top = el_top_i
    		 	 el_bottom = el_bottom_i
    		     el_left = el_left_i
    		     el_right = el_right_i
    		
    		}
    		count=1
    		document.getElementById("d1").innerHTML="<div style='background-color:#FFFFFF' >AddMoreInfo"
    	}
    }
    document.onmousemove=func
    
    }//end onload
    
    
    function refreshvalues()
    {
    	var x = 0;
    		var y = 0;
    		var offsetPointer = document.getElementById("d1"); 
    		while (offsetPointer) {
    		x += offsetPointer.offsetLeft;
    		y += offsetPointer.offsetTop;
    		offsetPointer = offsetPointer.offsetParent;	
    		}
    		  var el=document.getElementById("d1")
    		 
    		  var thebottom=parseInt(el.offsetHeight)+parseInt(y)
    		 
    		 var right=el.offsetWidth+x
    		 var width_total=el.offsetHeight+y
    		 
    		 el_top = y
    		 el_bottom = thebottom
    		 el_left = x
    		 el_right = right
    }
    </script>
    </head>
    <body>
    <div align="center" style="background-color:#33CCFF" id="d1"><div style="background-color:#FFFFFF">AddMoreInfo</div></div>
    </div>
    </body>
    </html>

  12. #12
    SitePoint Guru
    Join Date
    Mar 2004
    Posts
    639
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks, I will try it.

    But I still don't understand why does this happen? Is it just JS bug? There must be logical explanation.

  13. #13
    SitePoint Evangelist bals28mjk's Avatar
    Join Date
    Aug 2007
    Posts
    405
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Eh, now I don't think it's a js bug. It just seems to bubble oddly and inconsistently throughout different browsers. I think it would be a good idea for all browser writers to implement the onmouseleave and onmouseenter so someone else doesn't have to jump through hoops and pull their hair out over what should be a simple task.

  14. #14
    SitePoint Wizard
    Join Date
    Nov 2004
    Location
    Nelson BC
    Posts
    2,310
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This may be a hasLayout IE bug.

    Giving the containing divs a height (or any other css property that gives them layout) seems to fix it.

  15. #15
    SitePoint Wizard
    Join Date
    Nov 2004
    Location
    Nelson BC
    Posts
    2,310
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Probably easier to show my example:
    Code:
    <html>
    <head>
    <style type="text/css">
    div.setdiv {
    	xheight: 50px;
    }
    </style>
    <script type="text/javascript">
    var elements = Array([]);
    
    elements['addInformation'] = 'some html 1';
    elements['linkToThisPage'] = 'some html 2';
    elements['bookmarkThisPage'] = 'some html 3';
    
    
    function showDiv(element){
    	document.getElementById(element).innerHTML = elements[element];
    }
    
    function hideDiv(element){
    	document.getElementById(element).innerHTML = "";
    }
    </script>
    </head>
    <body>
    	<div onmouseover="showDiv('addInformation');"  onmouseout="hideDiv('addInformation');" class="setdiv">
    		<div align="center" class="green">
    			Add some information
    			<hr/>
    			<table><tr><td>1</td><td>2</td></tr></table>
    			<div id="addInformation"></div>
    		</div>
    	</div>
    	<div onmouseover="showDiv('linkToThisPage');"  onmouseout="hideDiv('linkToThisPage');" class="setdiv">
    		<div align="center" class="green">
    			Link to this page
    			<hr/>
    			<table><tr><td>1</td><td>2</td></tr></table>
    			<div id="linkToThisPage"></div>
    		</div>
    	</div>
    	<div onmouseover="showDiv('bookmarkThisPage');"  onmouseout="hideDiv('bookmarkThisPage');" class="setdiv">
    		<div align="center" class="green">
    			Bookmark this page
    			<hr/>
    			<table><tr><td>1</td><td>2</td></tr></table>
    			<div id="bookmarkThisPage"></div>
    		</div>
    	</div>
    
    </body>
    </html>
    If I try it in IE as is, it exhibits the problem you talked about I think. If I enable the height css property (by removing the x) then it seems to fix it.

  16. #16
    SitePoint Evangelist bals28mjk's Avatar
    Join Date
    Aug 2007
    Posts
    405
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by jimfraser
    This may be a hasLayout IE bug.
    If this were the case all we would have to do is change onmouseover and onmouseout to onmouseenter and on mouseleave for ie.
    Quote Originally Posted by al9
    By the way, it seems first div understands that text (simple text without links, images etc) of second div is a part of first one
    Quote Originally Posted by bals28mjk
    You're right, I noticed that too.
    I think you over looked this part of the thread Jim. He needs to put elements in a div but the onmouseover and onmouseout events don't behave as they seem they would. I'm gonna say it once more, the problem is the way browsers handle the bubbling of onmouseout and onmouseover.

  17. #17
    SitePoint Wizard
    Join Date
    Nov 2004
    Location
    Nelson BC
    Posts
    2,310
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Please try my example. If it fixes bug then great. If not, please post a concise example that displays the problem. Please state in which browsers it works/fails.

    The problem is when put mouse over ANY element inside second div (image, link, even <HR /> tag), second div hides.
    Reproduced in my test code, bug shows up in IE6. Cannot reproduce bug in FF.
    Fixed by adding height to container div, which gives it layout.

  18. #18
    SitePoint Guru
    Join Date
    Sep 2006
    Posts
    731
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    As the cursor enters a child element there is a mouseout event followed by a mouseover event, so both functions are called.

    The problem is when put mouse over ANY element inside second div (image, link, even <HR /> tag), second div hides.
    From your code, such elements are presumably generated by innerHTML and as such are not true child elements of the outer div. When the cursor enters them, the last event is a mouseout of the containing element.
    Tab-indentation is a crime against humanity.

  19. #19
    SitePoint Evangelist bals28mjk's Avatar
    Join Date
    Aug 2007
    Posts
    405
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by jimfraser
    Please try my example. If it fixes bug then great. If not, please post a concise example that displays the problem. Please state in which browsers it works/fails.

    Quote:The problem is when put mouse over ANY element inside second div (image, link, even <HR /> tag), second div hides.

    Reproduced in my test code, bug shows up in IE6. Cannot reproduce bug in FF.
    Fixed by adding height to container div, which gives it layout.
    Of course I tested your code . I see what you are trying to tell me, the elements are appearing perfectly fine. However, the task should be going like this:

    1. Mouseover an element and a new element appears.
    2. Hover over the new element and it remains visible.
    3. Mouseout of the new element and it dissapears.

    The problem is in step 2, the element dissapears instead of remaining visible. I tested in (ie6/7 new versisons ff opera.)
    Code:
    <html>
    <head>
    <style type="text/css">
    div.setdiv {
    	xheight: 50px;
    }
    </style>
    <script type="text/javascript">
    var elements = Array([]);
    
    elements['addInformation'] = '<a href="http://www.google.com">google</a>';
    elements['linkToThisPage'] = '<a href="http://www.google.com">google</a>';
    elements['bookmarkThisPage'] = '<a href="http://www.google.com">google</a>';
    
    
    function showDiv(element){
    	document.getElementById(element).innerHTML = elements[element];
    }
    
    function hideDiv(element){
    	document.getElementById(element).innerHTML = "";
    }
    </script>
    </head>
    <body>
    	<div onmouseover="showDiv('addInformation');"  onmouseout="hideDiv('addInformation');" class="setdiv">
    		<div align="center" class="green">
    			Add some information
    			<hr/>
    			<table><tr><td>1</td><td>2</td></tr></table>
    			<div id="addInformation"></div>
    		</div>
    	</div>
    	<div onmouseover="showDiv('linkToThisPage');"  onmouseout="hideDiv('linkToThisPage');" class="setdiv">
    		<div align="center" class="green">
    			Link to this page
    			<hr/>
    			<table><tr><td>1</td><td>2</td></tr></table>
    			<div id="linkToThisPage"></div>
    		</div>
    	</div>
    	<div onmouseover="showDiv('bookmarkThisPage');"  onmouseout="hideDiv('bookmarkThisPage');" class="setdiv">
    		<div align="center" class="green">
    			Bookmark this page
    			<hr/>
    			<table><tr><td>1</td><td>2</td></tr></table>
    			<div id="bookmarkThisPage"></div>
    		</div>
    	</div>
    
    </body>
    </html>
    Also, this one using createElement:
    Code:
    <html>
    <head>
    <style type="text/css">
    div.setdiv {
    	xheight: 50px;
    }
    </style>
    <script type="text/javascript">
    var elements = Array([]);
    
    function showDiv(element){
    	var el1=document.getElementById(element)
    	var el2=document.createElement("a")
    	el2.href="http://www.google.com"
    	var txt=document.createTextNode("google")
    	el2.appendChild(txt)
    	el1.appendChild(el2)
    	
    }
    
    function hideDiv(element){
    	document.getElementById(element).innerHTML = "";
    }
    </script>
    </head>
    <body>
    	<div onmouseover="showDiv('addInformation');"  onmouseout="hideDiv('addInformation');" class="setdiv">
    		<div align="center" class="green">
    			Add some information
    			<hr/>
    			<table><tr><td>1</td><td>2</td></tr></table>
    			<div id="addInformation"></div>
    		</div>
    	</div>
    	<div onmouseover="showDiv('linkToThisPage');"  onmouseout="hideDiv('linkToThisPage');" class="setdiv">
    		<div align="center" class="green">
    			Link to this page
    			<hr/>
    			<table><tr><td>1</td><td>2</td></tr></table>
    			<div id="linkToThisPage"></div>
    		</div>
    	</div>
    	<div onmouseover="showDiv('bookmarkThisPage');"  onmouseout="hideDiv('bookmarkThisPage');" class="setdiv">
    		<div align="center" class="green">
    			Bookmark this page
    			<hr/>
    			<table><tr><td>1</td><td>2</td></tr></table>
    			<div id="bookmarkThisPage"></div>
    		</div>
    	</div>
    
    </body>
    </html>

  20. #20
    SitePoint Guru
    Join Date
    Mar 2004
    Posts
    639
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for helping guys.

    I've tried your code in Firefox (Mac) and Safari and the only code working is bals28mjk's one.

    I rewrote it little bit and it even worked in my app. The problem is it only working with one div per page.

    Can you help me with rewriting this code little bit as function or point me to the right direction please. I'd really like to use this code on my site, but I need to call it as function(s).

  21. #21
    SitePoint Wizard
    Join Date
    Nov 2004
    Location
    Nelson BC
    Posts
    2,310
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ugh, yeah that sucks. One way to fix that is to see if the element that caused the mouseout is a child of the main container, and if it is don't hide the link.

    Code:
    <html>
    <head>
    <style type="text/css">
    div.setdiv {
    	height: 100px;
    }
    </style>
    <script type="text/javascript">
    	
    	
    	
    var elements = Array([]);
    
    function show(evt) {
    	evt = evt ? evt : window.event;
    	var ddId = this.id.split("_")[1];
    	if (this.contains && evt.fromElement) { // IE
    		if (!this.contains(evt.fromElement)) {
    			showDiv(ddId);
    		}
    	} else if (evt.relatedTarget) {
    		if (!containsDOM(this, evt.relatedTarget)) {
    			showDiv(ddId);
    		}
    	}
    }
    
    function hide(evt) {
    	evt = evt ? evt : window.event;
    	var ddId = this.id.split("_")[1];
    	if (this.contains && evt.toElement) { // IE
    		if (!this.contains(evt.toElement)) {
    			hideDiv(ddId);
    		}
    	} else if (evt.relatedTarget) {
    		if (!containsDOM(this, evt.relatedTarget)) {
    			hideDiv(ddId);
    		}
    	}
    }
    
    function containsDOM (container, containee) {
      var isParent = false;
      do {
        if ((isParent = container == containee))
          break;
        containee = containee.parentNode;
      }
      while (containee != null);
      return isParent;
    }
    
    function showDiv(element){
    	var el = document.getElementById(element).appendChild(document.createElement("a"));
    	el.href="http://www.google.com"
    	el.appendChild(document.createTextNode("google"));
    }
    
    function hideDiv(element){
    	document.getElementById(element).innerHTML = "";
    }
    
    window.onload = function () {
    	var divs = document.getElementsByTagName("div");
    	for (var i=0; i < divs.length; i++) {
    		var d = divs[i];
    		if (d.className == "setdiv") {
    			d.onmouseover = show;
    			d.onmouseout = hide;
    		}
    	}
    }
    
    </script>
    </head>
    <body>
    	<div class="setdiv" id="p_addInformation">
    		<div align="center" class="green">
    			Add some information
    			<hr/>
    			<table><tr><td>1</td><td>2</td></tr></table>
    			<div id="addInformation"></div>
    		</div>
    	</div>
    	<div class="setdiv" id="p_linkToThisPage">
    		<div align="center" class="green">
    			Link to this page
    			<hr/>
    			<table><tr><td>1</td><td>2</td></tr></table>
    			<div id="linkToThisPage"></div>
    		</div>
    	</div>
    	<div class="setdiv" id="p_bookmarkThisPage">
    		<div align="center" class="green">
    			Bookmark this page
    			<hr/>
    			<table><tr><td>1</td><td>2</td></tr></table>
    			<div id="bookmarkThisPage"></div>
    		</div>
    	</div>
    
    </body>
    </html>

  22. #22
    SitePoint Guru
    Join Date
    Mar 2004
    Posts
    639
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks Jim. It works. I wonder is it possible to make it smarter? I mean is it possible to learn it to remember height value of div elements?

    I think I know how to know about div's element height (before and after mouseover), but it will not work with this code, because of CSS. Am I wrong?

  23. #23
    SitePoint Wizard
    Join Date
    Nov 2004
    Location
    Nelson BC
    Posts
    2,310
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You don't necessarily have to set the height in CSS, but you need to give the container divs layout in order for IE to work well. See this page for other properties that can cause divs to have layout (under Remarks).

    http://msdn2.microsoft.com/en-us/library/ms530764.aspx

  24. #24
    SitePoint Guru
    Join Date
    Mar 2004
    Posts
    639
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by jimfraser View Post
    You don't necessarily have to set the height in CSS, but you need to give the container divs layout in order for IE to work well. See this page for other properties that can cause divs to have layout (under Remarks).

    http://msdn2.microsoft.com/en-us/library/ms530764.aspx
    I've just removed height: 100px from CSS and checked in all major browsers. It works perfectly in IE, Firefox (Mac) and Safari. Should I leave it as is?

  25. #25
    SitePoint Evangelist bals28mjk's Avatar
    Join Date
    Aug 2007
    Posts
    405
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Someone in the other thread linked to another solution that I like best found here.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •