This one is a tricky one, and i get the feeling its a missing piece of knowledge about just how these image maps work. Anyway..
The problem visible at here http://luff.redlinestaging.com/index.php?option=com_content&view=article&id=35
JS CODE:
jQuery(document).ready( function() {
jQuery.get('map.php?country=canada', function(output) {
jQuery('#map').html( output );
addClickMap();
});
});
function showState(e) {
//console.log( jQuery(this).is(':hidden' ) );
var title = jQuery(this).attr( 'title' );
var stateClass = '.' + title;
jQuery(stateClass).addClass( 'hover' );
}
function hideState(e) {
//console.log( jQuery(this).is(':hidden' ) );
var title = jQuery(this).attr( 'title' );
var stateClass = '.' + title;
jQuery(stateClass).removeClass( 'hover' );
}
function addClickMap() {
if( jQuery('#canada') ) {
jQuery('#canada area').each( function() {
//jQuery(this).hoverIntent( showState, hideNav );
jQuery(this).mouseenter( showState );
jQuery(this).mouseleave( hideState );
jQuery(this).click( function( e ) {
e.preventDefault();
});
});
}
}
CSS CODE:
#map {
width:100%;
}
.map {
width:100%;
height:100%;
position:relative;
}
area {
position:absolute;
top:0px;
left:0px;
z-index: 1001;
display:block;
visibility:visible;
}
.canada {
background-image:url(/map/map_canada.png);
background-repeat:no-repeat;
}
.hover {
display:block !important;
}
.state {
position:absolute;
z-index:2;
top:0px;
left:0px;
display:none;
}
.AB {
top:375px;
left:342px;
}
.BC {
top: 308px;
left: 236px;
}
.SK {
top: 394px;
left: 406px;
}
.NB {
top: 550px;
left: 784px;
}
.MB {
top: 405px;
left: 486px;
}
.NT {
top:198px;
left: 321px;
}
.NL {
top: 380px;
left: 765px;
}
.NU {
top:-4px;
left: 397px;
}
.ON {
top: 456px;
left: 535px;
}
.PE {
top: 532px;
left: 820px;
}
.NS {
top: 551px;
left: 811px;
}
.QC {
top: 364px;
left: 655px;
}
.YT {
top:180px;
left:243px;
}
Generated HTML dump from PHP for Canada:
<div class="map canada">
<img src="/map/map_canada.png" usemap="#canada" class="map_canada"/>
<div class="state AB" style="background-image:url(/map/icons/AB.png); width:107px; height:182px; background-repeat:no-repeat;">
</div>
<div class="state BC" style="background-image:url(/map/icons/BC.png); width:143px; height:239px; background-repeat:no-repeat;">
</div>
<div class="state MB" style="background-image:url(/map/icons/MB.png); width:112px; height:170px; background-repeat:no-repeat;">
</div>
<div class="state NB" style="background-image:url(/map/icons/NB.png); width:56px; height:55px; background-repeat:no-repeat;">
</div>
<div class="state NL" style="background-image:url(/map/icons/NL.png); width:170px; height:164px; background-repeat:no-repeat;">
</div>
<div class="state NT" style="background-image:url(/map/icons/NT.png); width:189px; height:218px; background-repeat:no-repeat;">
</div>
<div class="state NS" style="background-image:url(/map/icons/NS.png); width:83px; height:68px; background-repeat:no-repeat;">
</div>
<div class="state NU" style="background-image:url(/map/icons/NU.png); width:372px; height:425px; background-repeat:no-repeat;">
</div>
<div class="state ON" style="background-image:url(/map/icons/ON.png); width:207px; height:217px; background-repeat:no-repeat;">
</div>
<div class="state PE" style="background-image:url(/map/icons/PE.png); width:39px; height:42px; background-repeat:no-repeat;">
</div>
<div class="state QC" style="background-image:url(/map/icons/QC.png); width:216px; height:259px; background-repeat:no-repeat;">
</div>
<div class="state SK" style="background-image:url(/map/icons/SK.png); width:97px; height:176px; background-repeat:no-repeat;">
</div>
<div class="state YT" style="background-image:url(/map/icons/YT.png); width:118px; height:189px; background-repeat:no-repeat;">
</div>
</div>
<map id="canada" name="canada">
<area shape="poly" coords="410,552,446,401,500,413,485,568," href="#" title="SK" />
<area shape="poly" coords="488,568,503,413,552,419,596,463,545,519,542,572," href="#" alt="" title="MB" />
<area shape="poly" coords="597,466,548,524,546,569,590,589,608,575,641,599,687,629,666,668,700,651,738,619,673,642,691,602,686,589,680,535,655,515,653,485,627,481," href="#" alt="" title="ON" />
</map>
As you can see, it mouse overs fine, but calls the mouseout event to early, or mouseleave event to early (take your pick, neither work). Its not very responsive at times as well but that is a different problem unto the one that I really care about that being that it fires both the mouseover and mouseout event seemingly right after the other while the mouse is moving. Is there a way to make this not so messy?
If this cannot be done, what is the best method moving forward you figure? a) Simplify design and use maphilight b) write some very complicated function which detects mouse overs based on mouse position? We may want to put custom image designs into each of the states/provinces in the future so having a full image display is desirable.
I set a breakpoint in your hideState
function and looked at these properties:
e.target
e.relatedTarget
The first is the element that triggered the event. This was the area, as expected. For mouse enter/exit events, the 2nd is the area that the mouse moved into. In this case it is:
<div class="state SK hover"
style="background-image:url(/map/icons/SK.png);
width:97px; height:176px; background-repeat:no-repeat;">
</div>
So you have a series of rectangular DIVs overlaid on top of the image map. When you show the DIV, in the same area where the mouse is, it becomes the topmost layer, and the mouse therefore exits the area
and enters the div
causing the problem you are seeing.
In order to solve this problem, you need to be sure that the imagemap is always the topmost layer, yet you can still see the div
elements through it. You can do this by making a copy of the image, and making the imagemap transparent (but with a higher z-index than the divs). Basically, you have 3 layers: the bottom one is the visible image; the 2nd one is your div
elements, the top one is the imagemap (but completely transparent). The markup is like this:
<img src="http://luff.redlinestaging.com/map/map_canada.png"
class="map_canada"
style="position: absolute; left: 0; top: 0">
<img src="http://luff.redlinestaging.com/map/map_canada.png"
usemap="#canada"
class="map_canada"
style="z-index: 1000; opacity: 0; position: absolute; left: 0; top: 0;">
The position: absolute
is needed to put the two images on top of each other. You will notice the first one has no imagemap. It's not needed. This is just for show: this is the background image you can see. The 2nd one is the imagemap, but opacity:0
makes it invisible, and z-index:1000
ensures it is always on top, even when you add the divs later as a result of the mouseover event. So the imagemap still has the highest priority, but it doesn't conceal the actual image or the divs that will be rendered behind it.
Working example:
An alternative is to use ImageMapster which is a jquery plugin to do this for you without the need to manage alternate images for each area. That is- you can provide it with a single alternate image and it will use the data from each respective area to fill the highlights. The first demo on the web site shows this.