jquery keeps on selecting element after changing the class - javascript

I have a button which must change what it does after meeting some condition.
So I'm selecting the button by it's class and I want to remove that class upon meeting the condition and add a new class to the element and do something else with it. but it's not working.
I just made up an example for my problem.
this is the code:
$('.button-1').click(function(){
$('.box').width(function(){
return $(this).width() + 10;
});
$(this).removeClass('button-1').addClass('button-2');
});
$('.button-2').click(function(){
$('.box').width(function(){
return $(this).width() - 10;
});
$(this).removeClass('button-2').addClass('button-1');
});
and it's Fiddle
I expect this to toggle between increasing and decreasing the black box width, but it keeps on increasing.

That's because the event is bound statically on the button, use event delegation like this:
$(document).on('click','.button-1', function(){
$('.box').width(function(){
return $(this).width() + 10;
});
$(this).removeClass('button-1').addClass('button-2');
});
$(document).on('click','.button-2', function(){
$('.box').width(function(){
return $(this).width() - 10;
});
$(this).removeClass('button-2').addClass('button-1');
});
DEMO

Offcourse you could do it like that...but isn't it easier to add an another variable that checks whether or not there has been a click? The code is much simpler and you can check later on whether or not the box has been enlarged.
This method also seperates style from computing, which is generally regarded as a good idea.
var large = false;
$('body').on('click', '.button', function(){
if (large) {
$('.box').addClass('clicked');
large = false;
} else {
$('.box').removeClass('clicked');
large = true;
}
});
additionally, you need a css class like so:
.clicked {
width: 110px;
}
and I removed that button-1 and button-2 classes, gave the div the class 'button' instead

Related

For loop with eval not working

