Add class to element when scrolled into view (scrollable div) - javascript

Is there a solution for adding a class to the element in view when scrolling, and removing when out of view? This needs to work for a scrollable div. I have found a few solutions so far but they only seem to work for body... not a scrollable div.
I am happy to use a plugin if you know one exists. Something like this...
if ($('.journal-slider .each-slide img').inViewport() ) {
$(this).addClass('in-view');
} else {
$('.journal-slider .each-slide img').removeClass('in-view');
}
Thanks,
R

You could make your own jQuery plugin to do this. Something like this which takes two functions (whenInView, whenNotInView):
$('.journal-slider .each-slide img').inViewport(
function(){$(this).addClass("am-in-view");},
function(){$(this).removeClass("am-in-view");}
);
It tests on scroll (or resize) wether the target elements are currently within the viewport and calls the related function.
Here's the whole thing as a demo Snippet. In this example I have added an animation to the .am-in-view class so that you can see it working as the elements enter the viewport. This has not been tested on anything other than Chrome so far. Feel free to use and improve.
/*! inViewport 0.0.1
* jQuery plugin by Moob
* ========================
* (requires jQuery)
*/
(function ($) {
var vph=0;
function getViewportDimensions(){
vph = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
}
getViewportDimensions();
//on resize/scroll
$(window).on('resize orientationChanged', function(){
getViewportDimensions();
});
$.fn.inViewport = function (whenInView, whenNotInView) {
return this.each(function () {
var el = $(this),
inviewalreadycalled = false,
notinviewalreadycalled = false;
//on resize/scroll
$(window).on('resize orientationChanged scroll', function(){
checkInView();
});
function checkInView(){
var rect = el[0].getBoundingClientRect(),
t = rect.top,
b = rect.bottom;
if(t<vph && b>0){
if(!inviewalreadycalled){
whenInView.call(el);
inviewalreadycalled = true;
notinviewalreadycalled = false;
}
} else {
if(!notinviewalreadycalled){
whenNotInView.call(el);
notinviewalreadycalled = true;
inviewalreadycalled = false;
}
}
}
//initial check
checkInView();
});
}
}(jQuery));
html, body {
margin:0;
}
.me, .not-me {
padding:20px;
border:1px solid #aaa;
margin:20px;
}
.am-in-view {
background-color:pink;
-webkit-transition: all 1500ms;
-moz-transition: all 1500ms;
-o-transition: all 1500ms;
transition: all 1500ms;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="me">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eveniet, pariatur.</p>
<p>Saepe, eligendi nihil totam dolorum reprehenderit! Repellat omnis neque quasi.</p>
<p>Eos cumque voluptatum placeat eius nisi facere neque nesciunt praesentium.</p>
<p>Eos qui consectetur voluptatem eum, labore accusamus tempora distinctio sunt?</p>
</div>
<div class="me">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Excepturi, sit.</p>
<p>A veritatis quis quae totam accusamus repellendus adipisci corporis soluta.</p>
<p>Debitis animi dolor distinctio ratione dolorum ex aperiam maiores fugit?</p>
<p>Incidunt non consequatur porro provident recusandae sunt architecto repellat enim.</p>
</div>
<div class="me">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Blanditiis, reprehenderit?</p>
<p>Neque tempora perferendis dolor, mollitia debitis sunt voluptas ea ut!</p>
<p>Maiores earum officia corporis, sint voluptatem, in laboriosam perferendis asperiores?</p>
<p>Odit dolor voluptate laboriosam voluptatem accusamus aperiam explicabo at provident.</p>
</div>
<div class="not-me">
<p>I'm totally normal</p>
</div>
<div class="me">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ullam, accusamus.</p>
<p>Quisquam architecto repellat facere amet sapiente dolore obcaecati harum fuga.</p>
<p>Tempora labore, unde necessitatibus ipsam repellat architecto, aliquam autem at.</p>
<p>Sapiente quis doloremque a illum, repellat, eius corporis ab placeat.</p>
</div>
<div class="me">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptate, assumenda!</p>
<p>Nesciunt corrupti, eaque dolores ut libero ipsam dolorem laudantium saepe.</p>
<p>Similique quisquam quod esse expedita, voluptate quia nobis? Cum, tempore.</p>
<p>Amet voluptatem eaque non, praesentium tenetur molestias minima architecto laboriosam?</p>
</div>
<div class="me">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore, ex?</p>
<p>Perferendis hic, sint maxime similique quia autem cum quasi? Sed.</p>
<p>Nemo ratione aliquid itaque est blanditiis aliquam maiores veniam ab!</p>
<p>Reiciendis cumque fugit earum ea animi et aut molestiae dolores!</p>
</div>
<!-- how to call it -->
<script>
$(function(){
$('.me').inViewport(
function(){$(this).addClass("am-in-view");},
function(){$(this).removeClass("am-in-view");}
);
});
</script>

The plugin you are looking for is called waypoints
Quote from the "Get Started" :
"Let's say you have a div with overflow:scroll, and you want a waypoint inside of this scrollable element. The context option lets you do this. Scroll the box below."
$('#example-context').waypoint(function() {
notify('Hit top of context');
}, { context: '.example-scroll-div' });
EDIT: Not using waypoints
Based on what you already did, I came to this :
function checkInView(elem,partial)
{
var container = $(".scrollable");
var contHeight = container.height();
var contTop = container.scrollTop();
var contBottom = contTop + contHeight ;
var elemTop = $(elem).offset().top - container.offset().top;
var elemBottom = elemTop + $(elem).height();
var isTotal = (elemTop >= 0 && elemBottom <=contHeight);
var isPart = ((elemTop < 0 && elemBottom > 0 ) || (elemTop > 0 && elemTop <= container.height())) && partial ;
return isTotal || isPart ;
}
$(document).ready(function(){
$(".scrollable").scroll(function(){
var result="",result2="";
$.each( $(".scrollable p"),function(i,e){
if (checkInView($(e),false)) {
$( this ).addClass( "red" );
} else {
$( this ).removeClass( "red" );
}
result += " " + checkInView($(e),false);
result2 += " " + checkInView($(e),true);
});
$("#tt").text(result);
$("#kk").text(result2);
});
});
.scrollable{
margin:10px;
height:100px;
overflow-y:scroll;
}
p
{
border-width:1px;
border-color:black;
border-style:solid;
}
.red {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
full: <div id="tt"></div>
part: <div id="kk"></div>
<div class="scrollable">
<p>item1<span></span></p>
<p>item2<span></span></p>
<p>item3<span></span></p>
<p>item4<span></span></p>
<p>item5<span></span></p>
<p>item6<span></span></p>
<p>item7<span></span></p>
<p>item8<span></span></p>
</div>

where offset is an element's offset from screen. you should call this (throttles) using the scroll event, the repeatedly check if an element is in view.
function isElementInViewport(el, offset){
var rect = el.getBoundingClientRect();
offset = offset || 0;
return (
rect.top - offset >= 0 &&
rect.left >= 0 &&
rect.bottom + offset <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
);
}
using with onscroll event:
// utilizing underscore's `debounce` method
$(window).on('scroll.checkVisibility', _.debounce(check, 200));
function check(){
var visibility = isElementInViewport(element, -100);
if( visibility )
// do something if visisble
}

Using the Intersection Observer API
(native on modern browsers)
As jQuery is becoming obsolete, here is a simple solution using the Intersection Observer API:
/* Javascript */
// define an observer instance
var observer = new IntersectionObserver(onIntersection, {
root: null, // default is the viewport
threshold: 0.5, // percentage of taregt's visible area. Triggers "onIntersection"
});
// callback is called on intersection change
function onIntersection(entries, opts) {
entries.forEach((entry) => {
if (entry.isIntersecting) {
// Adding a class name if element is in view
entry.target.classList.add("class-name");
} else {
// Removing the class name if element is NOT in view
entry.target.classList.remove("class-name");
}
});
}
// Use the bserver to observe an element
observer.observe(document.getElementById("hello"));
// To stop observing:
// observer.unobserve(entry.target)
/* CSS */
#big-div {
height: 600px;
}
.class-name {
background-color: blue;
transition: 2s background-color;
}
<!--HTML-->
<div id="big-div">Scroll down to see the result!</div>
<div id="hello">Hello world</div>

Related

Javascript: I am trying to create scroll while user scrolling on the page, but i keep having NaN error for 'moveImaeCalc'

I'd like to trigger scrolling of a div with overflowing content by scrolling anywhere on the page, not just by moving the mouse and clicking within the div. Also, I'd like to hide the div's scrollbar such that only the page's scrollbar is visible.
let viewportHeight = $("body").innerHeight();
let contTopPositionArray = [];
let imageHeightArray = [];
let containerHeightArray = [];
let containerIDArray = [];
jQuery(window).on("scroll", function() {
var scroll = $(window).scrollTop();
//console.log(scroll);
containerIDArray.forEach((element, index) => {
var tempOffset = $('#' + element).offset();
console.log(tempOffset.top)
if (tempOffset.top < scroll + viewportHeight && tempOffset.top + containerHeightArray[index] < scroll) {
console.log('i can see you', element);
}
});
});
$('.container').each(function(index, el) { //vrti funkciju za svaki conteiner na stranici
var contPost = $(this).offset();
contTopPositionArray.push(contPost.top); // skuplja gde se nalazi conteiner sa slikom od vrha stranice, tj njegova top pozicija
console.log(contTopPositionArray);
var imgageHeigth = $('.col2 img', this).height();
imageHeightArray.push(imgageHeigth); // skuplja visinu slike
console.log(imageHeightArray);
var conteinerHeigth = $('.col2', this).height();
containerHeightArray.push(conteinerHeigth); // skuplja koliko je veliki div gde se slika nalazi
containerIDArray.push($(this).attr('id')); // skuplja koji je ID za red
console.log(containerIDArray);
var moveImageCalc = -(imageHeightArray[index] - conteinerHeigth[index] * ((imageHeightArray[index] - conteinerHeigth[index]) / viewportHeight));
console.log(moveImageCalc)
});
jQuery(window).on("scroll", function() {
var scroll = $(window).scrollTop();
//console.log(scroll);
containerIDArray.forEach((element, index) => {
var tempOffset = $('#' + element).offset();
console.log(tempOffset.top);
if (tempOffset.top < scroll + viewportHeight && tempOffset.top + containerHeightArray[index] < scroll) {
// mesto 500 treba da napravim funckiju koja ce automatski da racuna visinu slike i skrola kroz nju
$('#' + element + ' img').css('top', moveImageCalc);
console.log('i can see you', element);
}
});
});
var scroll =
window.requestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
var elementToShow = document.querySelectorAll(
".col2"
);
function loop() {
elementToShow.forEach(function(element) {
if (isElementInViewport(element)) {
element.classList.add("class");
} else {
element.classList.remove("class");
}
});
scroll(loop);
}
loop();
function isElementInViewport(el) {
if (typeof jQuery === "function" && el instanceof jQuery) {
el = el[0];
}
var rect = el.getBoundingClientRect();
return (
(rect.top <= 0 && rect.bottom >= 0) ||
(rect.bottom >=
(window.innerHeight || document.documentElement.clientHeight) &&
rect.top <=
(window.innerHeight || document.documentElement.clientHeight)) ||
(rect.top >= 0 &&
rect.bottom <=
(window.innerHeight || document.documentElement.clientHeight))
);
}
.container {
max-width: 80rem;
height: 80vh;
margin: 0 auto;
padding: 0 2rem;
display: flex;
align-items: center;
justify-content: center;
gap: 2rem;
margin-bottom: 4rem;
}
.col1 {
flex: 0 0 45%;
}
.col2 {
flex: 1;
height: 200px;
overflow: scroll;
position: relative;
}
.col2 img {
position: absolute;
top: 0;
left: 0;
width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container" id="first">
<div id="scrollMeToo" class="col1">
<h2>Project 1</h2>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Omnis voluptatem deleniti ipsam rem fugit facilis. Quaerat aliquid omnis sunt praesentium laudantium rem unde natus deleniti amet, labore maiores eos ratione doloribus at provident autem facere?</p>
Click
</div>
<div class="col2">
<img src="https://picsum.photos/200/300" alt="">
</div>
</div>
<div class="container " id="second">
<div class="col1">
<h2>Project 1</h2>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Omnis voluptatem deleniti ipsam rem fugit facilis. Quaerat aliquid omnis sunt praesentium laudantium rem unde natus deleniti amet, labore maiores eos ratione doloribus at provident autem facere?</p>
Click
</div>
<div class="col2">
<img src="https://picsum.photos/200/300" alt="">
</div>
</div>
<div class="container" id="tird">
<div class="col1">
<h2>Project 1</h2>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Omnis voluptatem deleniti ipsam rem fugit facilis. Quaerat aliquid omnis sunt praesentium laudantium rem unde natus deleniti amet, labore maiores eos ratione doloribus at provident autem facere?</p>
Click
</div>
<div class="col2">
<img src="https://picsum.photos/200/300" alt="">
</div>
</div>
<div class="container" id="fourth">
<div id="scrollMeToo" class="col1">
<h2>Project 1</h2>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Omnis voluptatem deleniti ipsam rem fugit facilis. Quaerat aliquid omnis sunt praesentium laudantium rem unde natus deleniti amet, labore maiores eos ratione doloribus at provident autem facere?</p>
Click
</div>
<div class="col2">
<img src="https://picsum.photos/200/300" alt="">
</div>
</div>
(also at https://codepen.io/Pavle1993/pen/poreRjW)
If anyone knows an easier solution I would be grateful to share with me. Thanks.
var moveImageCalc = - (imageHeightArray[index] - conteinerHeigth[index] * ((imageHeightArray[index] - conteinerHeigth[index])/viewportHeight));
console.log(moveImageCalc) // NaN
You have a semantic error in your code. It is illegal to run conteinerHeight[index], where conteinerHeight is a number value. I am pretty sure you meant containerHeightArray[index]. See the corrected code snippet below:
$('.container').each(function(index, el) { //vrti funkciju za svaki conteiner na stranici
var contPost = $(this).offset();
contTopPositionArray.push(contPost.top); // skuplja gde se nalazi conteiner sa slikom od vrha stranice, tj njegova top pozicija
console.log(contTopPositionArray);
var imgageHeigth = $('.col2 img', this).height();
imageHeightArray.push(imgageHeigth); // skuplja visinu slike
console.log(imageHeightArray);
var conteinerHeigth = $('.col2', this).height();
containerHeightArray.push(conteinerHeigth); // skuplja koliko je veliki div gde se slika nalazi
containerIDArray.push($(this).attr('id')); // skuplja koji je ID za red
console.log(containerIDArray);
var moveImageCalc = -(imageHeightArray[index] - containerHeigthArray[index] * ((imageHeightArray[index] - containerHeigthArray[index]) / viewportHeight));
console.log(moveImageCalc)
});
In regards to your question:
Also, I'd like to hide the div's scrollbar such that only the page's scrollbar is visible.
See answers to this stackOverflow question.

How to close a menu bar when clicking outside of it [duplicate]

This question already has answers here:
How do I detect a click outside an element?
(91 answers)
Closed 2 years ago.
I'm trying to find multiple ways to close a sidebar menu that pops out from the left side. The idea of this is to have a page with an "Open/Close Menu" button. As expected this button should be able to open and close the menu with clicked, but I also want to include an option of closing it when simply clicking outside the menu bar.
My thought process behind this is to add a div that surrounds all of the content on the page, and gives it a class name of "notMenu". I would define the dimensions of this to be the entire page and give it a z-index of 1. When the menu pops up, it would be on top of .notMenu with a z-index of 2, yet I can't seem to get it to work.
var menuBtn = document.querySelector('.menuBtn');
var sidebar = document.querySelector('.sidebar');
var closeMenuBtn = document.querySelector('.closeMenuBtn');
var notMenu = document.querySelector('.notMenu');
var nav = 'closed'
menuBtn.addEventListener('click', function() {
if (nav === 'closed') {
sidebar.style.display = 'block'
nav = 'open'
} else {
sidebar.style.display = 'none'
nav = 'closed'
}
});
// closeMenuBtn.addEventListener('click',function(){
// sidebar.style.display = 'none'
// });
closeMenuBtn.addEventListener('click', function() {
sidebar.style.display = 'none';
nav = 'closed';
});
/*
notMenu.addEventListener('click',function(){
sidebar.style.display = 'none'
nav = 'closed';
})
*/
h1 {
text-align: center;
}
.menuBtn {
position: relative;
left: 50%;
transform: translateX(-50%);
}
.closeMenu {
font-size: 30px;
z-index: 2;
}
.sidebar {
position: absolute;
top: 0;
height: 100vh;
width: 300px;
background: grey;
display: none;
z-index: 2;
}
.notMenu {
position: absolute;
top: 0;
height: 100%;
width: 100%;
z-index: 1;
}
<body>
<div class="notMenu">
<h1> Header </h1>
<div class="sidebar">
<ul>
<li><a href=''>Link1</a></li>
<li><a href=''>Link2</a></li>
<li><a href=''>Link3</a></li>
</ul>
<button class="closeMenuBtn">Close Menu</button>
</div>
<button class="menuBtn">Open/Close Menu</button>
<div class="content1">
<br><br> Lorem ipsum dolor sit amet consectetur, adipisicing elit. Aspernatur quia ipsam optio, veritatis corrupti exercitationem quae itaque accusamus voluptas ipsa consequuntur nostrum, culpa, cum dolore incidunt ducimus harum minus doloremque?
</div>
<div class="content2">
<br><br> Lorem ipsum dolor sit amet consectetur adipisicing elit. Eum quia laboriosam ut accusantium itaque adipisci vitae error provident voluptate, dolorem veniam dignissimos atque accusamus aut rem quos esse fugit voluptas soluta laudantium.
Nam voluptates maxime sapiente, pariatur voluptatibus mollitia quia.
</div>
</div>
<!--closes .notMenu-->
</body>
CodePen Link
Alternatively, is there a way to do this without designated a new class as .notMenu? I assume there is a possibility to do this with e.target in JS with if statements.
function(e){
if (e.target !== 'sidebar'){
sidebar.style.display = 'none'
}
}
The issue I ran into with this is that e.target returns an object. I'm unable to define which objects represent the sidebar and which ones do not, therefore I can't determine if the area outside the sidebar is being clicked.
try this
window.addEventListener('mouseup', function(e) {
var x = document.querySelector('.sidebar');
if (event.target != document.querySelector(".icon")) {
x.style.display = "none";
}
});
var menuBtn = document.querySelector('.menuBtn');
var sidebar = document.querySelector('.sidebar');
var closeMenuBtn = document.querySelector('.closeMenuBtn');
var notMenu = document.querySelector('.notMenu');
var nav = 'closed'
menuBtn.addEventListener('click',function(){
if (nav === 'closed'){
sidebar.style.display='block'
nav = 'open'
}
else{
sidebar.style.display = 'none'
nav = 'closed'
}
});
closeMenuBtn.addEventListener('click',function(){
sidebar.style.display = 'none';
nav = 'closed';
});
// fire event if click is outside of sidebar and menubtn
window.onclick = function(event) {
if (event.target !== sidebar && event.target !== menuBtn) {
sidebar.style.display = "none";
console.log('clicked');
}
}
h1{
text-align:center;
}
.menuBtn{
position:relative;
left:50%;
transform:translateX(-50%);
}
.closeMenu{
font-size:30px;
z-index:2;
}
.sidebar{
position:absolute;
top:0;
height:100vh;
width:300px;
background:grey;
display:none;
z-index:2;
}
.notMenu{
position:absolute;
top:0;
height:100%;
width:100%;
z-index:1;
}
<div class="notMenu">
<h1> Header </h1>
<div class="sidebar">
<ul>
<li><a href =''>Link1</a></li>
<li><a href =''>Link2</a></li>
<li><a href =''>Link3</a></li>
</ul>
<button class="closeMenuBtn">Close Menu</button>
</div>
<button class="menuBtn">Open/Close Menu</button>
<div class="content1">
<br><br>
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Aspernatur quia ipsam optio, veritatis corrupti exercitationem quae itaque accusamus voluptas ipsa consequuntur nostrum, culpa, cum dolore incidunt ducimus harum minus doloremque?
</div>
<div class="content2">
<br><br>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Eum quia laboriosam ut accusantium itaque adipisci vitae error provident voluptate, dolorem veniam dignissimos atque accusamus aut rem quos esse fugit voluptas soluta laudantium. Nam voluptates maxime sapiente, pariatur voluptatibus mollitia quia.
</div>
</div>
try this

Read more link with pure JavaScript

I am trying to create a simple Read More example. It consists of a paragraph and a button with half of the paragraph enclosed in a span tag which is initially set to hidden. When user clicks on Read More button the hidden span shows up. I have got the working code but just want to do a fade in effect like JQuery but with pure Javascript. Anyone please help.
var span = document.getElementsByTagName('span')[0];
var hideshow = document.getElementById('hideshow');
span.style.display = 'none';
hideshow.onclick = function() {
span.style.display = 'block';
};
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ipsa maiores dolore earum ducimus molestiae, aut. <span>Quisquam consequuntur, maiores et, doloremque atque provident similique consequatur totam voluptas vitae veniam, molestiae laborum.</span></p>
<button id="hideshow">Read More</button>
One approach is to use a CSS3 transition in order to transition the element's opacity.
In the example below, the class fade-in is added to the child span element when clicking the button.
var button = document.querySelector('.read-more');
button.addEventListener('click', function(event) {
var span = event.target.previousElementSibling.querySelector('span');
span.classList.add('fade-in');
});
.show-more span {
display: inline-block;
height: 0;
overflow: hidden;
transition: opacity 2s;
opacity: 0;
}
.show-more span.fade-in {
height: auto;
opacity: 1;
}
<p class="show-more">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ipsa maiores dolore earum ducimus molestiae, aut. <span>Quisquam consequuntur, maiores et, doloremque atque provident similique consequatur totam voluptas vitae veniam, molestiae laborum.</span></p>
<button class="read-more">Read More</button>
If you want an approach that works for multiple elements, you could also use the following:
var buttons = document.querySelectorAll('.read-more');
for (var i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function(event) {
var span = event.target.previousElementSibling.querySelector('span');
span.classList.add('fade-in');
});
}
.show-more span {
display: inline-block;
height: 0;
overflow: hidden;
transition: opacity 2s;
opacity: 0;
}
.show-more span.fade-in {
height: auto;
opacity: 1;
}
<p class="show-more">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ipsa maiores dolore earum ducimus molestiae, aut. <span>Quisquam consequuntur, maiores et, doloremque atque provident similique consequatur totam voluptas vitae veniam, molestiae laborum.</span></p>
<button class="read-more">Read More</button>
<p class="show-more">Another shorter paragraph. <span>Quisquam consequuntur, maiores et, doloremque atque provident similique consequatur totam voluptas vitae veniam, molestiae laborum.</span></p>
<button class="read-more">Read More</button>
Starting here
span.style.opacity = 0;
You'll need to gradually transition the opacity to here.
span.style.opacity = 1;
You'll need to use an asynchronous construct (setTimeout/setInterval/requestAnimationFrame) for iterating, because a synchronous one (while/for/for-in/forEach) will block the main thread, preventing the browser from actually rendering the element with the updated opacity.
function fadeIn(element) {
function transition() {
if(element.style.opacity < 1) {
requestAnimationFrame(transition);
element.style.opacity = Number(element.style.opacity) + 0.05;
}
}
transition();
}
Alternatively, if you're happy to use CSS (rather than pure JS) you can do this with classes and transitions.
.out {
opacity: 0;
transition-duration: 0.5s;
}
.in {
opacity: 1;
transition-duration: 0.5s;
}
Make sure that the element has the out class when it arrives in the DOM, then when you're ready to fade it in, swap it for the in class and the browser will handle the animation for you.
var duration = 2000; // msecs
document.getElementById('hideshow').onclick = () => {
requestAnimationFrame((start_time) => {
var anim = (time) => {
var p = (time - start_time) / duration;
(p < 1) && requestAnimationFrame(anim);
span.style.opacity = 1 - p;
}
anim(start_time);
})
}

Show more jquery to work with two divs

I found following solution for "show more" functionality that, which works great. I need to enhance this to have two divs to expand/hide simultaneously.
How to create a "show more" button and specify how many lines of text can be initially shown
Below is my updated code that does not work for some reason.
$(".show-more span").click( function() {
var $this = $(this);
var $content = $this.parent().prev("div.contentNav");
var $contentDesc = $this.parent().prev("div.contentDesc");
var linkText = $this.text().toUpperCase();
if(linkText === "(SHOW LESS)"){
linkText = "more...";
$content.switchClass("showContent", "hideContent", 200);
$contentDesc.switchClass("showContent", "hideContent", 200);
} else {
linkText = "(Show less)";
$content.switchClass("hideContent", "showContent", 200);
$contentDesc.switchClass("hideContent", "showContent", 200);
}
$this.text(linkText);
});
Thank you.
Your var $contentDesc = $this.prev("div.contentDesc"); change it to var $contentDesc = $content.prev("div.contentDesc");
DEMO
$(function() {
$(".show-more span").click( function() {
var $this = $(this);
var $content = $this.parent().prev("div.contentNav");
var $contentDesc = $content.prev("div.contentDesc");
var linkText = $this.text().toUpperCase();
if(linkText === "(SHOW LESS)") {
linkText = "more...";
$content.switchClass("showContent", "hideContent", 200);
$contentDesc.switchClass("showContent", "hideContent", 200);
} else {
linkText = "(Show less)";
$content.switchClass("hideContent", "showContent", 200);
$contentDesc.switchClass("hideContent", "showContent", 200);
}
$this.text(linkText);
});
});
.hideContent {
overflow: hidden;
line-height: 1em;
height: 2em;
}
.showContent{
height: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.8.18/jquery-ui.min.js"></script>
<div class="contentDesc hideContent">
<p>Description</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolor repudiandae non sit incidunt totam, error optio animi possimus saepe quidem voluptate molestias neque excepturi hic. Omnis, pariatur, aliquid. Facere, alias!</p>
</div>
<div class="contentNav hideContent">
<p>Navigation content</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolor repudiandae non sit incidunt totam, error optio animi possimus saepe quidem voluptate molestias neque excepturi hic. Omnis, pariatur, aliquid. Facere, alias!</p>
</div>
<div class="show-more" style="text-align: center; text-align: center; cursor: pointer;"><span>more...</span> </div>
Your Code is not working because it cant find the second div, So check your code. To fix it put , var $contentDesc = $this.parent().prev("div.content").prev();.

readmore javascript plugin first item open

I'm using this wonderful plugin and would like to know how I can set the first item to be open and the rest closed.
Any idea?
Javascript
var options = {
moreLink: '<a class="read_more_link" href="#">more...</a>',
lessLink: '<a class="read_less_link" href="#">less...</a>',
heightMargin: 50,
sectionCSS: 'display: inline-block; width: 100%;',
};
$('.content-top-wide, .content-bottom-item').each(function(){
var el = $(this), content = el.find('div:first,span:first,p:first, article:first'), maxHeight = 0;
if (content.length) {
maxHeight = content.outerHeight();
content.prevAll().each(function(){
maxHeight += $(this).outerHeight(true);
});
// set maxHeight to 200px if the element has hight greater than 200
options.maxHeight = Math.min(200, maxHeight);
el.readmore(options);
};
});
HTML
<div class="content-bottom pull-left">
<h2>Title</h2>
<div class="content-bottom-item pull-left">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus, consequatur inventore iure aliquam praesentium molestiae facilis labore! Magni, dolorem, ex? Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus, consequatur inventore iure aliquam praesentium molestiae facilis labore! Magni, dolorem, ex?
</div>
</div>
Read the documentation of the plugin: https://github.com/jedfoster/Readmore.js ?
Adding "startOpen: false" to the options of the first item should solve your problem.
I managed doing this by adding an if statement:
if ( i == 0) {
options.startOpen = true;
} else {
options.startOpen = false;
}
el.readmore(options);
Here is a working version in case someone need: http://jsfiddle.net/brunodd/pvZ8H/

Categories