Tie children of one div to children of another div with jquery - javascript

I have two parent divs: .inputs and .infoBoxes. Each of them have an equal number of children. When the user clicks into the first .input in .inputs, the first .infoBox in .infoBoxes should slideDown(). Same for second, third, etc. I'd like to do this without re-writing the same code for each pair. So far I have:
var $inputs = $('.inputs').children();
var $infoBoxes = $('.infoBoxes').children();
for(var i = 0; i < $inputs.length; i++ ) {
$($inputs[i]).find('.input').focus(function() {
$($infoBoxes[i]).slideDown();
})
$($inputs[i]).find('.input').blur(function() {
$($infoBoxes[i]).slideUp();
})
}
This isn't working but I have tried replacing i with the indexes of each div.
$($inputs[0]).find('.input').focus(function() {
$($infoBoxes[0]).slideDown();
})
$($inputs[0]).find('.input').blur(function() {
$($infoBoxes[0]).slideUp();
})
repeat...
repeat...
repeat...
This works but isn't very DRY. I'm looking for a better solution that won't have me repeating a bunch of code.

First code will not work, because you using same variable for all internal functions. You should wrap it into function, which will create local variable for index. Try following code:
var $inputs = $('.inputs').children();
var $infoBoxes = $('.infoBoxes').children();
for(var i = 0; i < $inputs.length; i++ ) {
(function(ix) {
$($inputs[ix]).find('.input').focus(function() {
$($infoBoxes[ix]).slideDown();
})
$($inputs[ix]).find('.input').blur(function() {
$($infoBoxes[ix]).slideUp();
})
})(i);
}

