jQuery fadeOut callback function not being called - javascript

I am trying to swap divs by fading them in and out when another div is clicked. The only problem is: first the callback function wouldn't get called, so I took it out completely and the divs are acting funny now. Meaning when I click one of the divs the corresponding div that should fadeIn doesn't and the div that should have fadedOut did not.
HTML:
<ul id="tour">
<li id="pitch_link" class="selected">
<h1>Pitch</h1>
<p>Pitch a ball.</p>
</li>
<li id="publish_link">
<h1>Publish</h1>
<p>Publish the spin.</p>
</li>
<div id="pitch">
<ul>
<li><h2>pitch Stuff</h2></li>
<li><h2>Graphics</h2></li>
</ul>
</div>
<div id="publish">
<ul>
<li><h2>publish Stuff</h2></li>
<li><h2>Graphics</h2></li>
</ul>
</div>
jQuery w/out callback:
$("#tour li").click( function(event) {
if( !$(this).is( ".selected" ) ) {
// find the link that was previously selected and fade it out
var prevSelectedLink = $(".selected").attr( 'id' );
prevSelectedID = "#" + prevSelectedLink.substr( 0, prevSelectedLink.length-5 );
// fade the previously selected div out
$(prevSelectedID).fadeOut( "fast" );
// Deselect the previously selected link (remove selected class)
$(prevSelectedLink).removeClass( "selected" );
// Select the new Link
$(this).addClass("selected");
// Fade the new div content in
var linkID = $(this).attr( 'id' ); // linkID = pitch_link
contentID = "#" + linkID.substr( 0, linkID.length-5 ); // contentID = #pitch
$(contentID).fadeIn( "slow" );
}
});
jQuery w/ callback:
if( !$(this).is( ".selected" ) ) {
// find the link that was previously selected and fade it out
var prevSelectedLink = $(".selected").attr( 'id' );
prevSelectedID = "#" + prevSelectedLink.substr( 0, prevSelectedLink.length-5 );
// fade the previously selected div out
$(prevSelectedID).fadeOut( "fast" , function() {
// Deselect the previously selected link (remove selected class)
$(prevSelectedLink).removeClass( "selected" );
// Select the new Link
$(this).addClass("selected");
// Fade the new div content in
var linkID = $(this).attr( 'id' ); // linkID = pitch_link
contentID = "#" + linkID.substr( 0, linkID.length-5 ); // contentID = #pitch
$(contentID).fadeIn( "slow" );
});
}
});

Without the CSS, I can't really tell what the problem is but the code can be cleaned up like so:
$('#tour li').click(function(){
if( !$(this).hasClass('selected') ){
//Get the ID of the DIV you want to show
var div_id = $(this).attr( 'id' ).replace('_link','');
$('#tour li').removeClass('selected');
$(this).addClass('selected');
$('div').fadeOut("fast", function(){
$('#'+div_id).fadeIn("fast");
});
}else{
return false;
}
});
I haven't tested this but what it does is if the link is not selected, it gets the ID of the div using the link ID, removes the 'selected' class from all other links and adds the 'selected' class to the li clicked. All div's are then faded out and finally the required div is faded In.
You can also use the .not() operator to prevent the fadeOut() for the div with 'div_id'.

This is the code I ended up with that worked thanks a lot to Sagar.
$("#tour li").click( function(event) {
// make sure we are not already selected
if( !$(this).hasClass( "selected" ) ) {
// find the tab link that was previously selected and the corresponding div content
var prevTab = '#' + $(".selected").attr( 'id' ); // prevTab = #pitch_link
prevTabCont = prevTab.replace( '_link', '' ); // prevTabCont = #pitch
// Deselect the previously selected tab link (remove selected class)
$(prevTab).removeClass( "selected" );
// Find the currently selected tab and its corresponding div content
var selectedTab = '#' + $(this).attr( 'id' ); // selectedTab = #publish_link
selectedTabCont = selectedTab.replace( '_link', '' ); // selectedTabCont = #publish
// Make the tab link selected
$(this).addClass("selected"); // this -> #publish_link
// fade the previously selected div out
$(prevTabCont).fadeOut( "slow", function() {
$(selectedTabCont).fadeIn( "slow" );
});
}
});

Related

Hide inactive or disabled elements in the list

