When I want to toggle off a component I can use
$("#donkey").toggle(false);
and when I need it to be toggled during a certain time period I can use
$("#emailInvalid").toggle(700);
but now I'd like to combine those two. I want to ensure that the component is being toggled off (not only toggled back and forth) and I want to specify a duration of the process.
According to the jQuery API, I'm supposed to be able to specify an object with options, too. However, the following
$("#donkey").toggle({ duration: 700, display: false });
only toggles the donkey back and forth (during said time, though), whereas I'd like it to be toggled to invisibility. When I reviewed the options, I noticed that there's none that addresses display, so I fear that the above is treated by jQuery equivalently with
$("#donkey").toggle({ duration: 700, biteMe: "in the donkey" });
How can I make sure that the toggler is hiding the component (equivalent with the first line of code above) and that I can control the time for the process to be done (equivalent to the second line of code above)?
Apply toggle only when visible:
$('#donkey:visible').toggle(500);
Alternatively
var element=$('#donkey');
if(element.css('display') !== 'none'){
element.toggle(500);
}
Short answer - you can't.
Your options are to build something custom and carry out the logic in custom code. Alernatively, you might want to toggle between differen classes that have the look that you like. Check out toggleAss() for details.
For completeness I also give you a link to animate() as suggested by #DavidThomas, although I haven't used that one very much.
I think this is what you want -- if the element (#donkey) is visible it gets hidden, if it's hidden nothing happens.
$( '#button' ).click( function(){
if( $( '#donkey' ).css( 'display' ) === 'block' ) {
$("#donkey").toggle( 700 );
}
});
Codepen: http://s.codepen.io/SteveClason/debug/RRwpBd
This small plugin would allow you to combine the two:
(function ( $ ) {
$.fn.myToggle = function(show, options) {
return this.each(function() {
if ($(this).is(":hidden") ? show : !show) $(this).toggle(options);
});
};
}( jQuery ));
Simple example:
$("#donkey").myToggle(false, 700);
Related
I have a problem combining a toggle function with another function involving a change of the css 'position' attribute.
I have a starting page with a menu at the top and columns of pictures beneath it.
Some columns are higher than the window and they can be scrolled down together with the menu (both in position: absolute).
When you click on an item from the menu however, the columns hide and another set of pictures appears (triggered by a click+toggle function). This new set is horizontal and this time I need the menu not to scroll with it.
So what I'm trying to do is to change the position of the menu from absolute to fixed, according to the state of the toggle.
At first I tried including an if/else statement inside my click function but the 'else' part never worked. Now I'm trying to use the callback property of the toggle, but I can't seem to make it work either... The best I can do is get the menu's position switched to fixed, but then it stays that way.
one of the uneffective try-outs:
function fixMenu(){
('.menu').css('position','fixed')};
function freeMenu(){
('.menu').css('position','absolute')};
$("#menu_item").click(function(){
$("#horizontal_set").toggle(1000,fixMenu);
$(".column").toggle(1000,freeMenu);
});
I have no idea whether my problem is in the syntax or if I need a completely different solution. Please enlighten me :-)
Many thanks
PS: I made two little sketches but it appears I'm not allowed to share them :-( I hope my problem remains understandable.
Try this:
It checks via an if-statement if horizontal_set or column is visible. and invokes the correct function as a result.
function fixMenu(){
$('.menu').css('position','fixed')};
function freeMenu(){
$('.menu').css('position','absolute')};
$("#menu_item").click(function(){
$("#horizontal_set").toggle(1000);
$(".column").toggle(1000);
if ( $( "#horizontal_set" ).is( ":visible" ) && $( ".column" ).is( ":hidden" ) )
{
fixMenu();
}
else
{
freeMenu();
}
});
You forgot jQuery selectors in the function. Try:
function fixMenu() {
$('.menu').css('position','absolute');
}
I wanted to create side tab slide outs for two subdivisions of our company on the new version of the website I'm working on. After a lot of research, I decided to make it relatively simple (or so I thought).
I created a div (#CMTabWrap, 245px) that wrapped around two other divs: #CMContent (200px) and #BNOCM_tab (45px). I set the margin for #CMTabWrap to -200px (the width of #CMContent), leaving only the tab showing. The HTML and CSS are working fine.
Beneath the divs in my HTML, I put the code below. On click, it should test the class of the object and move it in or out (as appropriate) by the width of the content, either making the whole kit and kaboodle visible or reducing it to just the tab.
I want to say that I ran the code through JSLint, and read several questions here along the same lines. I applied some of the fixes, but still nothing is happening. I have a feeling it's something obvious -- I'm not quite intermediate with JS and slightly more than a noob. Any help appreciated.
<script type="text/javascript">
/*global $, jQuery, alert*/
$(function(){
$("#BNOCM_tab").click(function () {
$('#BNOCM_tab').addClass('in');
var contentWidth = $('#CMContent').width();
if ($(this).is('.out')) {
$(this).removeClass('out').addClass('in');
$("#CMTabWrap").animate(
{"left": '+=' + contentWidth},
"slow"
);
}
if ($(this).is('.in')) {
$(this).removeClass('in').addClass('out');
$("#CMTabWrap").animate(
{"right": '-=' + contentWidth},
"slow"
);
});
});
</script>
Inside your click-function this refers to the clicked element, so $(this) and $("#BNOCM_tab") is always the same. Also your second if should be an else, because now you just swap the classes from "in" to out as #wwwmarty pointed to. So yours (inside $(document).ready) could look like this:
<div id="BNOCM_tab" class="out"></div> // add class 'out to the tab
var $Wrap = $("#CMTabWrap"), // create a jQuery object only once, store it
$Tab = $("#BNOCM_tab");
$Tab.click(function () {
var contentWidth = $('#CMContent').width();
// use .hasClass() for class check, note there's no dot in the name
if ($Tab.hasClass('out')) {
$Tab.removeClass('out').addClass('in');
$Wrap.animate({left: '+=' + contentWidth}, "slow");
} else {
$Tab.removeClass('in').addClass('out');
$Wrap.animate({left: '-=' + contentWidth}, "slow");
};
});
If that won't work, add the relevant part of your html to your question or/and make a fiddle and post what exactly went wrong.
I have this code that uses an API supplied by a plugin (wordpress)
$('#my_overlay').click(function(){
uberMenu_close('#menu-item-1459');
return false;
});
What it does is it closes the sub-menu associated with #menu-item-1459 when the #my_overlay is clicked.
However it is really abrupt since there is no animation.
How can I add an animation effect to the code above?
Here is the JS that defines the API of "uberMenu_close('ID')" (just in case I have to actually edit this instead of my code above, and to give you a better picture)
function uberMenu_close( id ){
var $uber = $ujq('#megaMenu').data( 'uberMenu' );
$uber.close( id );
}
Thanks
I'd try changing the second function you posted to add fadeOut() functionality. Something like this.
function uberMenu_close( id ){
var $uber = $ujq('#megaMenu').data( 'uberMenu' );
//adjust how quickly you want it to fade, 1000 is one second
$(id).fadeOut(1000,function(){
$uber.close( id );
});
}
I have a menu composed of three options.
Clicking on one causes a container div to "FadeInDown".
Then, its contents "FadeIn".
Clicking on another menu item or anywhere else on the page causes the
contents to "FadeOut" then container div to "FadeOutUp".
Here is the fiddle that I have been testing jsfiddle
$(document).ready(function() {
$('.container').each(function() {
animationHover(this,'.fadeInDown');
});
});
I'm not very familiar with jQuery and have been trying to use animate-css to get me along. Thanks for any help and tips in advance and welcome coding criticism :)
My answer is mainly based on JQuery and its animate function (http://api.jquery.com/animate/) . Here is the fiddle :
http://jsfiddle.net/awmat/7/
I use JavaScript objects like fadeInDown to animate the container.
var fadeInDown = {
opacity:1,
top: "50px"
};
And i use the complete callback function of animate to make the content appear after the container.
To manage several div (one for each menu item), I use id as selectors, but since the "click and display" function remains the same, I used a "builder" : (this uses a closure, so if you're not familiar with JavaScript, you may have to read several times to understand what is going on)
var menuClickCallbackBuilder = function(menuItem){
var container = $('#container' + menuItem);
var content = container.find('.content');
var showContent = function(){
content.animate({opacity:1},{duration:1000});
};
return function() {
var activeContainer = $('.active');
var hideContainer = function(){
activeContainer.animate(fadeOutUp,1000);
};
activeContainer.find('.content').animate({opacity:0},{duration: 1000, complete : hideContainer});
activeContainer.removeClass("active");
if(activeContainer[0] != container[0])
{
var timeout = activeContainer[0] ? 2000 : 0 ;
setTimeout(function(){
container.animate(fadeInDown,{duration : 1000, complete :showContent});
},timeout);
container.addClass("active");
}
}
};
This way, when you add the add the click callbacks, you can just do :
$(document).ready(function(){
// note that menuClickCallbackBuilder(1) returns a function
// again if you're not familiar with JS, you may have to re-read menuClickCallbackBuilder
$('#menuLink1').on('click', menuClickCallbackBuilder(1));
$('#menuLink2').on('click', menuClickCallbackBuilder(2));
$('#menuLink3').on('click', menuClickCallbackBuilder(3));
});
Some improvements you can bring to this :
Factor the durations into a variable (e.g animationDurationInSeconds) so that if you want to change the speed of the animation, you only have 1 thing to change. (#Huangism: and right after you did that, make animation faster so that it gets more dynamic)
(From #Huangism) : stop it from going crazy when people cicks on the menu 10 times really fast
Actually, I think you don't need 3 different containers, you could do it with just one container (though I don't know if it would be considered an improvement)
There is probably a way to use CSS classes instead of fadeInDown and fadeOutUp JS objects. That would be cleaner, I think you should keep styles in CSS as much as you can.
There is no need for different IDs for menu items, you could do the exact same thing with a loop.
Whatever your imagination wants to add
I wrote a little script that observes clicks and blinds up/down according to the 'display' property, and also added a queue-to-end parameter to the blindUp in order to avoid even more serious display issues. This is obviously not the way to implement this, as display bugs appear if click events are invoked in the middle of the effect.. This is the code:
<script type="text/javascript">
$$('#leftnav_container #modules h2').each(function(El){
El.observe('click',function(){
container = this.next('div');
display = container.getStyle('display');
if(display == 'none'){
container.blindDown({duration: 0.3});
}else{
container.blindUp({duration: 0.3, queue: 'end'});
}
})
});
</script>
Again, the problem is that I rely on 'display'. What is the proper way to this?
This should simplify it
$$('#leftnav_container #modules h2').invoke('observe','click',function(){
container = this.next('div');
Effect.toggle(container , 'blind', { duration: 0.3 });
});
Firstly if you are only running one method on all elements in the array returned from $$() then you can use the PrototypeJS method invoke().
http://api.prototypejs.org/language/Enumerable/prototype/invoke/
Then Effect.toggle() will check if the element is visible and do the appropriate up/down effect.
Try this out and let me know if it works for you.