slideDown is used for showing elements. I am guessing you want to hide elements, since you are clicking on them and you cant click an hidden element. Use hide or slideUp to hide elements.
$(".input, .infobox").on("click", function() {
var ind = $(this).index();
$(".infobox:eq(" + ind + "), .input:eq(" + ind + ")").hide(500);
});
.input,
.infobox {
widht: 100%;
height: 50px;
text-align: center;
margin: 5px 0;
color: white;
}
.input {
background: red;
}
.infobox {
background: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="inputs">
<div class="input">1</div>
<div class="input">2</div>
<div class="input">3</div>
<div class="input">4</div>
<div class="input">5</div>
</div>
<div class="infoboxes">
<div class="infobox">1</div>
<div class="infobox">2</div>
<div class="infobox">3</div>
<div class="infobox">4</div>
<div class="infobox">5</div>
</div>

Related

Javascript shopping cart - need assistance with javascript portion, why isnt my code working?

I am making a javascript shopping cart. When you click on an item, the contents of that item are appended on the DOM via javascript. Having some difficulty with my code, specifically the sections where I bolded with '** **'
For my 'dropDown-amount' class, I have a number as the value but i cant seem to access that value later on in the code (see dropDown-price).
Also I have a For statement on my if/else statement that tries to loop through each index in 'items' array and to essentially count how many times one specific item is inside the list (so I can update quantity of x item on DOM) but having trouble getting everything to work. I know what I have to do to solve this problem and I know all 3 of these issues are linked together, just don't know what is exactly causing this to fail.
//dropdown menu hidden
const cartDropdown = document.querySelector('.cart-dropDown-items');
//every single + symbol
const addToCartButtons = document.querySelectorAll('.addToCart');
//price of item
const foodPrices = document.querySelectorAll('.selection-row-title');
//name of item
const foodNames = document.querySelectorAll('.selection-row-foodName');
//weight of item
const foodWeights = document.querySelectorAll('.selection-row-weight');
const items = [];
let total = 0;
for (let i = 0; i < addToCartButtons.length; i++) {
addToCartButtons[i].addEventListener('click', function() {
const newItem = document.createElement('div');
newItem.className = 'dropDown-item';
let amountItems = document.querySelector('.amount-items');
newItem.innerHTML =
`<div class='dropDown-title dropDown-info'>
${foodNames[i].innerHTML}
</div>
<div class='dropDown-amount dropDown-info'>
**<p class='amount-items'>${1}</p>**
</div>
<div class='dropDown-price dropDown-info'>
**${Number(foodPrices[i].innerHTML.substring(1)) * Number(amountItems.textContent)}**
</div>`;
console.log(newItem)
// if item currently exists in array, just update amount in checkout and increase count++
if (items.includes(addToCartButtons[i].value)) {
items.push(addToCartButtons[i].value); **
for (let i = 0; i < items.length; i++) {
if (items[i].includes(addToCartButtons[i].value)) {
Number(amountItems.innerHTML) + 1;
}
} **
}
// if items does not exist in array, update dom with new item UI and count = 1 by default
else {
items.push(addToCartButtons[i].value);
cartDropdown.appendChild(newItem);
}
console.log(items)
})
}
.cart-dropDown-items {}
.dropDown-title {}
.dropDown-item {
display: flex;
align-items: center;
text-align: center;
background-color: orange;
margin: 3px;
padding: 4px;
}
.dropDown-info {}
.dropDown-title {
width: 40%;
}
.dropDown-amount {
width: 30%;
text-align: center;
}
.dropDown-amount p {
border: 1px solid black;
width: 35%;
padding: 8px;
margin: 0 auto;
background-color: white;
}
.dropDown-price {
width: 30%;
}
<!--cart dropDown-->
<div class='cart-dropDown'>
<div class='cart-dropDown-header'>
<p>My Carts</p>
<p>Personal Cart</p>
<p class='cart-dropDown-close'>Close</p>
</div>
<div class='cart-dropDown-items'>
<!--
<div class='dropDown-item'>
<div class='dropDown-title dropDown-info'>Mixed bell pepper, 6 ct</div>
<div class='dropDown-amount dropDown-info'>1</div>
<div class='dropDown-price dropDown-info'>$9.84</div>
</div>
next unique item...
-->
</div>
<div class='cart-dropDown-checkout'>
<div class='cart-dropDown-checkout1'>
<p>Go to Checkout</p>
</div>
<div class='cart-dropDown-checkout2'>
<p>$0</p>
</div>
</div>
</div>
</div>

jQuery .not() and :not with new classes? [duplicate]

This question already has answers here:
jQuery click event not working after adding class
(7 answers)
Closed 2 years ago.
I have some card to flip and check if one is equal to another (memory game).
If I flip the card, I don't want that is possible to click and run function if I click on the same card (that is .flipped) or on another that is flipped. But jQuery .not() and :not not working. Maybe I must read another time the DOM after .toggleClass?
$(".card:not('.flipped')").on("click", function () {
$(this).toggleClass("flipped");
if (first) {
firstCard = $(this).attr("game");
first = false;
} else {
secondCard = $(this).attr("game");
first = true;
checkGame();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
The code is binding the events when it is called. So whatver the classes are at that moment in time, is what it finds and binds the event.
So you need to check for the class inside of the method and exit it
$(".card").on("click", function() {
var card = $(this);
if (card.hasClass("flipped")) return;
console.log(this);
card.addClass("flipped");
});
.wrapper {
display: flex;
}
.wrapper > .card {
flex: 1;
text-align: center;
line-height: 50px;
font-size: 30px;
}
.card.flipped {
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<div class="card">1</div>
<div class="card">2</div>
<div class="card">3</div>
<div class="card">4</div>
<div class="card">5</div>
<div class="card">6</div>
<div class="card">7</div>
<div class="card">8</div>
</div>
Other option is using event delegation where you bind the event to the parent and element and have jQuery do the checking if the class is added yet.
$(".wrapper").on("click", ".card:not('.flipped')", function() {
console.log(this);
var card = $(this);
card.addClass("flipped");
});
.wrapper {
display: flex;
}
.wrapper > .card {
flex: 1;
text-align: center;
line-height: 50px;
font-size: 30px;
}
.card.flipped {
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<div class="card">1</div>
<div class="card">2</div>
<div class="card">3</div>
<div class="card">4</div>
<div class="card">5</div>
<div class="card">6</div>
<div class="card">7</div>
<div class="card">8</div>
</div>
Apply the click event to all cards.
On click, check if the card is flipped. If it is, do nothing.
Cache your jQuery objects.
$(".card").on("click", function() {
const $card = $(this);
if ($card.hasClass("flipped")) return;
$card.toggleClass("flipped");
// .........
});
you have to check it inside your event 'click'. if the card has class 'flipped' break it
$(".card").on("click", function () {
if($(this).hasClass('.flipped')) return;
$(this).toggleClass("flipped");
if (first) {
firstCard = $(this).attr("game");
first = false;
} else {
secondCard = $(this).attr("game");
first = true;
checkGame();
}
});

Make div in div clickable with Javascript

Have a problem and can't get to solve it. Tried to use QuerySelectorAll and comma separating with GetElementsByClassName, but that didn't work, so I am wondering how to solve this problem.
I have this HTML:
<div class="area">Test title
<div class="some content" style="display: none">blablbala
<input></input>
</div>
<div class="two">This should be clickable too</div>
</div>
<div class="area">
Test title
<div class="some content">
blablbala
<input></input>
</div>
<div class="two">This should be clickable too</div>
</div>
JS:
function areaCollapse() {
var next = this.querySelector(".content");
if (this.classList.contains("open")) {
next.style.display = "none";
this.classList.remove("open");
} else {
next.style.display = "block";
this.classList.add("open");
}
}
var classname = document.getElementsByClassName("area");
for (var i = 0; i < classname.length; i++) {
classname[i].addEventListener('click', areaCollapse, true);
}
http://jsfiddle.net/1BJK903/nb1ao39k/6/
CSS:
.two {
position: absolute;
top: 0;
}
So now, the div with classname "area" is clickable. I positioned the div with class "two" absolute and now the whole div is clickable, except where this other div is. If you click on the div with classname "two", it doesn't work (it does not collapse or open the contents). How can I make this work, without changing the structure?
One way is using a global handler, where you can handle more than one item by checking its id or class or some other property or attribute.
Below snippet finds the "area" div and pass it as a param to the areaCollapse function. It also check so it is only the two or the area div (colored lime/yellow) that was clicked before calling the areaCollapse.
Also the original code didn't have the "open" class already added to it (the second div group), which mean one need to click twice, so I change the areaCollapse function to check for the display property instead.
function areaCollapse(elem) {
var next = elem.querySelector(".content");
if (next.style.display != "none") {
next.style.display = "none";
} else {
next.style.display = "block";
}
}
window.addEventListener('click', function(e) {
//temp alert to check which element were clicked
//alert(e.target.className);
if (hasClass(e.target,"area")) {
areaCollapse(e.target);
} else {
//delete next line if all children are clickable
if (hasClass(e.target,"two")) {
var el = e.target;
while ((el = el.parentElement) && !hasClass(el,"area"));
if (targetInParent(e.target,el)) {
areaCollapse(el);
}
//delete next line if all children are clickable
}
}
});
function hasClass(elm,cln) {
return (" " + elm.className + " " ).indexOf( " "+cln+" " ) > -1;
}
function targetInParent(trg,pnt) {
return (trg === pnt) ? false : pnt.contains(trg);
}
.area {
background-color: lime;
}
.two {
background-color: yellow;
}
.area:hover, .two:hover {
background-color: green;
}
.some {
background-color: white;
}
.some:hover {
background-color: white;
}
<div class="area">Test title clickable 1
<div class="some content" style="display: none">blablbala NOT clickable 1
</div>
<div class="two">This should be clickable too 1</div>
</div>
<div class="area">Test title clickable 2
<div class="some content">blablbala NOT clickable 2
</div>
<div class="two">This should be clickable too 2</div>
</div>
<div class="other">This should NOT be clickable</div>
You need to find your two elements while you're binding classname, and bind that as well.
var classname = document.getElementsByClassName("area");
for(var i=0; i < classname.length; i++){
classname[i].addEventListener('click', areaCollapse, true);
var twoEl = classname[i].getElementsByClassName("two")[0];
twoEl.addEventListener('click', function(e) { console.log('two clicked'); });
}
If you want to use jQuery:
$('.two').click(function(){
//action here
});

How to target individual div & apply class or attribute id

How can i select each div inside parent div & apply class (om_0 & go on) with increasing index number. Here I am unable to target each div.
Or how can I add attribute id="om_0", id="om_1", id="om_2" etc. to each div
The problem is it's applying all classes in one div & repeat it
var cirLength = $("div#circleBox > div").length;
for(var i=0; i<cirLength; i++){
$("div#circleBox").find('div').addClass('om_'+i);
}
<div id="circleBox"><div class="om_0 om_1 om_2"><span>AcessGreen</span></div><div class="om_0 om_1 om_2"><span>AccessBlue</span></div><div class="om_0 om_1 om_2"><span>AccessOrange</span></div></div>
You can use each() to iterate jQuery objects
$("div#circleBox").find('div').each(function(i) {
$(this).addClass('om_' + i);
// If you need to add it as id then use `this.id= 'om_' + i ` instead of `$(this).addClass('om_' + i)`
});
.om_0 {
color: red;
}
.om_1 {
color: green;
}
.om_2 {
color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="circleBox">
<div><span>AcessGreen</span>
</div>
<div><span>AccessBlue</span>
</div>
<div><span>AccessOrange</span>
</div>
</div>
With your own code you need to select individual item using eq()
var cirLength = $("div#circleBox > div").length;
for (var i = 0; i < cirLength; i++) {
$("div#circleBox").find('div').eq(i).addClass('om_' + i);
}
.om_0 {
color: red;
}
.om_1 {
color: green;
}
.om_2 {
color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="circleBox">
<div><span>AcessGreen</span>
</div>
<div><span>AccessBlue</span>
</div>
<div><span>AccessOrange</span>
</div>
</div>

How can I change the x position of a div via javascript when I click on another div this way?

<body>
<div id = "SiteContainer">
<div id = "NavigationButtons"></div>
<div id = "ShowReelContainer">
<div id= "NavigationBackward" name = "back" onclick="setPosition();">x</div>
<div id= "NavigationForward" name = "forward" onclick="setPosition();">y</div>
<div id = "VideoWrapper">
<div id = "SlideShowItem">
<img src="Images/A.png" alt="A"></img>
</div>
<div id = "SlideShowItem">
<img src="Images/B.png" alt="B"></img>
</div>
<div id = "SlideShowItem">
<img src="Images/C.png" alt="C" ></img>
</div>
</div>
</div>
</div>
<script>
var wrapper = document.querySelector("#VideoWrapper");
function setPosition(e)
{
if(e.target.name = "forward")
{
if!(wrapper.style.left = "-200%")
{
wrapper.style.left = wrapper.style.left - 100%;
}
}
else
{
if(e.target.name = "back")
{
if!(wrapper.style.left = "0%")
{
wrapper.style.left = wrapper.style.left + 100%;
}
}
}
}
</script>
</body>
Hi, I am very new to javascript. What I am trying to do, is change the x-position of a div when another div (NavigationForward or NavigationBackward) is clicked. However it does not appear to do anything at all. Basically if the div with name forward is clicked, I want to translate the VideoWrapper -100% from it's current position and +100% when "back". The css div itself VideoWrapper has a width of 300%. Inside this div as you can see is a SlideShowItem which is what will change. Perhaps I am adding and subtracting 100% the wrong way?
EDIT:
Thanks everyone for helping me out with this...I had just one more query, I am trying to hide the arrows based on whether the wrapper is at the first slide or the last slide. If its on the first slide, then I'd hide the left arrow div and if it's on the last, I'd hide the right arrow, otherwise display both of em. Ive tried several ways to achieve this, but none of em work, so Ive resorted to using copies of variables from the function that works. Even then it does not work. It appears that my if and else if statements always evaluate to false, so perhaps I am not retrieving the position properly?
function HideArrows()
{
var wrapper2 = document.getElementById("VideoWrapper");
var offset_x2 = wrapper2.style.left;
if(parseInt(offset_x2,10) == max_x)
{
document.getElementById("NavigationForward").display = 'none';
}
else if(parseInt(offset_x2,10) == min_x)
{
document.getElementById("NavigationBackward").display = 'none';
}
else
{
document.getElementById("NavigationForward").display = 'inline-block';
document.getElementById("NavigationBackward").display = 'inline-block';
}
}
//html is the same except that I added a mouseover = "HideArrows();"
<div id = "ShowReelContainer" onmouseover="HideArrows();">
To achieve this type o slider functionality your div VideoWrapper must have overflow:hidden style, and your SlideShowItemdivs must have a position:relative style.
Then to move the slides forward or backward you can use the style left which allows you to move the divs SlideShowItem relative to it's parent VideoWrapper.
I've tested this here on JSFiddle.
It seems to work as you described in your question, although you may need to do some adjustments, like defining the width of your slides, how many they are and so on.
For the sake of simplicity, I defined them as "constants" on the top of the code, but I think you can work from that point on.
CSS
#VideoWrapper{
position:relative; height:100px; white-space:nowrap;width:500px;
margin-left:0px; border:1px solid #000; overflow:hidden; }
.SlideShowItem{
width:500px; height:100px;display:inline-block;position:relative; }
#NavigationForward, #NavigationBackward{
cursor:pointer;float:left; background-color:silver;margin-right:5px;
margin-bottom:10px; text-align:center; padding:10px; }
HTML
<div id = "SiteContainer">
<div id = "NavigationButtons">
</div>
<div id = "ShowReelContainer">
<div id= "NavigationBackward" name = "back" onclick="setPosition('back');">prev</div>
<div id= "NavigationForward" name = "forward" onclick="setPosition('forward');">next</div>
<div style="clear:both;"></div>
<div id = "VideoWrapper">
<div class= "SlideShowItem" style="background-color:blue;">
Slide 1
</div>
<div class = "SlideShowItem" style="background-color:yellow;">
Slide 2
</div>
<div class = "SlideShowItem" style="background-color:pink;">
Slide 3
</div>
</div>
</div>
</div>
JavaScript
var unit = 'px'; var margin = 4; var itemSize = 500 + margin; var itemCount = 3; var min_x = 0; var max_x = -(itemCount-1) * itemSize;
function setPosition(e) {
var wrapper = document.getElementById("VideoWrapper");
var slides = wrapper.getElementsByTagName('div');
var offset_x = slides[0].style.left.replace(unit, '');
var curr_x = parseInt(offset_x.length == 0 ? 0 : offset_x);
if(e == "forward")
{
if(curr_x <= max_x)
return;
for(var i=0; i<slides.length; i++)
slides[i].style.left= (curr_x + -itemSize) + unit;
}
else if(e == "back")
{
if(curr_x >= min_x)
return;
for(var i=0; i<slides.length; i++)
slides[i].style.left= (curr_x + itemSize) + unit;
} }
After you analyze and test the code, I don't really know what's your purpose with this, I mean, you maybe just playing around or trying to develop something for a personal project, but if you are looking for something more professional avoid to create things like sliders on your own, as there are tons of plugins like this available and well tested out there on the web.
Consider using jQuery with NivoSlider, it works like a charm and is cross browser.
I would recommend using jQuery, this will reduce your coding by quite a bit. Can read more here: http://api.jquery.com/animate/
I've created a simple fiddle for you to take a look at. This example uses the .animate() method to reposition two div elements based on the CSS 'left' property.
CSS:
#container {
position: absolute;
left: 1em;
top: 1em;
right: 1em;
bottom: 1em;
overflow: hidden;
}
#one, #two {
position: absolute;
color: white;
}
#one {
background: pink;
width: 100%;
top:0;
bottom:0;
}
#two {
background: blue;
width: 100%;
left: 100%;
top:0;
bottom:0;
}
HTML:
<div id="container">
<div id="one">Div One</div>
<div id="two">Div Two</div>
</div>
JavaScript/jQuery:
var one, two, container;
function animateSlides(){
one.animate({
left : '-100%'
}, 1000, function(){
one.animate({
left : 0
}, 1000);
});
two.animate({
left : 0
}, 1000, function(){
two.animate({
left:'100%'
}, 1000);
});
};
$(function(){
one = $('#one');
two = $('#two');
container = $('#container');
setInterval(animateSlides, 2000);
});
JSFiddle Example: http://jsfiddle.net/adamfullen/vSSK8/3/

Categories

Resources