slideUp and slideDown animation does not work after first use - javascript

I have used jQuery to build something like a dropdown, but it only works for the first two clicks, and then it doesn't. How can I make a dropdown? Can it be done with a loop? (I have not learnt loop yet, so any solution would work.)
For Each SLIDEUP and SLIDEDOWN I wanted to make different TIME....
jQuery(document).ready(function() {
jQuery(".click-on").click(function() {
jQuery(".box").slideUp(2000, function() {
jQuery(".click-on").click(function() {
jQuery(".box").slideDown(500);
});
return false;
});
return false;
});
});
.box {
width: 300px;
height: 300px;
background-color: skyblue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p id="fan">THIS IS A FAN</p>
<p id="gun">THIS IS A GUN</p>
<p class="click-on">Click Here</p>
<div class="box"></div>

Do you want to achieve something like that?
$(document).ready(function(){
$(".click-on").click(function(){
$('.box').slideToggle();
});
});
https://jsfiddle.net/jsrc9mbd/1/

The answer by #hetious is what I would have given - but having just seen the comment that slide-up and slide-down should have different times, you'll have to do this instead. Basically, check when you click whether the box is visible or not, and either slideUp or dlideDown accordingly:
jQuery(document).ready(function() {
jQuery(".click-on").click(function() {
var box = jQuery(".box");
if (box.is(":visible")) {
box.slideUp(2000);
}
else {
box.slideDown(500);
}
});
);
(Note that I have extracted a variable for jQuery(".box"), just to save some typing. And you can also use $ as an alias for jQuery to save yet more (the only reason this wouldn't work is if you are using another library which defines a global $ variable, which a few do.)

This is because you misunderstand the meaning of the .click() function.
.click() sets the handler function each time when the click event is triggered from the selected DOM.
Since you have called another .click() within the callback of .slideUp(), you are actually replacing the handler function. In your current logic, the obvious fix is to do infinite callback after each click like:
jQuery(".click-on").click(function(){
jQuery(".box").slideUp(2000, function(){
jQuery(".click-on").click(function(){
jQuery(".box").slideDown(500,function(){
jQuery(".click-on").click(function(){
jQuery(".box").slideUp(2000, function(){//Repeating callbacks... ...
});
});
});
});
and seriously it is very bad. Such implementation should not be done.
Instead, it is better for you to have a conditional checking for each click, so the logic will determine itself either .slideUp() or .slideDown() should be called. It should be like
$(".click-on").click(function(){//you can also use $ instead of jQuery
//do some conditional check here
if(isSlidedUp)$(".box").slideDown(1000);
else $(".box").slideUp(1000)
});
or even better you use .slideToogle().
$(".click-on").click(function(){
$(".box").slideToggle(1000)
}

Related

getting rid of duplicated code in jQuery

What is the most elegant way to beautify the following code? I would like to get rid of duplicated code:
$('#popup_settings_enable_name').click(function() {
$el = $('#popup_settings_name_field');
if ($(this).prop('checked')) {
$el.removeAttr("disabled");
} else {
$el.attr("disabled", "disabled");
}
}).each(function() {
$el = $('#popup_settings_name_field');
if ($(this).prop('checked')) {
$el.removeAttr("disabled");
} else {
$el.attr("disabled", "disabled");
}
});
You can simply trigger the click event handler after installing it using .triggerHandler:
$('#popup_settings_enable_name')
.click(function() {
// ...
})
.triggerHandler('click');
Note that .trigger would also do the exact same thing in many cases, but there are subtle differences between .trigger and .triggerHandler you should be aware of. The manual page makes clear mention of them.
You can simply trigger the event to execute the handler for initialisation:
$('#popup_settings_enable_name').click(function() {
…
}).click();
Another method would be to just use a function declaration:
function update() {
// a little simplification:
$('#popup_settings_name_field').prop("disabled", !this.checked);
}
$('#popup_settings_enable_name').click(update).each(update);
Triggering the click event manually could have unintended side effects (what if there are other delegates that have also been assigned the click event?)
I would suggest refactoring the duplicated code into its own method, then simply pass that method into the jQuery .click() function, and then passing it into the jQuery .each() function.

jQuery basic toggling only working one way

I've created some quick jQuery toggle code:
$("#expander.closed").click(function(){
console.log("opening");
$("#expander").removeClass();
$("#expander").addClass("open");
});
$("#expander.open").click(function(){
console.log("closing");
$("#expander").removeClass();
$("#expander").addClass("closed");
});
The idea is that everytime you click #expander the class toggles between open and closed.
However, for some reason, it only works once, changing from closed to open, and then goes no further.
I have no clue why. Here's a jsFiddle.
I think in the beginning, when you bind the events, .closed class does not exists, so the event does not get bound
May be you should bind the event to some other criteria, or use live. which is deprecated though
Better way would be like this
$("#expander_parent").on('click', '#expander.closed', function(){
// Do your stuff
})
Just bind it using the id and toggle the classes using .toggleClass
$("#expander").click(function(){
$(this).toggleClass('open closed');
});
FIDDLE
if you need to do other functions depending on which class it has you can check like this
$("#expander").click(function(){
var $this = $(this);
$this.toggleClass('open closed');
if($this.hasClass('open')){
// do your open code
}else{
// do your close code
}
});
FIDDLE
You can do this and add your other related operations within the if/else conditions
HTML:
<div id="expander" class="closed">Click Me</div>
CSS:
.closed {
background-color: red;
}
.open {
background-color: blue;
}
Javascript:
$("#expander.closed").click(function (){
if ($('#expander').attr('class') === 'closed') {
$('#expander').attr('class', 'open');
// Add other related functions here
} else {
$('#expander').attr('class', 'closed');
// Add other related functions here
}
});
http://jsfiddle.net/mCDwy/1/

JQuery - how to attach a method to the 2nd state in an event that has no states?

I'm using the premade .slideToggle method in JQuery
I want to add an object to the .slideDown state of .slideToggle. ie) When I click a button I want to bind that object to the .slideDown event and 'close' it. However I obviously cannot just .add the object to .slideToggle. Is there a way to specifically target the slideDown state? Or do I have to utilize .slideUp and .slideDown if I want the privilege of specificity?
Obviously .slideToggle is another super easy JQuery "let's look like magic while we cache all the if{s and all the rest into one big variable".
I believe you'll have to give up using .slideToggle() but you can still use the convenience of .toggle()
$('#some-element').toggle(function() {
// put slideDown here, along with anything else that should accompany it
}, function() {
// put slideUp here, etc.
});
You could always do like this. It's not better than #Justin Ward's way. But it works
$("#some-element").slideToggle(function(){
if ($(this).is(":visible")) {
// Do something (showing)
} else {
// Do something (not showing)
}
});

jQuery hover firing without mouse over

I have an element with id=message1mark. The following code will run the two alerts when the page loads regardless of the position on the mouse. Any help would be appreciated.
<script type="text/javascript">
jQuery(document).ready(function(){
jQuery("#message1mark").hover(alert("on"), alert("off"));
});
</script>
You need to wrap those alerts in functions:
$(document).ready(function(){
$("#message1mark").hover(function(){alert("on");}, function(){alert("off");});
});
Working example: http://jsfiddle.net/eJzKr/
What you tried would be interpreted as
try to call a function (which is why alert() is executed at the time of binding
and bind its result as a handler (which is nothing in this case)
$("#message1mark").hover(function(){
alert("on")
}, function(){
alert("off")
});
});
The correct way is:
jQuery("#message1mark").hover(function() {
alert("on");
},
function() {
alert("off"))
};
});
I believe that the alert() function fires automatically on each page. So even though you've tried to make it dependent on the hover function, it doesn't care.
It sounds like what you want is fundamentally a tooltip functionality. Some of the techniques listed in these resources might be a better way to approach things.
http://jquery.bassistance.de/tooltip/demo/
http://www.roseindia.net/tutorial/jquery/PopupOnHover.html
Instead of writing in two different functions you can include in one function itself. Below is the code for reference.
$(document).ready(function(){
$("#message1mark").hover(function(){alert("on");alert("off");});
});

js number +1 problem

I need click div.toggle1,control slideup, slidedown the div#text1,
click div.toggle7,control slideup, slidedown the div#text7.
here is my code, also in http://jsfiddle.net/qHY8K/ my number +1 not work, need a help. thanks.
html
<div class="toggle1">click</div>
<div id="text1">text1</div>
<div class="toggle7">click</div>
<div id="text7">text2</div>
js code
jQuery(document).ready(function() {
counter = 0;
for(i=1;i<11;i++){
(function(i){
counter = counter +1;
$('.toggle'+counter).toggle(function(){
$('#text'+counter).css('display','none');
},
function() {
$('#text'+counter).css('display','block');
});
})(i);
};
});
Lets simplify things a bit. One of the nice things about jQuery is that you can apply an event handler to many elements all at the same time. Start by adding a common classname to all of your 'toggle' divs:
HTML
<div class="toggle toggle1">click</div>
<div id="text1">text1</div>
<div class="toggle toggle7">click</div>
<div id="text7">text2</div>
Now you can use just one selector to target all of those divs. The rest is just a matter of pulling out the numeric difference in each 'toggle' div's classname:
JavaScript
jQuery(document).ready(function() {
$('.toggle').toggle(off, on);
function on() {
var i = this.className.match(/[0-9]+/)[0];
$('#text'+i).css('display','block');
}
function off() {
var i = this.className.match(/[0-9]+/)[0];
$('#text'+i).css('display','none');
}
});
I've updated your jsFiddle project. Hopefully this works out for you: http://jsfiddle.net/ninjascript/qHY8K/3/
Two solutions:
With your HTML as quoted, you can just do this:
jQuery(document).ready(function() {
$("div.toggle").click(function() {
$(this).next().toggle();
});
});
...since the div you're toggling is the next adjacent div. Note also that I'm using jQuery's toggle function to toggle the visibility.
But if it's possible that may change and you're defending against that, read on...
In your JavaScript code, you're already doing something that makes it possible to avoid the counter entirely, as knitti pointed out. But the way you're doing it creates functions unnecessarily and by using the same name (i) for both your loop counter and the argument to your anonymous function, you're making it very difficult to read and maintain that code.
So:
jQuery(document).ready(function() {
for(i=1;i<11;i++){
makeToggler(i);
}
function makeToggler(index){
$('.toggle'+index).click(function(){
$('#text'+index).toggle();
});
}
});
You can see how nice and clear that makes things, and in particular using a different name for the loop counter and the argument to makeToggler avoids confusion. And again, using jQuery's toggle function, no need for you to do it at the click level. (Also note that you don't put ; after the ending brace of a for statement.)
You don't need hard coded loop.
Preserve your current HTML and have such jQuery code instead:
$("div[class^='toggle']").each(function() {
var num = $(this).attr("class").replace("toggle", "");
$(this).toggle(function(){
$('#text' + num).css('display','none');
},
function() {
$('#text' + num).css('display','block');
});
});
This will iterate over all the <div> elements with class name starting with toggle and attach them the proper toggle function.
Updated jsFiddle: http://jsfiddle.net/qHY8K/5/
why do you introduce a new variable counter? (you should use var counter = 0; if you do).
in your function you could simply use your copied loop variable i:
for(i=1;i<11;i++){
(function(i){
$('.toggle'+i).toggle(function(){
$('#text'+i).css('display','none');
},
function() {
$('#text'+i).css('display','block');
});
})(i);
};
If your HTML has the structure as above, you could give all the toggleX elements the same class toggle and then all you have to do is:
$('.toggle').toggle(function(){
$(this).next().css('display','none');
},
function() {
$(this).next().css('display','block');
});
DEMO

Categories

Resources