NATIVE JavaScript only - element opacity change when scrolled into viewport - javascript

I'm trying to make the elements on the page fade in on scroll. Easy enough right? Not for me.
HTML is a standard list.
CSS sets all elements to opacity 0 prior to scrolling.
I'm trying to use Native JavaScript only.
// get current page body
var actBody = document.getElementById('acts-body');
// on scroll function
actBody.onscroll = function(){
// get screen height
var screenPosition = window.innerHeight;
// get all text elements
var artistName = document.getElementsByClassName('artist');
// loop through all elements
for(var i = 0; i < artistName.length; i++){
// get each elements position from top
var positionFromTop = artistName[i].getBoundingClientRect().top;
// if element is in viewport add class
if(positionFromTop - screenPosition <= 0){
artistName[i].classList.add('txt-fadeIn');
}
else{
artistName[i].classList.remove('txt-fadeIn');
}
console.log(artistName[i]);
}

i think it should solve it
if(screenPosition - positionFromTop <= 0){
artistName[i].classList.add('txt-fadeIn');
}

Related

How can I make text popup when I scroll to it?

I want the textblocks on my website to get bigger/popup when I scroll down to them. How can I do that?
I tried to google how to do that but I couldnĀ“t figure that out.
You need to use the IntersectionObserver API to detect when the text block is visible, then apply a CSS class.
Try this:
const element = document.querySelector('.text-block-1');
const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) {
element.classList.add('visible');
}
});
observer.observe(element);
And then use the visible class, like this:
.visible { color: red; font-size: 24px; }
Note that if you have multiple HTML elements using the same class, you will need to use document.querySelectorAll and create a loop to observe all elements.
This example will make the font size of the text blocks increase to 24px as they are scrolled into view.
window.addEventListener('scroll', function() {
var textBlock1 = document.getElementById('text-block-1');
var textBlock2 = document.getElementById('text-block-2');
// Get the position of the text blocks relative to the viewport
var rect1 = textBlock1.getBoundingClientRect();
var rect2 = textBlock2.getBoundingClientRect();
// Check if the text blocks are within the viewport
if (rect1.top < window.innerHeight && rect1.bottom > 0) {
textBlock1.style.fontSize = '24px';
}
if (rect2.top < window.innerHeight && rect2.bottom > 0) {
textBlock2.style.fontSize = '24px';
}
});

Get bootstrap accordion height