My first time writing my own javascript/jQuery for-loop and I'm running into trouble.
Basically, I have a series of divs which are empty, but when a button is clicked, the divs turn into input fields for the user. The input fields are there at the outset, but I'm using CSS to hide them and using JS/jQuery to evaluate the css property and make them visible/hide upon a button click.
I can do this fine by putting an id tag on each of the 7 input fields and writing out the jQuery by hand, like this:
$('#tryBTN').click(function(){
if ( $('#password').css('visibility') == 'hidden' )
$('#password').css('visibility','visible');
else
$('#password').css('visibility','hidden');
}
Copy/pasting that code 7 times and just swapping out the div IDs works great, however, being more efficient, I know there's a way to put this in a for-loop.
Writing this code as a test, it worked on the first one just fine:
$('#tryBTN').click(function() {
for(i = 1; i <= 7; i++) {
if($('#input1').css('visibility') == 'hidden')
$('#input1').css('visibility', 'visible');
}
});
But again, this only works for the one id. So I changed all the HTML id tags from unique ones to like id="intput1" - all the way out to seven so that I could iterate over the tags with an eval. I came up with this:
$('#tryBTN').click(function () {
for (i = 1; i <= 7; i++) {
if ($(eval('input' + i)).css('visibility') == 'hidden')
$('input' + i).css('visibility', 'visible');
}
});
When I put in the eval stuff - it doesn't work. Not sure what I'm doing wrong. A sample of the HTML looks like this:
<form>
<div class="form-group">
<label for="page">Description: Specifies page to return if paging is selected. Defaults to no paging.</label>
<input type="text" class="form-control" id="input7" aria-describedby="page">
</div>
</form>
You were forgetting the #:
$('#tryBTN').click(function () {
for (i = 1; i <= 7; i++) {
var el = $('#input' + i); // <-- The needed `#`
if (el.css('visibility') == 'hidden') {
el.css('visibility', 'visible');
}
}
});
#Intervalia's answer explains the simple error in your code (the missing #), and the comments explain why you should never use eval() unless you absolutely know it's the right tool for the job - which is very rare.
I would like to add a suggestion that will simplify your code and make it more reliable.
Instead of manually setting sequential IDs on each of your input elements, I suggest giving them all a common class. Then you can let jQuery loop through them and you won't have to worry about updating the 7 if you ever add or remove an item.
This class can be in addition to any other classes you already have on the elements. I'll call it showme:
<input type="text" class="form-control showme" aria-describedby="page">
Now you can use $('.showme') to get a jQuery object containing all the elments that have this class.
If you have to run some logic on each matching element, you would use .each(), like this:
$('#tryBTN').click( function() {
$('.showme').each( function( i, element ) {
if( $(element).css('visibility') == 'hidden' ) {
$(element).css( 'visibility', 'visible' );
}
});
});
But you don't need to check whether an element has visibility:hidden before changing it to visibility:visible. You can just go ahead and set the new value. So you can simplify the code to:
$('#tryBTN').click( function() {
$('.showme').each( function( i, element ) {
$(element).css( 'visibility', 'visible' );
});
});
And now that the only thing we're doing inside the loop is setting the new visibility, we don't even need .each(), since jQuery will do the loop for us when we call .css(). (Thanks #TemaniAfif for the reminder.)
So the code becomes very simple:
$('#tryBTN').click( function() {
$('.showme').css( 'visibility', 'visible' );
});

Remove Class when current toggle is clicked

The title is a bit of a tongue twister. A brief description of the fiddle, is that it's a toggle style accordion where the toggle state changes color when one of the divs is toggled. I've got it working to where if another div is toggled it will close that previous div and open the new div while changing the toggle state.
The issue I am running into is if a user wants to close the current toggle without clicking a different div it will close the current toggle but not change the toggle state back to it's original state. I am currently using this and have tried multiple things including if the container 'is: visible' or hasClass then to remove the toggle class, but nothing seems to work. I've also tried a different slideToggle function, but of course that applied it to the toggled element I've found.
Fiddle: http://jsfiddle.net/NFTFw/1256/
What I am trying to do?
I want the current toggle class to change back to its original state if the user clicks the current toggled div or clicks another div. So essentially I want the user to have either option.
CODE:
$(document).ready(function () {
$('.column').each(function (index) {
$(this).delay(750 * index).fadeIn(1500);
});
$('.column').hide();
$('.body').hide();
$('.column').each(function () {
var $toggle = $(this);
$('.toggle', $toggle).click(function () {
$(".toggle").removeClass("toggle-d");
$(this).addClass('toggle-d');
$body = $('.body', $toggle);
$body.slideToggle();
$('.body').not($body).hide();
});
});
});
Check to see if the thing that you're clicking already has the class. If so, remove it, if not, add it. I suspect the problem you were having with hasClass() is that you were attempting to check the wrong this.
Oooh I did a bad thing and didn't remove the class when a new div was clicked. I've fixed that and updated the jsfiddle
jsfiddle
js:
$(document).ready(function () {
$('.column').each(function (index) {
$(this).delay(750 * index).fadeIn(1500);
});
$('.column').hide();
var width = $(window).width();
if (width <= 600) {
$('.body').hide();
$('.column').each(function () {
var $toggle = $(this);
$('.toggle', $toggle).click(function () {
if($(this).hasClass('toggle-d')){
$(this).removeClass("toggle-d");
}
else{
$('.toggle').removeClass('toggle-d');
$(this).addClass('toggle-d');
}
$body = $('.body', $toggle);
$body.slideToggle();
$('.body').not($body).hide();
});
});
}
});
What i would suggest is to pass the element itself in the function
in the index.html Do this
<a class = 'classname' onclick = toggle(this)>
Your Content Here
</a>
After that in the script.js
what i am saying is in javascript, i believe you can easily convert it to jquery
function toggle(value){
if(value.className == 'the predefined value'){
value.className = value.className + ' Your new class addition'
// remember there should be a space if you are adding an additional class to the present class, else directly change the classname
}
else{
value.className = 'the predefined value'
}}
this will toggle your classname whenever the element is clicked

Hiding content depending on variable value

I am making a price estimator.
How would correctly write a jQuery function that checks a variable and depending on that amount hides/shows a certain div element accordingly.
So if I had:
a HTML div with the ID 'Answer'
<div id="answer">Hide Me</div>
$("#answer")...
a variable (this variable would change)
var x = 30
Now I know the css to hide the div would be:
#answer{
visibilty:hidden;
}
What would be the correct way to hide the function checking these certain parameters? for example if x > 20 then hide etc
Now I know there will be many ways to do this and they may not require jQuery, please inform me if this is the case. Perhaps it just needs JS. I know there will be many ways to do it not just one so if you have a different way please comment as I am keen to learn.
Any help would be greatly appreciated.
Cheers
F
Note that you can also remove or add a class:
$('#answer').removeClass('hide');
$('#answer').addClass('hide');
But what you want to do is $('#answer').hide(); or $('#answer').show();
Execute this function providing the variable v:
var checkVar = function(v) {
var target = $('#answer');
if (parseInt(v) > 20) {
target.hide();
} else {
target.show();
}
}
For example, if the variable comes form a selection:
$('#selectId').on('change', function() {
checkVar($(this).val());
});
Remove the CSS. You can do it in jQuery
if(x>20){
$('#answer').hide();
}
You can use this one
$("#answer").hide();
#kapantzak's answer looks good. But keep your logic and style separated and if your not going to use the variable for the actual element twice, I wouldn't make it. So go:
var checkVar = function(var) {
var element = $('#answer');
if (parseInt(var) > 20) {
element.addClass('hidden');
}else{
element.removeClass('hidden');
}
}
And in your CSS go:
#answer.hidden{
display: none;
}
Also, depending on your preference, display: none; doesn't display anything of the object whereas visibility: hidden hides the object but the space the object was occupying will remain occupied.
HTML
<input id="changingValue">
...
<div id="answer">Hide Me</div>
CSS (not mandatory if you check values on loading)
#answer{ display:none;}
JS
var limit = 20;
$(function(){
$("#changingValue").change(function(){
if(parseInt($("#changingValue").val())<limit) { $("#answer").show(); }
else { $("#answer").hide(); }
});
});

