In a picture gallery I try to make all pictures not hovered greyscale:
$('.featured_product_item').mouseover(function() {
$('.featured_product_item').not(this).addClass('greyscale',200);
});
$('.featured_product_item').mouseout(function() {
$('.featured_product_item').removeClass('greyscale',200);
});
However, it is not smooth if you move your mouse to another item before the first animation has finished... how could you achieve that in a better way?
You should try .mouseenter() and .mouseleave().
http://api.jquery.com/mouseenter/
http://api.jquery.com/mouseleave/
The mouseenter event will only fire when the mouse changes from being outside of the element to inside the element. The opposite is true for mouseleave.
This way you should not see the stuttering behavior as seen with mouseover because every time the mouse shifts and you are over the element, the event will fire.
Something to the effect of this using stop
$(document).ready(function() {
$(".featured_product_item").mouseover(function () {
$('.featured_product_item').not(this).stop(true,true).addClass("selected", 1000);
});
$(".featured_product_item").mouseout(function () {
$('.featured_product_item').stop(true,true).removeClass("selected",1000);
});
});
Please check the jQuery Manual for stop
Here is the JSFiddle for this
NOTE
Im not sure you are using addClass and removeClass correctly. I have not found any reference in the manual of using an animation time for the second param. From the manual:
.addClass( function(index, currentClass) )
function(index, currentClass) A function returning one or more space-separated class names to be added to the existing class name(s). Receives the index position of the element in the set and the existing class name(s) as arguments. Within the function, this refers to the current element in the set.
UPDATE
I had some code in the wrong place and missed the extra params for stop. Please check the code above and the new jsfiddle.
Related
$('button').click(function() {
$('.img-container').prepend('<img src="images/image.jpg">')
});
I have a one page design and a gallery section that becomes visible on click.
I do this by prepending the imgs. Here you can see how I add 1 image. The issue is that the more you click the more elements it creates.
Is there any way to make it create the element just once? Then somehow stop prepending.
If you handler is as simple as given then you can use .one() to register the handler so that the event handler will get executed only once
$('button').one('click', function() {
$('.img-container').prepend('<img src="images/image.jpg">')
});
Demo: Fiddle
Another option is to check whether an image exists
$('.img-container').not(':has(.someimage)').prepend('<img class="someimage" src="images/image.jpg">')
Demo: Fiddle
I'm creating a site using Bootstrap 3, and also using a script that makes the dropdown-menu appear on hover using the .hover() function. I'm trying to prevent this on small devices by using enquire.js. I'm trying to unbind the .hover() event on the element using this code:
$('.dropdown').unbind('mouseenter mouseleave');
This unbinds the .hover of that script but apparently it also removes the .click() event(or whatever bootstrap uses), and now when I hover or click on the element, nothing happens.
So I just want to how I can remove the .hover() on that element, that is originating from that script, but not change anything else.
Would really appreciate any help.
Thanks!
Edit: Here is how I'm calling the handlers for the hover functions:
$('.dropdown').hover(handlerIn, handlerOut);
function handlerIn(){
// mouseenter code
}
function hideMenu() {
// mouseleave code
}
I'm trying to unbind them with this code.
$('.dropdown').unbind('mouseenter', showMenu);
$('.dropdown').unbind('mouseleave', hideMenu);
But its not working.
Please help!
**Edit2: ** Based on the answer of Tieson T.:
function dropdownOnHover(){
if (window.matchMedia("(min-width: 800px)").matches) {
/* the view port is at least 800 pixels wide */
$('.dropdown').hover(handlerIn, handlerOut);
function handlerIn(){
// mouseenter code
}
function hideMenu() {
// mouseleave code
}
}
}
$(window).load(function() {
dropdownOnHover();
});
$(window).resize(function() {
dropdownOnHover();
});
The code that Tieson T. provided worked the best; however, when I resize the window, until I reach the breakpoint from any direction, the effect doesn't change. That is, if the window is loaded above 800px, the hover effect will be there, but if I make the window smaller it still remains. I tried to invoke the functions with window.load and window.resize but it is still the same.
Edit 3: I'm actually trying to create Bootstrap dropdown on hover instead of click. Here is the updated jsFiddle: http://jsfiddle.net/CR2Lw/2/
Please note: In the jsFiddle example, I could use css :hover property and set the dropdow-menu to display:block. But because the way I need to style the dropdown, there needs to be some space between the link and the dropdown (it is a must), and so I have to find a javascript solution. or a very tricky css solution, in which the there is abot 50px space between the link and the dropdown, when when the user has hovered over the link and the dropdown has appeared, the dropdown shouldn't disappear when the user tries to reach it. Hope it makes sense and thanks.
Edit 4 - First possible solution: http://jsfiddle.net/g9JJk/6/
Might be easier to selectively apply the hover, rather than try to remove it later. You can use window.matchMedia and only apply your script if the browser has a screen size that implies a desktop browser (or a largish tablet):
if (window.matchMedia("(min-width: 800px)").matches) {
/* the view port is at least 800 pixels wide */
$('.dropdown').on({
mouseenter: function () {
//stuff to do on mouse enter
},
mouseleave: function () {
//stuff to do on mouse leave
}
});
}
else{
$('.dropdown').off('mouseenter, mouseleave');
}
Since it's not 100% supported, you'd want to add a polyfill for those browsers without native support: https://github.com/paulirish/matchMedia.js/
If you're using Moderizr, that polyfill is included in that library already, so you're good-to-go.
I still don't understand how you intend to "dismiss" the dropdown-menu once it is displayed upon mousing over the dropdown element partly because there's not enough code in your question, but that's sort of irrelevant to this answer.
I think a much easier way to approach the mousenter event handling portion is not by using off()/on() to unbind/bind events at a specific breakpoints, but rather to do just do a simple check when the event is triggered. In other words, something like this:
$('.dropdown').on('mouseenter', function() {
if($('.navbar-toggle').css('display') == 'none') {
$(this).children('.dropdown-menu').show();
};
});
$('.dropdown-menu').on('click', function() {
$(this).hide();
});
Here's a working fiddle: http://jsfiddle.net/jme11/g9JJk/
Basically, in the mouseenter event I'm checking if the menu toggle is displayed, but you can check window.width() at that point instead if you prefer. In my mind, the toggle element's display value is easier to follow and it also ensures that if you change your media query breakpoints for the "collapsed" menu, the code will remain in sync without having to update the hardcoded values (e.g. 768px).
The on click to dismiss the menu doesn't need a check, as it has no detrimental effects that I can see when triggered on the "collapsed" menu dropdown.
I still don't like this from a UX perspective. I would much rather have to click to open a menu than click to close a menu that's being opened on a hover event, but maybe you have some magic plan for some other way of triggering the hide method. Maybe you are planning to register a mousemove event that checks if the mouse is anywhere within the bounds of the .dropdown + 50px + .dropdown-menu or something like that... I would really like to know how you intend to do this (curiosity is sort of killing me). Maybe you can update your code to show the final result.
EDIT: Thanks for posting your solution!
I have created a simple drop-down menu with JQuery, following a tutorial. LINK :
http://wabism.com/development/jquerydropdown/
Its jQuery code is this:
$('body').ready(function() {
// Add the 'hover' event listener to our drop down class
$('.dropdown').hover(function() {
// When the event is triggered, grab the current element 'this' and
// find it's children '.sub_navigation' and display/hide them
$(this).find('.sub_navigation').slideToggle();
});
});
Drop-down works fine with 1 error. If you rollover and out a menu item 3 or 4 times quickly, it does all the 3 or 4 slidetoggle() 's. How can I overcome this problem ?
Use .stop() method before animation.
As you described, animations in jQuery would be queued and all of them would be executed, unless you explicitly specify that you want any pending animation to stop. You would do this using .stop() function. In your case you should write:
$(this)
.find('.sub_navigation')
.stop()
.slideToggle();
It has some parameters too which would give you more granular level of control. See here.
I'm trying to create a function that disables voting button after an Ajax POST success. The voting buttons are enabled until POST completes, and then are fixed with 'disabled' styling and are in-clickable. I'm trying to use jQuery .not() to disable starting the function from clicked buttons (with the class 'disabled') but I'm not having much luck. Here's a fiddle of my function so you can see my problem, I'm not sure what I'm missing but I'm hoping someone can help me find my error, it's frustrating me : )
jQuery Code:
$("a.votebutton").not(".disabled").each(function(index) {
var el = $(this);
$(this).click(function() {
el.addClass("active disabled").unbind("click");
el.siblings().addClass("disabled");
});
});
The problem is that your code:
$("a.votebutton").not(".disabled")
selects all of the links that are not disabled at the time that line of code runs, and then you loop through assigning click handlers. These click handlers remain bound to those links even if they happen to be given the "disabled" class at a later time - so when you add the "disabled" class to the clicked element's siblings those siblings still have a working click handler. If you unbind the click from the siblings that should fix it:
// change
el.siblings().addClass("disabled");
// to be
el.siblings().addClass("disabled").unbind("click");
Note that you don't need the .each():
$("a.votebutton").not(".disabled").click(function() {
$(this).addClass("active disabled").unbind("click")
.siblings().addClass("disabled").unbind("click");
});
Another way to do it would be to use delegated event handling:
$("div.panel").on("click", "a.votebutton:not(.disabled)", function() {
$(this).addClass("active disabled")
.siblings().addClass("disabled");
});
That way the clicks are only handled once they bubble up to the containing div ("div.panel"), at which time your click handler is only run if the event's source element matches the selector that is the second parameter to .on().
Updated demo: http://jsfiddle.net/RSezp/2/
I would like to know if there is a jQuery event that I can use to determine when a particular DIV's top property has changed.
For instance, I have invisible content above a DIV. When that content becomes visible, the DIV is shifted down. I would like to capture that event and then use the offset() function to get the X/Y coordinates.
The easy answer is that there are no events in the DOM for detecting layout updates.
You have a couple options the way I see it:
Poll, nasty but it may work depending on your update frequency requirements.
Tap into whatever event causes the invisible DIV to change size and do whatever you need to do in that handler
I shall correct myself.
I took a look at the DOM and noticed the DOMAttrModified event and found this JQuery Plug-In that you might be able to leverage to do what you want.
As the article mentions, it works great in IE and Firefox but seems to have problems in WebKit.
I thiiink you should be able to do:
$(document).ready( function (){
$("#mydiv").bind("movestart", function (){ ...remember start position... });
$("#mydiv").bind("moveend", function (){ ...calculate offsets etc... });
});
$("#someId").resize(function () {
// your code
});