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();.
Related
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
I have this code (make element ".aaa" margin-bottom equal to element ".bbb" height):
$('.aaa').css( 'margin-bottom', $('.bbb').css('height'));
It works but... how to make it to work dynamically if ".bbb" elements have varying heights?
I am very sorry, but I do not know how to explain it better.
Edit: Sorry, this is a code sample to better understand what I mean: https://jsfiddle.net/d77n9ajx/1/
Should be like the first one.
Try the following code:
$('.aaa').css('margin-bottom', $('#bbb').height() + 'px');
You can use the jQuery method outerHeight() to get .bbb height.
.outerHeight( [includeMargin ] ) Returns: Number
Description: Get the
current computed height for the first element in the set of matched
elements, including padding, border, and optionally margin. Returns a
number (without "px") representation of the value or null if called on
an empty set of elements.
After you get .bbb height you assign it to .aaa margin-bottom property with .css() function.
Code Snippet:
(function() {
var a = $(".aaa"),
b = $(".bbb");
var bOuterHeight = b.outerHeight();
a.css("margin-bottom", bOuterHeight);
var aMarginBottom = a.css("margin-bottom");
console.log("bbb height:" + b.outerHeight() + " aaa margin bottom:" + aMarginBottom);
})();
* {
box-sizing: border-box;
}
div {
height: 50px;
}
.aaa {
background-color: gold;
}
.bbb {
background-color: purple;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="aaa"></div>
<div class="bbb"></div>
This is only an example, the objective is that you add the code:
$('.aaa').css( 'margin-bottom', $('.bbb').css('height'));
in the event that resize the element bbb
function ChangeDivSize(){
$('.bbb').height(100);
$('.aaa').css( 'margin-bottom', $('.bbb').css('height'));
}
.aaa{
background-color:red;
height:100px;
margin-bottom: 10px;
}
.bbb{
background-color: blue;
height:50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="aaa"></div>
<div class="bbb"></div>
<input type="button" value="Change Div Size" onclick="ChangeDivSize()" />
This is not very neat, but it should work.
var previousHeight = null;
setInterval(function()
{
var height = $('.bbb').height();
if (height == previousHeight)
return;
$('.aaa').css('margin-bottom', height);
previousHeight = height;
}, 10);
animate();
function animate()
{
$('.bbb').animate({ height: '0px' }, 1000, function()
{
$('.bbb').animate({ height: '100px' }, 1000, animate);
});
}
.aaa {
background: red;
height: 10px;
}
.bbb {
background: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="aaa"></div>
<div class="bbb"></div>
Here's a solution for your problem.
The code properly resizes aaa margin-bottom in case your bbb div changes as well.
HTML
<div class="aaa">Test the code</div>
<div class="bbb">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </div>
jQuery
<script type="text/javascript">
$(document).ready(function(){
var bheight=$('.bbb').height();
$('.aaa').css('margin-bottom',bheight);
new ResizeSensor($('.bbb'), function() {
bheight=$('.bbb').height();
$('.aaa').css('margin-bottom',bheight);
}); //Function runs incase bbb div changes size
});
</script>
Please do include the following scripts to run your code:
<script src="js/jquery.min.js"></script>
<script src="js/ElementQueries.js"></script>
<script src="js/ResizeSensor.js"></script>
These .js files are my local versions. You do download it for yourself. You can find ElementQueries.js and ResizeSensor.js in following link:http://marcj.github.io/css-element-queries/
Hope this satisfies your concern!!
Since you have more .aaa and .bbb elements you should use each().
var calculateMargin = function(){
// Make ".aaa" margin-bottom equal to ".bbb" height
$('.aaa').each(function(){
$(this).css( 'margin-bottom', $(this).next('.bbb').css('height'));
});
};
calculateMargin();
$(window).on('resize', function() {
calculateMargin();
});
.wrap {
position: relative;
float: left;
margin: 10px;
}
.aaa {
width: 200px;
height: 200px;
background-color: pink;
}
.bbb {
position: absolute;
bottom: 0;
left: 0;
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<div class="wrap">
<div class="aaa"></div>
<div class="bbb">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Non recusandae ipsa cum eum aspernatur sint eligendi. Accusantium, veniam, porro voluptatum dolorem deleniti laborum sapiente...
</div>
</div>
<div class="wrap">
<div class="aaa"></div>
<div class="bbb">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Non recusandae ipsa cum eum...
</div>
</div>
<div class="wrap">
<div class="aaa"></div>
<div class="bbb">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Non recusandae ipsa cum eum aspernatur sint eligendi. Accusantium, veniam, porro...
</div>
</div>
<div class="wrap">
<div class="aaa"></div>
<div class="bbb">
Lorem ipsum dolor sit amet...
</div>
</div>
<div class="wrap">
<div class="aaa"></div>
<div class="bbb">
Lorem ipsum dolor sit amet, consectetur adipisicing elit....
</div>
</div>
<div class="wrap">
<div class="aaa"></div>
<div class="bbb">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Non recusandae ipsa cum eum aspernatur sint eligendi. Accusantium, veniam, porro voluptatum dolorem...
</div>
</div>
or if .bbb will not always be the next sibling of .aaa, but will be within the same container; than:
$('.aaa').each(function(){
$(this).css( 'margin-bottom', $(this).parent().find('.bbb').first().css('height'));
});
Both will work in your example.
Based on #mbadeveloper try this:
$( ".bbb" ).resize(function() {
$( ".aaa" ).css( "margin-bottom" , $( ".bbb" ).height());
});
Hope the syntax is correct :/
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);
})
}
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>
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/