I have a menu which has 8 pictures and I want to write a fade effect for them. I want to show the name of the menu when the mouse goes over it, and hide it when mouse goes out. Here is my code for two of my menu items:
$(".menu_account").mouseover(function(){
$("#menu_name").html('first');
$("#menu_name").fadeIn('slow', function(){
$(".menu_account").mouseout(function(){
$("#menu_name").fadeOut('slow', function(){});
})
});
});
$(".menu_myposts").mouseover(function(){
$("#menu_name").html('second');
$("#menu_name").fadeIn('slow', function(){
$(".menu_myposts").mouseout(function(){
$("#menu_name").fadeOut('slow', function(){});
})
});
});
My problem is when I am on the first item and the name has been appeared, when I move the cursor to the second item before the first fades out, the name's innerHTML changes and it gets ugly. I want to wait for fading out to be completed and start again. I really appreciate any help.
thanx.
Here is my full code:
HTML :
<div id="menu">
<a class="menu_account"></a>
<a class="menu_myposts"></a>
<a class="menu_allposts"></a>
<a class="menu_favorites"></a>
<a class="menu_follow"></a>
<a class="menu_logout"></a>
<a class="menu_help"></a>
<a class="menu_contact"></a>
</div>
<div style="height:20px;width:200px;margin:0 auto;text-align:center;">
<div id="menu_name" style="font-size:30px;color:#A1A1A1;display:none;"></div>
</div>
JS :
$("#menu").ready(function(){
$(".menu_myposts").hover(
function () {
$("#menu_name").html('first');
$("#menu_name").fadeIn('slow', function(){});
},
function () {
$("#menu_name").fadeOut('slow', function(){});
}
);
$(".menu_myposts").hover(
function () {
$("#menu_name").html('second');
$("#menu_name").fadeIn('slow', function(){});
},
function () {
$("#menu_name").fadeOut('slow', function(){});
}
);
});
Correct JS:
$(".menu_item").hover(
function() {
$("#menu_name").html($('#' + this.id + '_name').html());
$("#menu_name").stop(true, true).fadeIn();
},
function() {
$("#menu_name").stop(true, true).fadeOut();
}
);
I guess the mouseout event should be defined outside like this:-
$(".menu_account").mouseover(function(){
$("#menu_name").html('first');
$("#menu_name").fadeIn('slow', function(){
});
});
$(".menu_account").mouseout(function(){
$("#menu_name").fadeOut('slow', function(){});
})
That's why the fadeout happens immediately.
You could reuse the code like this :-
var menuClasses = {'menu_account' : 'first', 'menu_classes' :'second'};
$.each(menuClasses function(index, value) {
$("."+value).hover(dothisOnMouseover(value), dothisOnMouseout())
});
$("td").hover(
function () {
$(this).addClass("hover");
},
function () {
$(this).removeClass("hover");
}
);
function dothisOnMouseover(value)
{
$("#menu_name").html(value);
$("#menu_name").fadeIn('slow', function(){});
}
function dothisOnMouseout()
{
$("#menu_name").html('');
$("#menu_name").fadeOut('slow', function(){});
}
Updates
The solution is to somehow check inside dothisOnMouseout() if the fadeIn() has completed already. But I don't know how to do that. So, I have this other trick to enable mouseover only if fadeOut() is complete -
function dothisOnMouseover(value)
{
//Remove the `onmouseover="dothisOnMouseover()" binding of all other menus here - or may be all menus - check it.
$("#menu_name").html(value);
$("#menu_name").fadeIn('slow', function(){
//On completion of this fade in attach back the `onmouseover="dothisOnMouseover"` event binding all other menus here - Note - do not call `dothisOnMouseout()` here
});
}
Doing so, if you hover on any menu before the fadeOut() completes, nothing will happen. try it out.
I've created a Fiddle that might be interesting. It is similar to the one in this post with the difference that the names of the menu items are created on the fly.
The code from the fiddle:
$("#menu li").hover(
function() {
if (!$(this).data("name")) {
$(this).data("name",
$('<div class="name"></div>')
.text($(this).text())
.hide()
.appendTo("#nameWrapper"));
}
$(this).data("name")
.stop(true, true)
.fadeIn();
},
function() {
$(this).data("name")
.stop(true, true)
.fadeOut();
}
);
The idea is to have a name element for every menu item so you get a nice fade effect when the old name fades out and new one fades in at the same time.
The first part of the first hover function creates a name element if there isn't one. The element is connected with the menu item using the data() function.
The second part of the first hover function just fades in the name element. The second function fades it out.
The trick here is to use stop(true, true) to stop all animation on the element.
EDIT:
You start with a html structure like this one:
<ul id="menu">
<li>First</li>
<li>Second</li>
</ul>
<div id="nameWrapper"></div>
And after a couple of mouseover's over the menu items the nameWrapper div gets filled like so:
<div id="nameWrapper">
<div class="name">First</div>
<div class="name">Second</div>
</div>
The div.name elements is what actually gets shown when you hover over the menu items. The div.name elements are created when you hover over the menu item for the first time, in the folowing code section:
$(this).data("name", // associate the <div class="name"> element with the menu item that is currently hovered - $(this)
$('<div class="name"></div>') // create a div element
.text($(this).text()) // set text inside div to text of the menu item
.hide() // hide the div (it gets faded in later)
.appendTo("#nameWrapper")); // append the element to the element with id nameWrapper
Edit: See this jsFiddle code
I would bind all your menu items at once with a class name with an id attached to each one, like (I'm just guessing your HTML structure here):
<ul id="menu">
<li class="menu-item" id="account">Account</li>
<li class="menu-item" id="myposts">My Posts</li>
</ul>
And your javascript might be something like the below. Keep in mind that it's untested though, and I'm not sure what effect it would have on performance.
bindMouseOver();
$('.menu-item').mouseout(function(){
$('.menu-item').unbind('mouseover'); //disable all mouseovers while fadeOut is happening
$("#menu_name").fadeOut('slow', function(){
bindMouseOver(); //rebind the mouseover event after the fadeOut is completed
});
});
var bindMouseOver = function(){
$('.menu-item').mouseover(function(){
$("#menu_name").html($(this).html()); //use the menu item's innerHTML text, or something else if you prefer
$("#menu_name").fadeIn('slow');
});
};
Here is a JSFiddle I made that kind of simplifies all the JS into one hover listener: Example here
[EDIT] updated to auto load the menu title container...
Code to example:
CSS
#menu_name div{
position:absolute;
display:none;
}
.menu_link{
cursor:pointer;
}
HTML
<div id="menu_name"></div>
<br/>
<div id="menu_account" class="menu_link">link 1</div>
<div id="menu_myposts" class="menu_link">link 2</div>
JavaScript
(function() {
//auto-load the menu title container...
$(".menu_link").each(function(index, item) {
$('#menu_name').append('<div id="' + item.id + '-title">' + item.innerHTML + '</div>');
});
$(".menu_link").hover(
function() {
$('#' + this.id + '-title').fadeIn('medium');
}, function() {
$('#' + this.id + '-title').fadeOut('medium');
});
})();
Related
I'm running the following html:
<div class="container">
<div class="row">
<div class="col">
<div class="row">
<div class="col">
<div id="container1">
<div class="resizeDiv col-6"></div>
<div class="resizeDiv col-6"></div>
</div>
</div>
<div class="col">
<div id="container2"></div>
</div>
</div>
</div>
</div>
</div>
And this is the JS
var currentParent;
$(".resizeDiv").draggable({
revert: 'invalid',
containment: "#container2",
start: function(){
currentParent = $(this).parent().attr('id');
}
});
$('#container1, #container2').droppable({
accept:'.resizeDiv',
drop: function(event,ui) {
if (currentParent != $(this).attr('id')) {
$(ui.draggable).appendTo($(this)).removeAttr('style');
}
$(this).find("div").on("click", function(){
if($(this).hasClass("col-6")) {
$(this).removeClass("col-6").addClass("col");
} else {
$(this).removeClass("col").addClass("col-6");
}
});
}
});
When I drop one element and I click on it, its class changes from col-6 to col, however when I drop the second item, the toggle classes on the click only works on the second added item and not the first one added.
Here it is a codepen, try adding one item to the second container and the click on it and then drop the second item and try to click on them.
NOTE
Ideally I would like to auto size without the click
Your problem is this
$(this).find("div").on("click", function(){
if($(this).hasClass("col-6")) {
$(this).removeClass("col-6").addClass("col");
} else {
$(this).removeClass("col").addClass("col-6");
}
});
What this does is every time you drop an element it is going to go through ALL divs in that container. That means the ones you already set a click handler on, so when you drop a second item, the first div is going to get a second click handler. If you dropped a third it would get a third and so on.
So when you click the first one you are actually firing off two of these callbacks, and the class gets added in the first and removed in the second.
Since ui.draggable refers to the dragged element use that as a reference to add the click handler
$(ui.draggable).on("click",function(){
let $this = $(this);
if($this.hasClass("col-6")) {
$this.removeClass("col-6").addClass("col");
} else {
$this.removeClass("col").addClass("col-6");
}
//note instead of doing the if else and removeClass().addClass()
//calls you could just do toggleClass('col-6 col')
//it will toggle one off and the other on
$this.toggleClass('col-6 col');
});
If instead you want to get rid of the click handler and just want to add the class directly then do so on ui.draggable
$this = $(this);
$draggable = $(ui.draggable);
if (currentParent != $this.attr('id')) {
$draggable.appendTo($this).removeAttr('style').toggleClass('col-6 col');
}
Also note I am storing the jQuery objects. If you are going to use something like $(this) or $(ui.draggable) multiple times it is better to store it in a variable and use it instead of making multiple calls to jQuery()
The solution I found was to use:
e.stopImmediatePropagation();
Link to doc
Final js code
var currentParent;
$(".resizeDiv").draggable({
revert: 'invalid',
containment: "#container2",
start: function(){
currentParent = $(this).parent().attr('id');
}
});
$('#container1, #container2').droppable({
accept:'.resizeDiv',
drop: function(event,ui) {
if (currentParent != $(this).attr('id')) {
$(ui.draggable).appendTo($(this)).removeAttr('style');
}
$(this).find("div").on("click", function(e){
e.stopImmediatePropagation();
if($(this).hasClass("col-6")) {
$(this).css("background-color", "red");
$(this).removeClass("col-6").addClass("col");
} else {
$(this).css("background-color", "yellow");
$(this).removeClass("col").addClass("col-6");
}
});
}
});
NOTE
Yet I am still trying to auto size if el is dropped next to the other.
I have this HTML structure:
<div id="side-menu">
<ul>
<li><img src="img/once_sonra.png"></img></li>
<li><img src="img/online_destek.png"></img></li>
<li><img src="img/sizi_arayalim.png"></img></li>
</ul>
</div>
CSS:
#side-menu {
display:block;
z-index:20;
position:fixed;
right:0;
top:76px;
}
I want, when click my page show this items and after hide with animate effect but i dont know how can i do? Thanks.
Something like this:
$(document).ready(function() {
// hide the menu initially
$("#side-menu").hide();
$(document).click(function() {
// on click show and then hide menu with animation
$("#side-menu").slideDown().delay(500).slideUp();
});
});
Demo: http://jsfiddle.net/dhVzq/
If you don't like the slide effect jQuery gives you several other options.
You'll need to bind to the click event of the page:
jQuery(function($) {
var $sideMenu = $('#side-menu'),
itemClicked = false; // Use to determine whether an item was clicked
$sideMenu.hide();
// Catch clicks on the document
$(document.body).click(function(e) {
// Check if the menu is visible
if (!$sideMenu.is(':visible')) {
$sideMenu
.stop(true) // Cancel any animation from a previous click
.show(); // Show the menu
// Set a timer to hide the menu after 5 seconds if nothing was clicked
setTimeout(function() {
if (!itemClicked) {
$sideMenu.slideUp(); // Hide the menu with the slideUp effect
}
itemClicked = false; // Reset the flag for next time round
}, 5000);
}
});
// Catch clicks on menu items
$sideMenu.click(function(e) {
itemClicked = true;
});
});
The problem:
In the example provided below, I have a sidenav with options, you click to reveal a toggled div. If you click the third item in the menu "Dolar", you will see you get a dropdown with three options appear below the link.
This is great, but I want the dropdown to close when I click on the other links. I'm not sure how to achieve this.
jsFiddle:
http://jsfiddle.net/visualdecree/4A23Z/39/
jQuery:
Note: I know it might be messy, I'm still learning this.
$('.sn a, .sn-alt a').on('click',function(){ // Sidenav panel script
var panID = $("#" + $(this).data('panel') );
$("div[id*='sn-pan-']")
.stop()
.hide({width:'toggle'},400);
$(panID)
.css({'left' : '139px','overflow':'visible'})
.stop()
.animate
({ width: "toggle", opacity: "toggle"
}, { duration: "slow" });
$(".control-view").hide(); // Fadein menu close button
$(".control-view").not(":visible").stop().delay(400).fadeTo("fast", 0.33);
});
$('.sn, .sn-drop').click(function(e) {
$('ul.sidenav li').not(this).removeClass('active'); // Active class removal / add
$(this).stop(true, true).toggleClass("active");
});
$('.sn-alt').click(function(e) {
$('ul.additional li').not(this).removeClass('active'); // Active class removal / add
$(this).stop(true, true).toggleClass("active");
});
$(".control-view").hover( // Hover effect for menu close button
function () {
$(".control-view").stop().hide().fadeTo("fast", 1); // Hover in
},
function () {
$(".control-view").fadeTo("normal",0.33); // Fade back to previous set opacity
});
$('.control-view').click(function(e) {
$("div[id*='sn-pan-']")
.stop(true,true)
.hide({width:'toggle'}, 100);
$('ul.sidenav li').not(this).removeClass('active');
$(".control-view").stop().fadeOut("fast");
});
$(".additional").hide(); // Controls for the 'design' dropdown
$(".sn-drop").click(function(){
$(".additional").slideToggle(300);
var scrt_var = Math.random();
return false; //Prevent the browser jump to the link anchor
});
Just add this JQuery, when you click on other link in your sidebar, it will close your .additional
$(".sn").click(function(){
$(".additional").slideUp(300);
var scrt_var = Math.random();
return false; //Prevent the browser jump to the link anchor
});
If it's just the links in the left that you want to be the trigger to close the dropdown then you can do it simply with this:
$('.sn').click(function(){
$('.additional').slideUp();
})
I need hide tooltip on mouseout of link, BUT not if mouseover on tooltip (both have different parents)
For example: we can see it on Facebook when hover on names or avatars friends
I try this but every time i get FALSE
$('a').bind('mouseleave', function () {
var i = $('div.tooltip').is('hover');
if(i===true){
console.log('cursor over the tooltip, so dont hide');
}
else{
console.log('hide tooltip');
}
});
How i can check both condition?
Put both the link and the tool tip in the same parent:
<div id="parent">
link
<div id="tooltip">tooltip</div>
</div>
And then in the script you can just put the mouseleave function on the parent:
$("#parent a").mouseenter(function(){
$("#tooltip").css("display","block"); //or however you handle this
});
$("#parent").mouseleave(function(){
$("#tooltip").css("display","none");
});
If you can't change your markup, use a timed event and abort it when the mouse enter either element, like so:
var timer;
$("a, .tooltip").mouseleave(function() {
timer = setTimeout(doSomething, 10);
}).mouseenter(function() {
clearTimeout(timer);
});
function doSomething() {
console.log('hide tooltip');
}
Here's a FIDDLE
I setup a jquery dropdown menu that works perfect. It drops down when a user rolls over a link. The problem is that when the user rolls over the content area of the drop down menu, it slides back up. I need to set up the code so that the slidedown box remains in the down position while the user's cursor is still over it.
Here is my HTML:
<ul id="tabnav">
<li class="tab2">My Leases</li>
</ul>
<div id="leases">
<!-- slide down content here -->
</div>
JS Trigger:
<script type="text/javascript">
$(document).ready(function(){
$(".btn-slide").hover(function(){
$("#leases").slideToggle("medium");
$(this).toggleClass("active");
return false;
});
});
</script>
Any ideas?
EDIT: Here is a link to page in question: http://designvillain.com/testbed/600/601.html
I'm not sure if this is what you want, but I'll just drop it here. It waits 500ms before sliding up #leases, and only when appropriate
var isMousedOver;
var hideDropdown = function(a) {
setTimeout( function() {
if (isMousedOver) return;
$("#leases").slideUp("medium");
$(a).removeClass("active");
}, 500);
}
$(".btn-slide").hover(
function(){
$("#leases").stop(true,true).slideDown("medium");
isMousedOver = true;
$(".btn-slide").removeClass("active");
$(this).addClass("active");
var that = this;
$("#leases").data("mouseoutfn", function() { hideDropdown(that) });
},
function(){
isMousedOver = false;
hideDropdown(this);
}
);
$("#leases").hover(
function() {
isMousedOver = true;
},
function() {
isMousedOver = false;
$(this).data("mouseoutfn")();
}
);
Here's a demo: http://jsfiddle.net/mMRZc/
The .hover() binds two events, mouseenter and mouseleave.
I would instead go granular and use the mouseenter() on the .btn-slide and the mouseleave() on the .leases
$(function()
{
$(".btn-slide").mouseenter(function(){
$("#leases").slideToggle("medium");
$(this).toggleClass("active");
});
$("#leases").mouseleave(function(){
$(".btn-slide").toggleClass("active");
$(this).slideToggle("medium");
});
});
EDIT: Note, if the mouse never enters the #leases div, it will not get the mouseleave, and you may need to consider that.
EDIT2: fix my bad finger typing of funciton to function
I assume the div is hidden on page load and you want it to show when you hover over the link? Change toggle to down...
$(document).ready(function(){
$("#leases").hide();
$(".btn-slide").hover(function(){
$("#leases").slideDown("medium");
$(this).toggleClass("active");
return false;
});
});
Does it need to slide back up sometime?