I am struggling with the following issue.
On my wordpress website I have a dropdown filter lists
1. VEHICLE TYPE (convertible, coupe etc.)
2. MAKE (Mercedes, BMW etc.)
3. MODEL (CLK, X5 etc.)
so, when selecting the VEHICLE TYPE from the FIRST list,
appears the corresponding MAKES in the SECOND one for the selected item,
and in the THIRD list appears then the model coresponding the MAKE (Mercedes-CLK, BMW-X5).
Now the thing is, that the Makes or Models that are disabled or inactive won't show on DESKTOP but on MOBILE they appear although still inactive.
1ST question: How can I hide the disabled elements from the list on MOBILE?
2ND question: Can I disable the MAKES and MODELS unless chosen VEHICLE TYPE?
Here below you can see the backend code for the list.
var car_dealer = {};
(function ($) {
/*
* Cleans the form URL from empty parameters on submit
*/
$('.vehicle-search-form').submit( function() {
$(this).find( "input[type='number']" ).filter(function(){
return ($(this).attr( 'min' ) == $(this).attr( 'value' ) || $(this).attr( 'max' ) == $(this).attr( 'value' ));
}).attr( 'disabled', 'disabled' );
$(this).find( "input[type='search']" ).filter(function(){
return ! $(this).val();
}).attr( 'disabled', 'disabled' );
$(this).find( "select" ).filter(function(){
return ! ( $(this).val() && $(this).val() != '-1');
}).attr( 'disabled', 'disabled' );
})
/*
* Disables all models that do not fit the selected make
*/
$('#car_dealer_field_vehicle_type').on('change',function(){
var makeName = $(this).find( 'option:selected' ).attr( 'data-type' );
$('#car_dealer_field_make option')
// first, disable all options
.attr( 'disabled', 'disabled' )
// activate the corresponding models
.filter( '[data-type="' + $.trim( makeName ) + '"], [value="-1"]' ).removeAttr( 'disabled' )
// remove previous value
.parent().val( -1 );
});
$('#car_dealer_field_make').on('change',function(){
var makeName = $(this).find( 'option:selected' ).attr( 'data-make' );
$('#car_dealer_field_model option')
// first, disable all options
.attr( 'disabled', 'disabled' )
// activate the corresponding models
.filter( '[data-make="' + $.trim( makeName ) + '"], [value="-1"]' ).removeAttr( 'disabled' )
// remove previous value
.parent().val( -1 );
});
}(jQuery));
I am grateful and looking forward to hear from you soon !
I know this is old but here we go.
Here is the event handler - reworked a slight bit to only have one selection event handler.
Now as far as the hiding and showing, simply do that to the appropriate list of options filtered as you indicate to hide the disabled ones.
Use prop("disabled",true) to disable, not an attribute.
I left out how to re-enable and show when that is needed but that is a simple
.find('option').prop('disabled",false).show();
(function($) {
/* * Cleans the form URL from empty parameters on submit */
$('.vehicle-search-form').on('submit', function(e) {
// might want to prevent the submit?
e.preventDefault();
$(this).find("input[type='number']")
.filter(function() {
return ($(this).attr('min') == $(this).attr('value') ||
$(this).attr('max') == $(this).attr('value'));
}).prop('disabled', true);
$(this).find("input[type='search']")
.filter(function() {
return !$(this).val();
}).prop('disabled', true);
$(this).find("select").filter(function() {
return !($(this).val() && $(this).val() != '-1');
}).prop('disabled', true);
});
// here we can create one custom event handler to do the disable
$('#car_dealer_field_make')
.on('change', function() {
var makeName = $(this).find('option:selected').data('make');
$(this).trigger("custom-set-me", [makeName, "fun"]);
});
$('#car_dealer_field_vehicle_type')
.on('change', function() {
let makeName = $(this).find('option:selected').data('type');
$(this).trigger("custom-set-me", [makeName, "fun"]);
})
// add the other one to the handler
.add("#car_dealer_field_make")
/*
* Disables all that do not fit the selected
*/
.on('custom-set-me', function(event, compareTo, param2) {) {
let iamMe = $(this);
let options = iamMe.find('option');
options
.prop('disabled', true)
// activate the corresponding models
.filter(function() {
return $(this).data('type') == $.trim(compareTo);
}).val(-1).prop('disabled', false);
// remove previous value
iamMe.val(-1);
options.filter(':diabled').hide();
});
}(jQuery));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Change colour of elements previously clicked

I have a list of elements that I want to change color after the user has click a button (then clicked a different one). I know to change the button colour on click I would use onclick, but how would I change the colour of the button AFTER I've clicked?
For example, the user clicks Titanic. Nothing happens. Then the user clicks Titanic7, Titanic changes colours and remains that colour. Then the user clicks Titanic9. Titanic and Titanic7 both have the "visited" colour.
See JSFiddle here
If I understand you correctly, I would do something like this:
http://jsfiddle.net/KHwcU/
$('.song').click(function(e) {
e.preventDefault();
$('.selectnext').css('background-color', 'blue').removeClass('selectnext');
$(this).addClass('selectnext');
});
Seeing that you're already using data-, I would do something like the following:
$(function() {
var currentButton;
$('a.song').on('click',function() {
if(currentButton === this) return;
currentButton = this;
$('a.song').each(function() {
if($(this).data('visited') == 'true' && !$(this).hasClass('visited'))
$(this).addClass('visited');
});
$(this).data('visited','true');
});
});
have a data-visited which keeps track of which button has been clicked
everytime a button is clicked, check if it's the same one that was clicked previously. if not, change the background for the previously clicked button, and set the current button as visited.
example fiddle: http://jsfiddle.net/9eJPD/
$(function(){
$( "a" ).click(function() {
$( this ).toggleClass( "color" );
});
});
css
.color{
background: yellow;
}
or double click
$(function(){
$( "a" ).each(function() {
var count = 0;
$( "a" ).click(function() {
count++;
//$( this ).text( "clicks: " + count );
$( this ).toggleClass( "color", count % 3 === 0 );
});
});
});

dotimeout not working properly

I am trying to use the dotimeout plugin to create a delay for the effect of showing a sub-nav when hovering over the top nav. The plug in seems to work well when the active class is added to the first li but when added to subsequent li's, it stops showing the hidden ul for this above the active li.
Here's my script:
$(function(){
$('ul.main-nav').each(function(){
var nav = $(this);
nav
.mouseover(function(e){
nav.doTimeout( 'main-nav', 500, over, e.target );
}).mouseout(function(){
nav.doTimeout( 'main-nav', 500, out );
});
function over( elem ) {
var parent = $(elem).closest( 'li.main-nav' );
out( parent );
parent.children( 'a' ).addClass( 'hover' );
parent.children( 'ul:hidden' ).slideDown( 'fast' );
};
function out( elem ) {
var parents = elem
? $(elem).closest( 'li.main-nav' ).siblings()
: nav.children();
if ( nav.is( '.main-nav-horizontal' ) ) {
parents = parents.not( '.active' );
}
parents.children( 'a' ).removeClass( 'hover' );
parents.children( 'ul' ).hide();
};
});
});
Here's my jsfiddle
I can see people are using this plugin so this issue seems like it should be easily solved but everything as far as I can see should work properly.
Change your out function to this.
function out( elem ) {
var parents;
if (elem) {
parents = $(elem).closest( 'li.main-nav' ).siblings();
}
else {
parents = nav.children();
showthisone = parents.filter( '.active' );
parents = parents.not( '.active' );
}
parents.children( 'a' ).removeClass( 'hover' );
parents.children( 'ul' ).hide();
if (!elem) {
showthisone.children( 'a' ).addClass('hover');
showthisone.children( 'ul' ).show();
}
};

unwrap list items in jquery based on controller value

I have two side menus. Each menu has subitems as list items under unordered list, like
- FIRST MENU
- Link one
- Link two
- SECOND MENU
- Link three
- Link four
When page loads I want to open one menu and other menu list items should stayed unwrapped
like
- FIRST MENU
- Link one
- Link two
- SECOND MENU
I have working example with FIRST MENU unwrapped here but I do need example with unwrapped SECOND MENU so I can change it to dynamic value sent from my controller.
var unwrapped_menu = $data_sent_from_controller;
if data_sent_from_controller == "SECOND MENU"
then unwrapped second menu.
Changed this example here to hardcoded SECOND MENU unwrapped would be perfect. Nothing more.
If you need more info please ask.
If the dynamic value sent from the controller is the index (starting from 0) of the menu to be opened then:
JSFIDDLE
dynamic_value_from_controller = 1;
$(document).ready(function() {
$.easing.def = "easeOutBounce";
var menus = $( 'div.menu ul li.submenu' ),
current_submenu = null;
menus.next().hide();
menus.each( function(i){
var dropdown = $( this ).next(),
title = $( 'a.title', this );
title.click( function(e){
if ( current_submenu !== null && current_submenu != dropdown )
{
current_submenu.slideUp( 'slow' );
}
current_submenu = dropdown;
dropdown.stop(false, true).slideToggle('slow');
e.preventDefault();
} );
if ( i == dynamic_value_from_controller )
title.click();
});
});
If the dynamic value is the text of the title then:
JSFIDDLE
dynamic_value_from_controller = 'SECOND MENU';
$(document).ready(function() {
$.easing.def = "easeOutBounce";
var menus = $( 'div.menu ul li.submenu' ),
current_submenu = null;
menus.next().hide();
menus.each( function(i){
var dropdown = $( this ).next(),
title = $( 'a.title', this );
title.click( function(e){
if ( current_submenu !== null && current_submenu != dropdown )
{
current_submenu.slideUp( 'slow' );
}
current_submenu = dropdown;
dropdown.stop(false, true).slideToggle('slow');
e.preventDefault();
} );
if ( title.text() == dynamic_value_from_controller )
title.click();
});
});
Have your controller output something on the submenu that you want to open, e.g. a data attribute, or a class name. Then your JS can trigger the submenu that has said attribute or class name to open.
Your list item that you want to open should look something like this:
<li id="second_menu" class="submenu" data-open-on-load="true">
... then in your js, instead of if( i==0 ) you can do something like this:
if ( $(this).attr("data-open-on-load") )
title.click();
See example: http://jsfiddle.net/cWXm5/13/
Note that you'll need to have your controller output this on the first submenu when no others will be set to open, or none will open.

sliding transitions not listening to each other in js

I have a js transition I can not resolve. There are three links, blue/green/red, when you select one of the links a color swatch slides into the up position. Push that same link again to make the color swatch slide into the down position.
How can I have each swatch slide all other swatches into the down position before sliding into the up position?
// When the DOM is ready, initialize the scripts.
jQuery(function( $ ){
// Get a reference to the container.
var container = $( ".container" );
// Bind the link to toggle the slide.
$( "a" ).click(
function( event ){
// Prevent the default event.
event.preventDefault();
// Toggle the slide based on its current visibility.
if (container.is( ":visible" )){
// Hide - slide up.
container.slideUp(500, function(){ $('').show(); });
} else {
// Show - slide down.
container.slideDown(500, function(){ $('').hide(); });
}
}
);
});
JSFiddle Demo
I've forked your jsfiddle with a simple solution: http://jsfiddle.net/cwmanning/jvj2u/2/
All in the fiddle, but it uses data attributes to switch classes instead of onClick attributes.
// Bind the link to toggle the slide.
$( "a" ).click(function( event ){
// Prevent the default event.
event.preventDefault();
var $this = $(this);
var $target = $("#target");
if ($target.attr("class") === $this.attr("data-color")) {
container.slideUp(500);
} else {
// Hide - slide up.
container.slideUp(500, function(){
$target.attr("class", $this.attr("data-color"));
// Show - slide down.
container.slideDown(500);
});
}
});
This is a quick workaround. I am sure there is a much more elegant way, but seems to work.
just change the following:
function slider(v) {
colors = {
'blue':'blue2',
'red' :'red2',
'green':'green2'
}
var confirm = document.getElementById("target");
if (colors.hasOwnProperty(v)){
setTimeout(function(){target.className = colors[v]},500);
}else {target.className = "chart";}
}
Substitute the following in place where you currently have the if(.... is(":visible").
I don't mean at the bottom of the code. Just sub the following in where it sits now in your code.
if (container.is( ":visible" )){
// Hide - slide up.
container.slideUp(500,function(){$().hide()});
setTimeout(function(){
container.slideDown(500, function(){ $('').show(); })
},500);
}else{
container.slideDown(500,function(){$().hide()})
}

Categories