jQuery using variables so one function performs multiple tasks - javascript

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.

Related

jQuery making only one div appear at a time

i'm trying to make divs appear and disappear by clicking on their thumbnails, but I can't figure out how to make them disappear after I make another one appear (the room variable changes its value), they just get placed after each other. The goal is to have only one div appeared at a time.
Here's my last try:
jQuery('.thumbs a').click(function () {
var room = "#room" + $(this).data('slide');
$(document).trigger('data-changed');
});
$(document).on('data-changed', function() {
$(room).toggleSlide('fast');
});
Sorry if its hard to understand.
CSS:
#wrapper div{
display:none;
}
JQuery:
jQuery('.thumbs a').click(function () {
room = "#room" + $(this).data('slide');
$(room).slideToggle('fast');
$('#wrapper').children().not(room).slideUp('fast');
});
Demo: http://jsfiddle.net/ffoa3pno/1/

jquery keeps on selecting element after changing the class

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

Div Transitions - IE vs. others

I have a JSFiddle that displays a series of boxes. If one of the boxes is clicked, it expands to cover the other boxes, then displays text. When the now expanded box is clicked, it retracts to its original width and height. This javascript works flawlessly in Firefox, Chrome, and Safari. However, in Internet Explorer (v10), the box expands but fails to retract. Any Insight on why this may be?
JSFiddle: http://jsfiddle.net/QBdDE/
Javascript:
$('div').on('click', function (e) {
if ($(this).hasClass('clicked')) {
setTimeout(function (div) {
return function () { div.css('z-index', '') ; } ;
} ($(this)), 1000) ;
$('.overlay-text').hide();
}
else {
$(this).css('z-index', 400) ;
setTimeout(function(){$('.overlay-text').show();},1000);
}
$(this).toggleClass('clicked') ;
});
What's Going On
Problem:
pointer-events support was added in IE11. IE10 is ignoring this, and because your overlay is on top, the mouse is interacting with it. We can get around this though!
Solution:
We need to remove dependency on that CSS rule. To do this, we need to do two things:
1.) We need to make the hover color stays applied even if the :hover effect isn't happening. We can add another selector to our CSS so that the .clicked class will cause the colors.
2.) We need to address what happens when .overlay_text is clicked, and use that to trigger the shrinking animation.
Code
1.) Hover Effect
We need to add in another select to every place :hover is used:
Old CSS:
.first_box:hover {
...background color rule ...
}
New CSS:
.first_box:hover, .first_box.clicked {
...background color rule ...
}
Duplicate the above for all 4 box rules.
2.) .overlay-text Trigger
We need to cause a click on .overlay-text to trigger the shrinking.
Old JS:
$('div').on('click', function (e) {
if ($(this).hasClass('clicked')) {
setTimeout(function (div) {
return function () { div.css('z-index', '') ; } ;
} ($(this)), 1000) ;
$('.overlay-text').hide();
}
else {
$(this).css('z-index', 400) ;
setTimeout(function(){$('.overlay-text').show();},1000);
}
$(this).toggleClass('clicked') ;
});
New JS:
We have to add a new selector to the .on() code, then we have to add .clicked to both the selected square, add the overlaying section. Finally we have to remove .clicked from both. We can't use .toggleClass() because we are adding to $(this) and removing from all divs.
$('div, .overlay-text').on('click', function (e) {
if ($(this).hasClass('clicked')) {
setTimeout(function (div) {
return function () { div.css('z-index', '') ; } ;
} ($(this)), 1000) ;
$('.overlay-text').hide();
$('div').removeClass('clicked');
$('.overlay-text').removeClass('clicked');
}
else {
$(this).css('z-index', 400) ;
setTimeout(function(){$('.overlay-text').show();},1000);
$(this).addClass('clicked');
$('.overlay-text').addClass('clicked');
}
});
Summary
I've tested in IE10 and it works.
Working Example:
Extra
If I may say, the CSS structure you are using could be improved and your animations will look a lot better. Chrome and IE both flicker during the animation of the two left blocks.
This is because their width AND position is being animated. If you position them from right:0, only their width will animate and it'll look a lot smoother.
I've created a Fiddle for you to address the above. I used absolute positioning. The CSS ends up being shorter, but mainly the animation doesn't flicker. Take a look:
Working Example:
Extra 2
As per comments from OP, we are going to prevent users from double clicking. Since all animations take 1 second, we will disable clicking from triggering anything for 1 second after each click.
It's actually pretty simple to do. In the Extra 1 above, we cleaned up the JS, and it became this:
$('div, .overlay-text').on('click', function (e) {
if ($(this).hasClass('clicked')) {
$('.overlay-text').hide();
$('div').removeClass('clicked');
$('.overlay-text').removeClass('clicked');
}
else {
setTimeout(function(){$('.overlay-text').show();},1000);
$(this).addClass('clicked');
$('.overlay-text').addClass('clicked');
}
});
We just need to add a global variable that starts true. When once the click happens, set it to false immediately, and after 1 second, set it to true. Then we just check to see if it's true, and don't do anything at all if it's false:
var notdouble = 1;
$('div, .overlay-text').on('click', function (e) {
if (notdouble) {
if ($(this).hasClass('clicked')) {
$('.overlay-text').hide();
$('div').removeClass('clicked');
$('.overlay-text').removeClass('clicked');
}
else {
setTimeout(function(){$('.overlay-text').show();},1000);
$(this).addClass('clicked');
$('.overlay-text').addClass('clicked');
}
notdouble=0;
setTimeout(function(){notdouble=1;},1000);
}
});
Working Example:
Note, this builds from the new structure in the Fiddle version 13, so it won't work exactly with the fixed version of the original structure. The concept can be adapted though.
Not working in IE 9 as the div click event never fires. I think it's covered by the section with class="overlay-text". But I've got a workaround by handling the click event of the section and triggering the div click event
$('section').on('click', function (e) {
$('.overlay-text').hide();
$( "div" ).addClass('clicked') ;
$( "div" ).trigger( "click" );
});

jQuery - have different events if element is on the same row

I have a page with a row of boxes that are responsive........
so the smaller you resize the window the amount of boxes on each row lessens
heres a fiddle to show you whats going on
http://jsfiddle.net/abtPH/6/
Right now the behavior is......if you click on a box then a div appears under it.....if you click on the next box the div slides up a bit then slides down revealing the new content...
I want it so that if the box is on the same row and the user clicks the next one it does not slide up then down but fades the content in
I only want it to slide up when the box is on a different row...like underneath
heres my jquery so far
$('li').on('click', function(e){
$(this).siblings('.active').toggleClass('active', 400).find('.outer').slideToggle();
$(this).find('.outer').slideToggle();
$(this).toggleClass('active', 400);
});
The trick is detecting what is on the same line. For that I think the position() function is what you need. When a list item is clicked, check to see if there is an active one already, if so, check to see if the current and active items have the same top value. If they do crossfade otherwise toggle.
$('li').on('click', function(e){
var active = $(this).siblings('.active');
var posTop = ($(this).position()).top;
if (active.length > 0) {
var activeTop = (active.position()).top;
if (activeTop == posTop) {
active.toggleClass('active', 400).find('.outer').fadeOut('slow');
$(this).find('.outer').fadeIn('slow');
} else {
$(this).siblings('.active').toggleClass('active', 400).find('.outer').slideToggle();
$(this).find('.outer').slideToggle();
}
} else {
$(this).find('.outer').slideToggle();
}
$(this).toggleClass('active', 400);
});
jsFiddle

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