jQuery using variables so one function performs multiple tasks

I'm a real noob and every time I've tried to implement any of these things it just stops working altogether...
I have 4 boxes on my page that should each expand and contract in the direction the little blue tabs are facing.
The thing I'd like to know, which I tried to implement but just have no idea about, was if there was a way I could input some variables so the same function could be performed by the other boxes but in different directions...
.exp1 needs to be replaced so a variable with value 1-4 goes in place of the number
eg/ .exp(variable value from 1 to 4)
Depending on which value .exp takes, the other classes variable numbers need to change further down in the code
eg/ .box3 would need to be .box(variable value from 1 to 4)
.miniBox3 would be .miniBox(variable value from 1 to 4)
and lastly .con1 would be .con(variable value from 1 to 4)
The values and properties in animate would also need to change
eg/ instead of being .animate({bottom... it could be .animate({left... with a new va;lue like 30px instead of 10px
In the expandFunction() the rules are:
if it's .exp1... then .box3 closes replaced by .miniBox3, .box1 expands and .exp1 is switched to .con1
if it's .exp2... then .box1 closes replaced by .miniBox1, .box2 expands and .exp2 is switched to .con2
if it's .exp3... then .box4 closes replaced by .miniBox4, .box3 expands and .exp3 is switched to .con3
if it's .exp4... then .box2 closes replaced by .miniBox2, .box4 expands and .exp4 is switched to .con4
In the contractFunction() the .box, .exp and .con numbers are all the same.
Here's the code:
$(document).ready(function () {
//function declared expand
$('.exp1').click(function(){
expandFunction();
});
});
//expand function properties
function expandFunction(){
if($(".box3").is(":visible"))
{
$('.box3').animate({left:'100%', top:'70px', width:'0px', height:'0px'},
"slow", function(){
$(this).switchClass("box3", "miniBox3", "slow");
$('.exp3').hide();$('.miniBox3').show("fast");//hide blue bar, show box in sidebar
$('.box1').animate({bottom:'10px'}, "slow", function(){ //opens box right
$('.exp1').unbind('click').removeClass('exp1').addClass('con1')
.click(function(){
contractFunction();
});
});
});
}
else
{
$('.box1').animate({bottom:'10px'}, "slow", function(){ //opens box right
$('.exp1').unbind('click').removeClass('exp1').addClass('con1')
.click(function(){
contractFunction();
});
});
}
}
//};
function contractFunction(){
$('.box1').animate({bottom:'46.5%'}, "slow", function(){
$('.box1 div').unbind('click').removeClass('con1').addClass('exp1').click(function(){
expandFunction();
});
});
}
Here's a fiddle
(My first problem was that the 1st box (top left) expands once, contracts once and then doesn't do anymore. It should continually expand and contract to infinity. SOLVED WITH IF ELSE STATEMENT)
Thank you very much in advance for any pointers and help you can give me.
i've updated your fiddle with just a few things.
i get rid of the div.miniBox, i thought they weren't necessary for achiving your needs.
i rewrited the css classes you used so i can perform the animations just adding and removing classNames and each box now has a unique id.
i added to the trigger divs a data- attribute (thanks html5) to store the id of the related box to hide/show, so i can retrive that value with ease with the jQuery.data() function.
here a sample of html
<div id="a1" class="box">
<div class="exp" data-related="a3"></div>
1
</div>
and here the code i used
$(function () {
$('.exp').click(function () {
var exp = $(this); //this is the clicked trigger
var parent = exp.parent(); //this is the parent box
var related = $('#' + exp.data('related')); //this is the related box
if (exp.is('.con')) { // check if the box is expanded
// i can do the same with parent.is('.maxi')
//expanded
parent.removeClass('maxi' /* shrink the box */,
'slow',
function () {
exp.removeClass('con'); //now i know the parent box is no more expanded
related.removeClass('mini', 'slow'); //restore the related box
});
} else {
//collapsed
related.addClass('mini' /* minimize the related box */,
'slow',
function () {
exp.addClass('con'); //this to know if parent is expanded
parent.addClass('maxi', 'slow'); //expand the parent box
});
}
});
});
you can check the full code in this fiddle
EDIT: so, to answer your question (how to do this with variables) i say you can use the state of your elements as variables themself.

How to fire a unique ID modal when multiple divs with class is clicked using jQuery?

Forgive the strangely worded question, my first StackOverflow post, and I'm a novice to jQuery/JS. I've used the search feature a lot and haven't found exactly what I'm looking for:
I am having an issue essentially, where I have dynamically added divs by the end-user (they pick how many content blocks they want to use), with the same class, that need to hide and show specific divs (with unique IDs) when they are clicked. I finally figured out how to give each div a unique ID, but I'm not sure how to get the child divs of the particular div what was clicked, to fire properly on click. Hope that makes sense.
Here is the HTML I have:
<div class="resource-video">
//Unique thumbnail
</div>
<div class="overlay-container hide" style="width: 50px; height: 50px;">
<div class="video-player hide">
//Included unique video
</div>
</div>
This will end up being duplicated based on how many videos are added.
Here is the JavaScript I am using:
//Generates unique IDs for each of the divs on the page with those classes
var i = 0;
$(".resource-video").each(function(i){
$(this).attr("id","video_"+ (i+ 1) );
});
$(".overlay-container").each(function(i){
$(this).attr("id","container_"+ (i+ 1) );
});
$(".video-player").each(function(i){
$(this).attr("id","player_"+ (i+ 1) );
});
//Currently opens all of them
$(".resource-video").on("click", function(){
openModal(".overlay-container", false, true);
alert($(this).attr("id")); //Alerts the right div clicked
if ($(".video-player").hasClass("hide")){
$(".video-player").removeClass("hide").addClass("show");
$(".overlay-container").animate({ height:'300px', width: '500px' }, "slow");
}
$("#overlay").on("click", function(){
$(".video-player").removeClass("show").addClass("hide");
$(".overlay-container").css({ "height":"50px", "width":"50px",
"display":"none"});
$(this).hide();
});
return false;
});
// Probably not totally necessary, but just in case
function closeModals(){
$("body").find(".modal").hide();
$("#overlay").hide();
$("body, html").removeClass("no-scroll");
};
function openModal(divID, allowScroll, blockScreen){
closeModals();
$(divID).show();
if ( blockScreen == true ){ $("#overlay").show(); };
if ( allowScroll == false ){ $("body, html").addClass("no-scroll"); };
};
As it stands now, all of the overlays open because I am targeting the class not the IDs. Basically, I need to find out a way to have the specific overlay associated with the specific div clicked on to display without hardcoding that, since the number of divs will change all the time. I would think I could use something like $(this) or event.target, but things I tried didn't work.
Hopefully I was clear enough with my issue and made it general enough for other people to use too. Thanks for any help in advance!
This uses DOM traversal functions to find the corresponding DIVs to the one that was clicked.
$(".resource-video").on("click", function(){
var overlayContainer = $(this).next();
var videoPlayer = overlayContainer.children(".video-player");
openModal(overlayContainer, false, true);
if (videoPlayer.hasClass("hide")){
videoPlayer.removeClass("hide").addClass("show");
overlayContainer.animate({ height:'300px', width: '500px' }, "slow");
}
return false;
});
// Only need to bind this once, not every time .resource-video is clicked.
$("#overlay").on("click", function(){
$(".video-player").removeClass("show").addClass("hide");
$(".overlay-container").css({ "height":"50px", "width":"50px",
"display":"none"});
$(this).hide();
});
// Probably not totally necessary, but just in case
function closeModals(){
$(".modal").hide();
$("#overlay").hide();
$("body, html").removeClass("no-scroll");
};
function openModal(div, allowScroll, blockScreen){
closeModals();
div.show();
if ( blockScreen == true ){ $("#overlay").show(); };
if ( allowScroll == false ){ $("body, html").addClass("no-scroll"); };
};

Categories