Is it possible to use querySelectorAll with offsetHeight? - javascript

I would like to know if it's possible to get the height of many element with offsetHeight
<div class="container">
<div class="card">
<h4 class="card__title">My Title</h4>
<div class="card__img">
<img src="image.jpg" alt="">
</div>
<div class="card__description">
<p>
Lorem ipsum dolor, sit amet consectetur adipisicing elit.
</p>
</div>
</div>
<div class="card">
<h4 class="card__title">Thailande</h4>
<div class="card__img">
<img src="image.jpg" alt="">
</div>
<div class="card__description">
<p>
Description 2
</p>
</div>
</div>
</div>
I would like to to have a translate on the .card__img of the height of .card__description on a 'mouseover', is it possible to get the offsetHeight using querySelectorAll('.card__description).offsetHeight and using a loop?
I tried but didin't work.

Thanks guys, I did it!
Here is my solution
const cards = document.querySelectorAll('.card')
function cardAnimation () {
for (let i = 0; i < cards.length; i++) {
let card = cards[i]
let cardImg = card.querySelector('.card__img')
let description = card.querySelector('.card__description')
let descriptionHeight = description.offsetHeight
card.addEventListener('mouseover', () => {
description.style.transform = `translateY(0)`;
cardImg.style.transform = `translateY(-${descriptionHeight}px) scale(1.2)`
})
card.addEventListener('mouseleave', () => {
description.style.transform = `translateY(100%)`;
cardImg.style.transform = `translateY(0px) scale(1)`
})
}
}
cardAnimation()

Related

How do you set string values from an array in data() as the src path for an img element?

I am trying to have the <div.box> element that holds the elements appear depending on how many the user asks for using a form. I am using vue3 and using v-for to iterate over the array 'images' that holds strings of urls to images and then set those url values to the src.
But as of now, it's reading that the image in images points to my localhost:3000/image instead of "URLtoImage"
Any suggestions on what I am doing wrong here? Thanks in advance!
My script:
<script>
import ImageService from "../services/ImageService";
export default {
name: "Image",
data() {
return {
request: "",
images: [],
outOfRange: false,
errorMsg: "",
isHidden: true
};
},
methods: {
delay(time) {
return new Promise(resolve => setTimeout(resolve, time));
},
fullDataReset() {
Object.assign(this.$data, this.$options.data.apply(this));
},
getImagesFromCall() {
if (this.request < 1 || this.request > 5) {
this.outOfRange = true;
this.errorMsg = "Please enter a number from (1 - 5)";
this.delay(2000).then(() => this.reset());
} else
ImageService.getImagesFromNasaApodApi(this.request).then(response => {
this.images = response.data;
});
}
}
};
</script>
My template:
<template>
<div>
<h1>NASA API PHOTO GENERATOR</h1>
<div class="container-one">
<div class="container-item">
<form class="form" #submit.prevent="getImagesFromCall">
<input
type="number"
min="1"
max="5"
class="form-field"
placeholder="How many photos would you like? (6 max)"
v-model="request"
/>
<div id="error-message" v-if="outOfRange === true">{{ errorMsg }}</div>
</form>
</div>
</div>
<div class="container-two">
<button
type="submit"
id="toggle"
class="btn btn--primary btn--inside uppercase"
#:click="isHidden = false; getImagesFromCall()"
>Confirm</button>
</div>
<div id="spacer"></div>
<div v-show="!isHidden" v-if="request !== ''" class="container-three">
<div class="box" v-for="image in images" :key="image">
<div id="image" class="imgBx">
<img :src="image"/>
</div>
<div class="content">
<div>
<h2>Image Title</h2>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Commodi accusamus molestias quidem
iusto.
</p>
</div>
</div>
</div>
</div>
</div>
</template>
And here is what is showing on devtools of what data is retrieved from my external API call:
I think that the error is in the src attribute:
Try to bind src correctly to {{url}}
<img v-for="url in images" v-bind:key="url" :src="url"/>
I found the answer with help from the previous suggestion.
Very small idiosyncrasy in my div.box:
<div class="box" v-for="image in images" :key="image">
<div id="image" class="imgBx">
<img :src="image"/>
</div>
<div class="content">
<div>
<h2>Image Title</h2>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Commodi accusamus molestias quidem
iusto.
</p>
</div>
</div>
Switching the src="image"/> to :src="image"/> was all I needed. Hope this helps anyone else that may run into the same problem.

Removing active class from button

I have 3 buttons that represent a product category on my site. I want to load the page with the "All Products" button having an active class and then have that class removed and added to another button when clicked. There seems to be an issue that is causing an active class to be added twice to a button or not removed and so two buttons will be active at the same time.
Two active buttons at once and Active class added twice
I can fix the problem if I remove the active class from the "All Products" button but again I want the page to load with it set to active. These buttons also have to control the visibility of elements depending on what category they belong to.
Here is my code:
HTML:
<div class="list-group" id="myBtnContainer">
<button class="btn list-group-item active" onclick="filterSelection('all')">All Products</button>
<button class="btn list-group-item" onclick="filterSelection('shirts')">Shirts</button>
<button class="btn list-group-item" onclick="filterSelection('pants')">Pants</button>
</div>
HTML - Example Element:
<div class="col-lg-4 col-md-6 mb-4 filterDiv shirts">
<div class="card h-100 ">
<img class="card-img-top" src="blackshirt.png" alt="">
<div class="card-body">
<h4 class="card-title">
Black Shirt
</h4>
<h5>$24.99</h5>
<p class="card-text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!</p>
</div>
<div class="card-footer">
<i class="fa fa-search"></i> View Product
</div>
</div>
</div>
JavaScript
filterSelection("all")
function filterSelection(c) {
var x, i;
x = document.getElementsByClassName("filterDiv");
if (c == "all") c = "";
for (i = 0; i < x.length; i++) {
w3RemoveClass(x[i], "show");
if (x[i].className.indexOf(c) > -1) w3AddClass(x[i], "show");
}
}
function w3AddClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
if (arr1.indexOf(arr2[i]) == -1) {element.className += " " + arr2[i];}
}
}
function w3RemoveClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
while (arr1.indexOf(arr2[i]) > -1) {
arr1.splice(arr1.indexOf(arr2[i]), 1);
}
}
element.className = arr1.join(" ");
}
// Add active class to the current button (highlight it)
var btnContainer = document.getElementById("myBtnContainer");
var btns = btnContainer.getElementsByClassName("btn");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function(){
var current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace(" active", "");
this.className += " active";
});
}
Two active buttons at once
Check the logic within this function filterSelection.
Active class added twice
You can use toggle function from the classList attribute.
Show products according to the selected button
Use the data attributes and work with the classList attribute.
I.e: Set to your buttons: data-target='shirts', data-target='pants' and so on.
Use a class hide with this style: display: none
var btnContainer = document.getElementById("myBtnContainer");
var btns = btnContainer.getElementsByClassName("btn");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function() {
var current = document.getElementsByClassName("active");
current[0].classList.toggle('active');
this.classList.toggle('active');
var target = this.dataset.target;
filterSelection(target);
});
}
function filterSelection(target) {
document.querySelectorAll('.filterDiv').forEach((div) => {
if (target === 'all' || div.classList.contains(target)) {
div.classList.remove('hide');
} else {
div.classList.add('hide');
}
});
}
.active {
background-color: lightgreen;
}
.hide {
display: none
}
<div class="list-group" id="myBtnContainer">
<button class="btn list-group-item active" data-target='all'>Show all</button>
<button class="btn list-group-item" data-target='shirts'>Shirts</button>
<button class="btn list-group-item" data-target='pants'>Pants</button>
</div>
<div class="col-lg-4 col-md-6 mb-4 filterDiv shirts">
<div class="card h-100 ">
<img class="card-img-top" src="blackshirt.png" alt="">
<div class="card-body">
<h4 class="card-title">
Black Shirt
</h4>
<h5>$24.99</h5>
<p class="card-text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!</p>
</div>
<div class="card-footer">
<i class="fa fa-search"></i> View Product
</div>
</div>
</div>
<div class="col-lg-4 col-md-6 mb-4 filterDiv pants">
<div class="card h-100 ">
<img class="card-img-top" src="blackshirt.png" alt="">
<div class="card-body">
<h4 class="card-title">
Pants
</h4>
<h5>$44.99</h5>
<p class="card-text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!</p>
</div>
<div class="card-footer">
<i class="fa fa-search"></i> View Product
</div>
</div>
</div>
Resource
Element.classList