I'm trying to use HTML2Canvas with jsPDF to save some accordions to the pdf. Accordions are created dynamically with javascript and i'm trying to get their height to save them to pdf (i need to split the page at some point and save them in separate images because they're way too big). I've gathered all the accordions with their classname:
function gatherAccordions(){
//Launched on button click
var accordionArr = document.getElementsByClassName("akkordion");
for (var i = 0; i<accordionArr.length;i++){
console.log(accordionArr[i]);
console.log(accordionArr[i].clientHeight); //returns 0
}
}
Edit: as i read a bit more i got that .clientHeight will return 0 in case height is not set in CSS. I decided to try the jQuery approach which was highly suggested. Although it returned me -2 (which obviously can't be the right height).
function gatherAccordions(){
var accordionArr = document.getElementsByClassName("akkordion");
for (var i = 0; i<accordionArr.length;i++){
console.log(accordionArr[i]);
console.log($("#"+accordionArr[i].id).height()); //returns -2
}
}
Any ideas how could I approach this thing? I have to note that the accordions (as you can see from code below) are not the bottom elements of the accordion tree, there are several divs and other stuff below it. If i gave .height() to accordionBody and accordionhead separately i did recieve -20 and -31 as a result height, which also sounds weird (being negative). Also, when i added elements to the accordion body then the height of body did not increase although visually i can clearly tell that it did.
This builds the accordions:
/*
#Builds the head of accordion which contains main stats
*/
function buildAccordionHead(player){
//player has attributes: coef, ratio, pos, hasplayed, name, points
//This is the panel that holds the player main information (coef,name,pos etc)
var accordionHead = document.createElement("div");
accordionHead.className = "panel-heading";
accordionHead.dataset.parent = "#accordion";
accordionHead.dataset.toggle = "collapse";
accordionHead.setAttribute('href', "#id_"+player.pos);
//This is the container for positioning items
var container = document.createElement("div");
container.className = "container-fluid";
//Create playerrow (FN06)
var upper_row = rowCreate("KOHT","","K","S","P",true);
var playerRow = rowCreate(player.pos,player.name,player.coef,player.ratio,player.score,false);
//Add row(s) to the children of container
container.appendChild(upper_row);
container.appendChild(playerRow);
//Add container to the children of accordion head
accordionHead.appendChild(container);
return accordionHead;
}
/*
Builds the body of the accordion which contains history
*/
function buildAccordionBody(player,round){
//moving inside out!
//generates container-fluid element with a rows inside
if (even){
var containerfluid = historyRowEven(player);
}
else{
var containerfluid = historyRowOdd(player,round);
}
var bodyel = document.createElement("div");
bodyel.className = "panel-body";
bodyel.appendChild(containerfluid);
var collapser = document.createElement("div");
collapser.id = "id_"+player.pos;
collapser.className = "panel-collapse collapse";
collapser.appendChild(bodyel);
return collapser;
}
/*
The main builder function!
*/
function buildAccordion(player,round){
//This is outer panel
var accordionPanel = document.createElement("div");
accordionPanel.className = "panel panel-default akkordion";
var accordionHeading = buildAccordionHead(player);
var accordionBody = buildAccordionBody(player,round);
//Add accordion head to the children of accordion-panel
accordionPanel.appendChild(accordionHeading);
accordionPanel.appendChild(accordionBody);
accordionPanel.id = "collapser_id_"+player.pos;
//Add accordion-panel to the children of div with accordion
var mainElement = document.getElementById("accordion");
mainElement.appendChild(accordionPanel);
}

JavaScript scrolling events, fade in place?

I'm trying to pin some divs in place and fade them in and out as a user scrolls down. My code looks like this so far:
$(window).on("load",function() {
var fadeDuration = 500;
function fade() {
// compute current window boundaries
var windowTop = $(window).scrollTop(),
windowBottom = windowTop + $(window).innerHeight(),
focusElt = null;
// find our focus element, the first visible .copy element,
// with a short-circuiting loop
$('.imgdiv').toArray().some(function(e, i) {
var objectTop = $(e).offset().top;
if ((objectTop >= windowTop) && (objectTop <= windowBottom)) {
focusElt = e;
return true;
}
console.log(focusElt);
});
// obscure all others
$('.focus').not(focusElt)
.removeClass('focus')
.fadeTo(fadeDuration, 0);
// focus on our focus element; if was the previous focus, nothing
// to do; but if it wasn't focus / wasn't showing before, make
// it visible and have class focus
$(focusElt).not('.focus')
.addClass('focus')
.fadeTo(fadeDuration, 1);
}
fade(); //Fade in completely visible elements during page-load
$(window).scroll(function() {fade();}); //Fade in elements during scroll
});
Here's the corresponding fiddle that almost does what I'm looking for, but instead of the green "Fade In" blocks moving upward and fading, I want them pined in place near the top of the window. As the "IMG DIVs" move past them they will fade and reappear with each new "IMG DIV". Here, I'm focusing on the particular green block and fading it when it becomes the focus element. Instead, what I need to do is, focus on the IMG DIV blocks, add a "pinned" class to the green blocks when they reach the top of the page, and fade the green blocks in and out.
Does anyone have any advice?
Part 2 of my question is how to do this with native JavaScript, and not rely on jQuery's dependency.
Ok, so lets split your first issue into two issues :)
First of all, you want to (in general) do something when some element becomes visible in the viewport and when it becomes invisible. So, basically, all you need is function like that:
watchElementIsInViewport(
$('.imgdiv'),
doSomethingWhenElementAppearedInViewport,
doSomethingWhenElementOutOfViewport
);
You know, that when element becomes visible, you want to show some other element. When element becomes invisible, you want to hide that related element. So now, define those two functions:
function doSomethingWhenElementAppearedInViewport(element) {
// retrieve text related with the element
var $copy = $(element).next('.copy');
// fade it in
$copy.fadeTo(500, 1);
}
function doSomethingWhenElementGotOutOfViewport(element) {
// retrieve text related with the element
var $copy = $(element).next('.copy');
// fade it out
$copy.fadeTo(500, 0);
}
What about watchElementIsInViewport? There is no magic inside, only logic you already created, but decoupled from showing of finding elements.
function watchElementIsInViewport($elements, elementAppearedInViewport, elementGotOutOfViewport) {
var currentlyVisible = [ ];
// retrieve positions once, assume it won't change during script is working
var positions = getVerticalBoundaries($elements);
function _scrollHandler() {
var viewportTop = window.scrollY;
var viewportBottom = viewportTop + window.innerHeight;
$elements.each(function(index, element) {
var elementPosition = positions[index];
/* if you wish to check if WHOLE element is in viewport
* var elementIsInViewport = (elementPosition.top >= viewportTop) &&
* (elementPosition.bottom <= viewportBottom);
*/
var elementIsInViewport = (elementPosition.top < viewportBottom) &&
(elementPosition.bottom > viewportTop);
var elementIndexInCurrentlyVisible = currentlyVisible.indexOf(element);
// if element is visible but was not visible before
if(elementIsInViewport && (elementIndexInCurrentlyVisible === -1)) {
elementAppearedInViewport(element);
currentlyVisible.push(element);
// if element is not visible but was visible before
} else if(!elementIsInViewport && (elementIndexInCurrentlyVisible !== -1)) {
elementGotOutOfViewport(element);
currentlyVisible.splice(elementIndexInCurrentlyVisible, 1);
}
});
}
// initial check & update
_scrollHandler();
// check & update on every scroll
$(window).on('scroll', _scrollHandler);
}
And that's all. Working example.

JavaScript Jquery function that is triggered on event executes all at once instead of right time

I made a function that Is made to be trigered when user scrolls on a element on the page. In this case when user scrolls to an id then it fades in. The problem is that they fade in all at the same time with the first scroll instead of when they reaching the element That is supposed to allow it to fade in! Please help me make my function work.
Thanks a lot
var selected={
//// Storing selectors
items:[],
/// Function that stores items and hides them from the page
selectFunc: function(select) {
//// Store selected element
selected.items.push(select);
/// hide selector from the page
$(select).hide();
}
};
//// Function triggeres on scroll
$(window).scroll(function() {
/// loops trough the selected elements
for(i=0; i<selected.items.length; i++){
var currentItem = selected.items[i];
///// calculates your position and item position
var hT = $(currentItem).offset().top,
hH = $(currentItem).outerHeight(),
wH = $(window).height(),
wS = $(this).scrollTop();
////// check if you are in the position
if (wS > (hT+hH-wH)){
$( currentItem ).fadeIn( 2500 );
}
}
});
//// Using my function to select id about and p element in it.
selected.selectFunc("#about p");
selected.selectFunc("#about input");
In your for loop, you are doing an iteration for each element in selected.items. What's in there? Two strings: "#about p", and "#about input".
So for each of these selectors, you show them all. You need to get every element separately.
Another problem is that hiding these elements means they are not taking up the space they should on the page, so you might not be able to scroll down. You can solve that by changing their opacity instead of making them display:none (what .hide() is doing).
Here is your code with some modifications:
var selected = {
//// Storing selectors
items: [],
/// Function that stores items and hides them from the page
selectFunc: function(select) {
//// Store selected element
var items = $(select);
for (var i = 0, l = items.length; i < l; i++) selected.items.push(items[i]);
/// hide selector from the page
items.css('opacity', 0);
}
};
//// Function triggeres on scroll
$(window).scroll(function() {
/// loops trough the selected elements
for (i = 0; i < selected.items.length; i++) {
var currentItem = selected.items[i];
///// calculates your position and item position
var hT = $(currentItem).offset().top,
hH = $(currentItem).outerHeight(),
wH = $(window).height(),
wS = $(this).scrollTop();
////// check if you are in the position
if (wS > (hT + hH - wH)) {
$(currentItem).animate({
'opacity': 1
}, 2500);
}
}
});
//// Using my function to select id about and p element in it.
selected.selectFunc("#about p");
selected.selectFunc("#about input");
// Simulating a scroll to show the first elements
$(window).scroll();
JS Fiddle Demo

How to count numbers of line in a textarea

I want to make a dynamic textarea, it should increase in rows as the content increase.
I am using this code:
$("#text_textarea").keyup(function(e) {
//splitting textarea value wrt '\n' to count the number of lines
if ($(this).val().lastIndexOf('\n')!=-1)
var x = $(this).val().split('\n');
$(this).attr( "rows" , x.length+1 );
});
But it fails when user continues to write without giving any new line \n (pressing Enter).
var keyUpTimeout = false; // Required variables for performance
var keyupTimer = 0;
$("#text_textarea").keyup(function(e) {
var cooldownTimeout = 500;
//Set the cooldown time-out. The height check will be executed when the user
// hasn't initiated another keyup event within this time
var ths = this;
function heightCheck(){
keyupTimer = false;
// Reset height, so that the textarea can shrink when necessary
ths.style.height = "";
// Set the height of the textarea
var newheight = this.scrollHeight + 2;
ths.style.height = newheight + "px";
}
if(keyupTimeout){ //Has a cooldown been requested?
clearTimeout(keyupTimer); //This+next line: Refresh cooldown timeout.
keyUpTimer = setTimeout(heightCheck, cooldownTimeout);
return; //Return, to avoid unnecessary calculations
}
// Set a cooldown
keyupTimer = setTimeout(heightCheck, cooldownTimeout);
keyupTimeout = true; //Request a cooldown
});
This piece of script will change the height of the textarea to fit the text inside.
Update
I have added an additional feature: To improve performance (changing the CSS height requires a significant amount of computer power), I have added a cooldown effect: The height check will only be executed when the user hasn't initiated a keyup event for 500 milliseconds (adjust this value to meet your wishes).
read this,
Textarea Height increase
TextAreaExpander (Demo)
autoResize Plugin
JQuery Elastic
You should use the attribute wrap='hard' on your textarea.
I write this code. what about it..
$("#text_textarea").keyup(function(e) {
var textarea_height = Number($(this).css('height').replace("px", ""))+4;
var scroll_height = this.scrollHeight;
if(textarea_height < scroll_height ){
$(this).css('height' ,"");
var x = Number(scroll_height) + 3;
if(x != $(this).height())
$(this).css("height", x+"px");
}
});

Categories