I am trying to create an interactive map with an overlay using html image maps.
To see it, please visit: http://www.surge.ca/testing/WFA2100/index.html
The explanation:
When you hover over an <area> of the map, it bring up an overlay with links.
To prevent the overlay from closing when you move to it, as you are no longer hovering over the area, I am using a setTimeout before it closes the overlay.
The problem:
It works like I want in every browser but IE.
In IE 7 and 8, when you hover over an overlay that is above another <area>, it immediately switches to the overlay of that <area>.
At first, I thought it was a z-index issue where the <area>'s z-index was above the overlay, but I think my z-index is set up correctly. I am also thinking that it could just be how IE handles image maps?
The code:
Here is the code that sets up the events.
jQuery(function($){
// binds mouseenter and mouseleave to <area>
$('area').bind('mouseenter',function(){
sectionNum = this.hash;
sectionNum = sectionNum.replace(/#/,'');
showOverlay(sectionNum);
clearTimeout(timer);
}).bind('mouseleave', function(){
timerClose();
});
$('.map_info').bind('mouseenter', function(){
clearTimeout(timer);
}).bind('mouseleave', function(){
timerClose();
});
});
// sets timer before closing to allow cancel
var timer;
function timerClose(){
timer = setTimeout(function(){hideOverlay();},500);
}
The problem is that IE clear the setTimeout when hover ends. I didn't ran your code but I had same problem and cpuld fix it by passing the setTimeout function as an string.
For example setTimeout(alert('hi'), 1000) wasn't working on a function that was running in a hover state but setTimeout("alert('hi')", 1000) was working.
In your code maybe replacing
timer = setTimeout(function(){hideOverlay();},500);
with
timer = setTimeout("function(){hideOverlay();}",500);
solve the problem.
It seems IE run code that passed in string in global scope.
Also I can see you have jQuery in your page. There is a jQuery plug-in called hoverIntent that do hover delay very nice. Maybe plug-in writer wrote more cross-browser code.
Let me know if it works. :)
Related
i have 2 divs which toggles in every 3 seconds. now for the text in the div i am using an extension called sliding letters, as you can see in the demo available here. http://tympanus.net/Development/SlidingLetters/
The problem is, it works alone but now with toggle.
i have my working version located here http://webmaster.lk/n/
as you can see it is not showing the text "IMAGE 2" unless u hover it once.
can anybody please help me resolve this ?
i have the same created as a fiddle here, http://jsfiddle.net/KuW6K/5/
without hoverwords() - http://jsfiddle.net/KuW6K/4/ this is working correctly.
<body style="background:#cdcdcd;">
<div class="sl_examples">
<!-- need to show one of the links below every 3 seconds-->
image4
image2
</div>
</body>
Update
sample demo of the letter sliding extension - http://tympanus.net/Development/SlidingLetters/
Update 2
i removed the toggle() and re wrote it this was as in the answer 1 it was mentioned as toggle() is depreciated. but still no good.
$(document).ready(function() {
setInterval(function(){
if($("#example1").is(":visible"))
$("#example1").hide();
else
$("#example1").show();
if($("#example2").is(":visible"))
$("#example2").hide();
else
$("#example2").show();
},3000);
});
Update 3
I have attached the source here for reference, https://www.mediafire.com/?fi8547rhm1q8ixt
Update 4
actually it should only work when mouse enters and mouse leave. but here the problem is, (check this) http://webmaster.lk/n/ first it shows IMAGE 4 (red background) and when you hover it IMAGE 3 appears (light blue letters) then afer 3 seconds, Green color plain background appears without the text IMAGE 2. this is the problem why it is not working as IMAGE 4 works.
Your initial issue was caused because you were setting #example1 to display none;
#example1 {
background: green;
display: none;
}
And then you were calling
$('#example1').hoverwords();
This was causing the blank background.
So just remove the display:none; css and call hoverwords on example1 before it's hidden.
$('#example1').hoverwords();
$('#example2').hoverwords();
$('#example1').hide();
And then hide it after using jQuery.
It looks like you have a simillar working solution in your Update 4
http://jsfiddle.net/trevordowdle/KuW6K/15/
While it works well you can still trigger the error. This happens when hovering back and forth and the setInterval triggers at the same time. The toggle from the trigger and the hoverwords function if ran at near the same time interfere with each other and you don't get the desired result.
One option is to stop the words from changing while they are being hovered.
Like:
jQuery
var hover = false;
setInterval(function () {
if(!hover){
$('#example1').toggle();
$('#example2').toggle();
}
}, 3000);
$('#example1').hoverwords();
$('#example2').hoverwords();
$('#example1').hide();
$('.sl_examples').hover(function(){
hover = true;
},function(){
hover = false;
});
CSS
#example1 {
background: green;
}
http://jsfiddle.net/trevordowdle/KuW6K/14/
And if you would would rather have it reset the timer.. Meaning that once your done hovering the 3 second timer starts from 0. Here is another example:
http://jsfiddle.net/trevordowdle/KuW6K/16/
.toggle() is deprecated
http://api.jquery.com/toggle-event/
Check here for an equivalent
Equivalent of deprecated jQuery Toggle Event
UPDATE
So the real issue here is the way that the Sliding Letters library binds the event which triggers itself. This is the line doing the binding:
$el.bind('mouseenter.hoverwords mouseleave.hoverwords', function(e) {
aux.toggleChars($el, settings);
});
As you can see it is only bound to fire on mouseenter and mouseleave. Since you want this to trigger on an interval you need to alter the existing or create a new binding.
I've a scenario that requires me to detect animation stop of a periodically animated element and trigger a function. I've no control over the element's animation. The animation can be dynamic so I can't use clever setTimeout.
Long Story
The simplified form of the problem is that I'm using a third party jQuery sliding banners plugin that uses some obfuscated JavaScript to slide banners in and out. I'm in need of figuring out a hook on slideComplete sort of event, but all I have is an element id. Take this jsfiddle as an example and imagine that the javascript has been obfuscated. I need to trigger a function when the red box reaches the extremes and stops.
I'm aware of the :animated pseudo selector but I think it will need me to constantly poll the required element. I've gone through this, this, and this, but no avail. I've checked jquery promise but I couldn't figure out to use that in this scenario. This SO question is closest to my requirements but it has no answers.
P.S. Some more information that might be helpful:
The element isn't created by JavaScript, it is present on page load.
I've control over when to apply the plugin (that makes it periodically sliding banner) on the element
Most of the slideshow plugins I have used use changing classes at the end of the animation... You could extend the "addClass" method of jQuery to allow you to capture the class change as long as the plugin you use is using that method like it should:
(function($){
$.each(["addClass","removeClass"],function(i,methodname){
var oldmethod = $.fn[methodname];
$.fn[methodname] = function(){
oldmethod.apply( this, arguments );
this.trigger(methodname+"change");
return this;
}
});
})(jQuery);
I threw together a fiddle here
Even with obfuscated code you should be able to use this method to check how they are sending in the arguments to animate (I use the "options" object when I send arguments to animate usually) and wrap their callback function in an anonymous function that triggers an event...
like this fiddle
Here is the relevant block of script:
(function($){
$.each(["animate"],function(i,methodname){
var oldmethod = $.fn[methodname];
$.fn[methodname] = function(){
var args=arguments;
that=this;
var oldcall=args[2];
args[2]=function(){
oldcall();
console.log("slideFinish");
}
oldmethod.apply( this, args );
return this;
}
});
})(jQuery);
Well since you didn't give any indication as to what kind of animation is being done, I'm going to assume that its a horizontal/vertical translation, although I think this could be applied to other effects as well. Because I don't know how the animation is being accomplished, a setInterval evaluation would be the only way I can guess at how to do this.
var prevPos = 0;
var isAnimating = setInterval(function(){
if($(YOUROBJECT).css('top') == prevPos){
//logic here
}
else{
prevPos = $(YOUROBJECT).css('top');
}
},500);
That will evaluate the vertical position of the object every .5 seconds, and if the current vertical position is equal to the one taken .5 seconds ago, it will assume that animation has stopped and you can execute some code.
edit --
just noticed your jsfiddle had a horizontal translation, so the code for your jsfiddle is here http://jsfiddle.net/wZbNA/3/
I am having an issue where the slider will not stop auto play when I click a link on my navigation menu. I start the slider via:
$('.bxslider1').bxSlider({auto: true,autoControls: true});
It auto plays and works, but if I try to stop the slider by creating an onclick function or .click() jQuery like:
$(".nav-portfolio").click(function() {
slider = $('.bxslider1').bxSlider();
slider.stopAuto();
});
It seems to do something for a split second and then start again. The reason I need to stop the slider is, I am using jQuery waypoints for anchor links to scroll smooth horizontally, and the panels start moving back and fourth by 1 or 2 pixels and its really annoying for the user.
Any help would be appreciated.
Try modifying your code to be:
$(".nav-portfolio").click(function() {
$('.bxslider1').stopAuto();
});
You were previously using the example from the bxSlider webpage which assumes you haven't already initialized the bxSlider. Since you previously initialized it perhaps the second initialization isn't handled gracefully.
Try adding var keyword before the slider declaration.
$(".nav-portfolio").click(function() {
var slider = $('.bxslider1').bxSlider();
slider.stopAuto();
});
Using OpenLayers, I have a OpenLayers.Control.SelectFeature installed on a layer, with the hover option set to true. When creating the layer I call
<layer>.events.register("featureselected",...)
and
<layer>.events.register("featureunselected",...)
to register functions that create and destroy a popup. This all works fine. Now I want to add a small delay before the popup is created in order to avoid the popup flickering that currently occurs when moving the mouse across multiple features. However, I can't seem to figure out how to do this. I did find the OpenLayers.Handler.Hover handler, which has a delay option, but I don't know how to combine that with the SelectFeature control (if I even can).
I think this post has some valuable info, which I'm about to verify. Some answers down, someone talks about the flickering.
edit: In case you are making your own labels, I noticed the effect is less when you raise the labelOutlineWidth . It seems that only the letters of the label count as 'hover' and not the whole PointRadius radius. When you make the label outline too big, the label looks like a fly that hit a windscreen though (not a square but it follows the label contours, the letters more specifically).
update: apparently this is why when you hover a text label , check this out: pointer events properties. set this attribute (pointerEvents: ) in your OpenLayers.Style and try value 'all' and the others. It sure makes a difference for me.
I bind my feature selections a little different, here's a quick (untested) example that should get you what you need.
var timer,
delay = 500, //delay in ms
hover = new OpenLayers.Control.SelectFeature( <layer> , {
hover: true,
onSelect: function (feature) {
// setup a timer to run select function
timer = window.setTimeout(function () {
// your select code
}, delay);
},
onUnselect: function () {
// first cancel the pending timer (no side effects)
window.clearTimeout(timer);
// your unselect code
}
});
<map>.addControl(hover);
hover.activate();
I'm asking a question very similar to this one—dare I say identical?
An example is currently in the bottom navigation on this page.
I'm looking to display the name and link of the next and previous page when a user hovers over their respective icons. I'm pretty sure my solution will entail binding or timers, neither of which I'm seeming to understand very well at the moment.
Currently, I have:
$(document).ready(function() {
var dropdown = $('span.hide_me');
var navigator = $('a.paginate_link');
dropdown.hide();
$(navigator).hover(function(){
$(this).siblings(dropdown).fadeIn();
}, function(){
setTimeout(function(){
dropdown.fadeOut();
}, 3000);
});
});
with its respective HTML (some ExpressionEngine code included—apologies):
<p class="older_entry">Older<span class="hide_me">Older entry:
<br />
{title}</span></p>
{/exp:weblog:next_entry}
<p class="blog_home">Blog Main<span class="hide_me">Back to the blog</span></p>
{exp:weblog:prev_entry weblog="blog"}
<p class="newer_entry">Newer<span class="hide_me">Newer entry:
<br />
{title}</span></p>
This is behaving pretty strangely at the moment. Sometimes it waits three seconds, sometimes it waits one second, sometimes it doesn't fade out altogether.
Essentially, I'm looking to fade in 'span.hide_me' on hover of the icons ('a.paginate_link'), and I'd like it to remain visible when users mouse over the span.
Think anyone could help walk me through this process and understand exactly how the timers and clearing of the timers is working?
Thanks so much, Stack Overflow. You guys have been incredible as I walk down this road of learning to make the internet.
If you just want to get it working, you can try to use a tooltip plugin like this one.
If you want to understand how this should be done: first, get rid of the timeout, and make it work without it. The difference (from the user's point of view) is very small, and it simplifies stuff (developing and debugging). After you get it working like you want, put the timeout back in.
Now, the problem is you don't really want to hide the shown element on the navigator mouse-out event. You want to hide it in its own mouse out event. So I think you can just pass the first argument to the navigator hover function, and add another hover to dropdowns, that will have an empty function as a first argument, and the hiding code in its second argument.
EDIT (according to your response to stefpet's answer)
I understand that you DO want the dropdown to disappear if the mouse moves out of the navigator, UNLESS its moved to the dropdown itself. This complicates a little, but here is how it can be done: on both types of items mouse-out event, you set a timer that calls a function that hides the dropdown. lets say the timer is 1 second. on both kind of item mouse-in even, you clear this timer (see the w3school page on timing for syntax, etc). plus, in the navigator's mouse-in you have to show the dropdown.
Another issue with the timer in your code is that it will always execute when mouse-out. Due to the 3 seconds delay you might very well trigger it again when mouse-over but since the timer still exist it will fade out despite you actually have the mouse over the element.
Moving the mouse back and forth quickly will trigger multiple timers.
Try to get it to work without the timer first, then (if really needed) add the additional complexity with the delay (which you must keep track of and remove/reset depending on state).
Here was the final working code, for anyone who comes across this again. Feel free to let me know if I could have improved it in any ways:
$(document).ready(function() {
var dropdown = $('span.hide_me');
var navigator = $('a.paginate_link');
dropdown.hide();
$(navigator).hover(function(){
clearTimeout(emptyTimer);
$(this).siblings(dropdown).fadeIn();
}, function(){
emptyTimer = setTimeout(function(){
dropdown.fadeOut();
}, 500);
});
$(dropdown).hover(function(){
clearTimeout(emptyTimer);
}, function(){
emptyTimer = setTimeout(function(){
dropdown.fadeOut();
}, 500);
});
});