Filter cards in Bootstrap 4 with jQuery

I am attempting to create a page that is populated by many cards, using bootstrap 4's new card component.
I want to create a search bar, that when searched, filters out cards whose titles don't match the search query.
Here is a plunker of what I have in mind. Plunker
I would like the cards to get something like a display: none, or opacity:0 if they don't match.
I currently am attempting to write a function that onChange of the search bar does this. I'll post if I can get it figured out.
I've tried to use the built in snippet feature as well.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/js/bootstrap.js"></script>
<link href="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/css/bootstrap.css" rel="stylesheet" />
<div class="container">
<div class="row">
<div class="col-sm-4">
<input type="search" placeholder="Search......" name="search" class="searchbox-input" onkeyup="buttonUp();" required>
</div>
<div class="col-sm-4">
</div>
<div class="col-sm-4">
</div>
</div>
<div class="card-columns">
<div class="card">
<div class="card-block">
<h4 class="card-title">Card title that wraps to a new line</h4>
<p class="card-text">This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
</div>
</div>
<div class="card card-block">
<blockquote class="card-blockquote">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p>
<footer>
<small class="text-muted">
Someone famous in <cite title="Source Title">Source Title</cite>
</small>
</footer>
</blockquote>
</div>
<div class="card">
<div class="card-block">
<h4 class="card-title">Card title</h4>
<p class="card-text">This card has supporting text below as a natural lead-in to additional content.</p>
<p class="card-text"><small class="text-muted">Last updated 3 mins ago</small>
</p>
</div>
</div>
<div class="card card-block card-inverse card-primary text-xs-center">
<blockquote class="card-blockquote">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat.</p>
<footer>
<small>
Someone famous in <cite title="Source Title">Source Title</cite>
</small>
</footer>
</blockquote>
</div>
<div class="card card-block text-xs-center">
<h4 class="card-title">Card title</h4>
<p class="card-text">This card has supporting text below as a natural lead-in to additional content.</p>
<p class="card-text"><small class="text-muted">Last updated 3 mins ago</small>
</p>
</div>
<div class="card">
</div>
<div class="card card-block text-xs-right">
<blockquote class="card-blockquote">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p>
<footer>
<small class="text-muted">
Someone famous in <cite title="Source Title">Source Title</cite>
</small>
</footer>
</blockquote>
</div>
<div class="card card-block">
<h4 class="card-title">Card title</h4>
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This card has even longer content than the first to show that equal height action.</p>
<p class="card-text"><small class="text-muted">Last updated 3 mins ago</small>
</p>
</div>
</div>
</div>
Here's a quick example of how you could do it using jQuery's contains selector:
$('.searchbox-input').change( function () {
$('.card').show();
var filter = $(this).val(); // get the value of the input, which we filter on
$('.container').find(".card-title:not(:contains(" + filter + "))").parent().css('display','none');
});
Currently this is set up to happen on change of the search input, you would probably want set up a submit button and have it fire on submit instead.
Bootply Example
Here are a few more modern options that are Bootstrap 4 or Bootstrap 5 friendly...
Bootstrap 5 (using JavaScript)
var buttonUp = () => {
const input = document.querySelector(".searchbox-input");
const cards = document.getElementsByClassName("card");
let filter = input.value
for (let i = 0; i < cards.length; i++) {
let title = cards[i].querySelector(".card-body");
if (title.innerText.indexOf(filter) > -1) {
cards[i].classList.remove("d-none")
} else {
cards[i].classList.add("d-none")
}
}
}
Demo
Bootstrap 4 (using jQuery)
// this overrides `contains` to make it case insenstive
jQuery.expr[':'].contains = function(a, i, m) {
return jQuery(a).text().toUpperCase()
.indexOf(m[3].toUpperCase()) >= 0;
};
var buttonUp = () => {
$('.card').removeClass('d-none');
var filter = $(this).val(); // get the value of the input, which we filter on
$('.card-deck').find('.card .card-body h4:not(:contains("'+filter+'"))').parent().parent().addClass('d-none');
}
Demo
Here is the simple solution.
$(document).ready(function(){
$('.searchbox-input').on("keyup", function() {
var value = $(this).val().toLowerCase();
$(".card").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
});
$(document).ready(function() {
$('#searchForm').keyup(function(){
search_text($(this).val());
});
function search_text(value){
$('#search_section .card').each(function(){
var found = 'false';
$(this).each(function(){
if($(this).text().toLowerCase().indexOf(value.toLowerCase()) >= 0)
{
found = 'true';
}
});
if(found == 'true'){
$(this).show()
}
else {
$(this).hide();
}
})
}
});

How To Hide And Display Multiple Divs using JavaScript

How would I go about hiding and showing multiple divs using JavaScript? I don't want to use JQuery. I can make it work for hiding and showing one div but not multiple divs. The problem originates because I'm using PHP to display multiple records. These records are included in divs which have the same ID.
document.getElementById( 'history-slider' ).addEventListener( 'click', function() {
document.getElementById('edit-slider').style.display = 'block';
document.getElementById('history-slider').style.display = 'none';
}, false );
document.getElementById( 'edit-slider' ).addEventListener( 'click', function() {
document.getElementById('history-slider').style.display = 'block';
document..getElementById('edit-slider').style.display = 'none';
}, false );
.edit-slider {
display: none;
}
<div class="panel-body panel-strip" id="history-slider">
<h3>Title</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
<p>
<img src="img/time_icon.png" class="time-icon"> <span class="hour-text">4.00 hrs</span>
</p>
</div>
<hr class="calendar-divider">
<div class="panel-body panel-strip edit-slider">
<div class="row pull-right">
<a href="add.php">
<div class="col-xs-4 delete-panel">
<img src="img/delete_icon.png" class="edit-images center-block"><span class="text-center edit-texts">Delete</span>
</div>
</a>
<a href="http://google.com/">
<div class="col-xs-4 edit-panel">
<img src="img/edit_icon.png" class="edit-images center-block"><span class="text-center edit-texts edit-text">Edit</span>
</div>
</a>
<a href="http://google.com/">
<div class="col-xs-4 record-panel">
<img src="img/record_icon.png" class="edit-images center-block"><span class="text-center edit-texts">Record</span>
</div>
</a>
</div>
</div>
HTML;
<div class="panel-body panel-strip" id="history-slider">
<h3>Title</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
<p>
<img src="img/time_icon.png" class="time-icon"> <span class="hour-text">4.00 hrs</span>
</p>
</div>
<hr class="calendar-divider">
<div class="panel-body panel-strip edit-slider">
<div class="row pull-right">
<a href="add.php">
<div class="col-xs-4 delete-panel">
<img src="img/delete_icon.png" class="edit-images center-block"><span class="text-center edit-texts">Delete</span>
</div>
</a>
<a href="http://google.com/">
<div class="col-xs-4 edit-panel">
<img src="img/edit_icon.png" class="edit-images center-block"><span class="text-center edit-texts edit-text">Edit</span>
</div>
</a>
<a href="http://google.com/">
<div class="col-xs-4 record-panel">
<img src="img/record_icon.png" class="edit-images center-block"><span class="text-center edit-texts">Record</span>
</div>
</a>
</div>
</div>
JavaScript;
document.getElementById( 'history-slider' ).addEventListener( 'click', function() {
document.getElementById('edit-slider').style.display = 'block';
document.getElementById('history-slider').style.display = 'none';
}, false );
document.getElementById( 'edit-slider' ).addEventListener( 'click', function() {
document.getElementById('history-slider').style.display = 'block';
document..getElementById('edit-slider').style.display = 'none';
}, false );
I have also set in the CSS to hide the "edit-slider" div on page load.
.edit-slider {
display: none;
}
The HTML is echoed out in a loop for every record in the database. Information is also added in replace of the placeholder text.
How should I best go about making it so that if a div if clicked it is hidden and the corresponding div is shown in it's place?
I was thinking about doing something about individually giving the divs separate ID's in PHP and than passing those ID's to JavaScript and creating some sort of a loop? My knowledge of JavaScript isn't massive so I don't really know how easy or difficult this method would be. Or is there a much easier method?
This is my first stack overflow post,so sorry if I'm doing anything wrong or missed something.
If you use classes instead of IDs you can use document.QuerySelectorAll() to get all the divs with that class and then show or hide as necessary.
Something like below would hide all divs with an edit-slider class and reveal (assuming they were already hidden) all divs with a history-slider class.
(function() {
var editSliders = document.querySelectorAll('div.edit-slider');
for(var i=0;i<editSliders.length;i++){
editSliders[i].style.display = 'none';
}
var historySliders = document.querySelectorAll('div.history-slider');
for(var i=0;i<historySliders.length;i++){
historySliders[i].style.display = 'block';
}
})();
First, consider using class instead of id to set multiple elements with the same attribute and value. Then, use the following script:
<script type="text/javascript">
document.querySelectorAll('div.history-slider').forEach(item => {
item.addEventListener("click", myFunction);
});
function myFunction() {
this.hide;
}
</script>

javascript removing elements

How to remove such type html elements using javascipt?
<section id="cd-timeline" class="cd-container">
<div class="cd-timeline-block">
<div class="cd-timeline-img cd-location">
<img src="img/cd-icon-location.svg" alt="Location">
</div> <!-- cd-timeline-img -->
<div class="cd-timeline-content">
<h2>Title of section 4</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. .</p>
Read more
<span class="cd-date">Feb 14</span>
</div> <!-- cd-timeline-content -->
</div> <!-- cd-timeline-block -->
</section> <!-- cd-timeline -->
var element = document.getElementById('cd-timeline');
if (element) {
element.parentNode.removeChild(element);
}
You can just use:
document.getElementById("cd-timeline").outerHTML='';
You can use this:
document.getElementById('cd-timeline').remove();
If you would like to remove a element by it's id use:
var elem = document.getElementById("myDiv");
elem.parentNode.removeChild(elem);
If you would like to remove elements by their tag, class, etc. use:
var elems = document.getElementsByTag("myDiv");
for(var i = 0, len = elems.length; i < len; i++) {
if(elems[i] && elems[i].parentElement) {
elems[i].parentElement.removeChild(elems[i]);
}
}

Categories

Resources