I'm trying to initiate a function when a user clicks on a button.
At the moment it initiates when the site is loaded and when a user scrolls or resizes the browser. But how do I get it to work when a user clicks on a specific button. At the momment the button has a onclick="sort();".
var lazy = [];
registerListener('load', setLazy);
registerListener('load', lazyLoad);
registerListener('scroll', lazyLoad);
registerListener('resize', lazyLoad);
document.getElementById('sort').addEventListener('click', function() {
});
function setLazy(){
lazy = document.getElementById('img-loading').getElementsByTagName('img');
// console.log('Found ' + lazy.length + ' lazy images');
}
function lazyLoad(){
console.log('lazyLoad initiated');
for(var i=0; i<lazy.length; i++){
if(isInViewport(lazy[i])){
if (lazy[i].getAttribute('data-src')){
lazy[i].src = lazy[i].getAttribute('data-src');
lazy[i].removeAttribute('data-src');
}
}
}
cleanLazy();
console.log('lazyLoad END');
}
function cleanLazy(){
lazy = Array.prototype.filter.call(lazy, function(l){ return l.getAttribute('data-src');});
}
function isInViewport(el){
var rect = el.getBoundingClientRect();
return (
rect.bottom >= 0 &&
rect.right >= 0 &&
rect.top <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.left <= (window.innerWidth || document.documentElement.clientWidth)
);
}
function registerListener(event, func) {
if (window.addEventListener) {
window.addEventListener(event, func)
} else {
window.attachEvent('on' + event, func)
}
}
var button=document.getElementById('button'),
clickFunction=function(button){
alert('click');
};
button.addEventListener('click',clickFunction);
<input id="button" type="button" value="test">
Related
useEffect(() => {
const maybeHandler = (event: MouseEvent) => {
menuData.forEach((el) => {
if (el.hasActiveDropdown && event.clientY > 50) {
handleCloseDropDown();
// handleDropDown('0');
}
});
};
document.addEventListener('mousedown', maybeHandler);
return () => document.removeEventListener('mousedown', maybeHandler);
}, [handleCloseDropDown, menuData]);
I am used this useEffect to handle mulltip dropdowns in navbar component,
navbar has fix height 50px so my logic is whenver use click outside the navbar the drop downs all are close.
I am unadble to test in JEST this clientY propery
For my project I basically had a function that detected when the scroll happens This Project Was In React TypeScript
window.addEventListener('wheel', onScroll);
window.addEventListener('touchstart', handleTouchStart);
window.addEventListener('touchmove', handleTouchMove);
and it calls back to onScroll
function onScroll(e:any) {
if(Math.abs(e.deltaY) <= 35 || Scrolled) return;
Scrolled = true;
//console.log(e.deltaY);
let direction = e.deltaY;
//console.log(page);
if(direction > 0) page++;
if(direction < 0) page--;
//console.log(page);
if(page <= 0) page = (0);
if(page >= (pagesRef.current.length-1)) page = (pagesRef.current.length-1);
pagesRef.current[page].scrollIntoView({behavior: "smooth"});
setTimeout(()=>{Scrolled=false},800);
}
and for touch / mobile devices
function handleTouchStart(evt:any) {
const firstTouch = getTouches(evt)[0];
xDown = firstTouch.clientX;
yDown = firstTouch.clientY;
};
function handleTouchMove(evt:any) {
if ( ! xDown || ! yDown ) {
return;
}
var xUp = evt.touches[0].clientX;
var yUp = evt.touches[0].clientY;
var xDiff = xDown - xUp;
var yDiff = yDown - yUp;
if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {/*most significant*/
if ( xDiff > 0 ) {
/* right swipe */
} else {
/* left swipe */
}
} else {
if ( yDiff > 0 ) {
page++;
} else {
page--;
}
}
if(page <= 0) page = (0);
if(page >= (pagesRef.current.length-1)) page = (pagesRef.current.length-1);
pagesRef.current[page].scrollIntoView({behavior: "smooth"});
/* reset values */
xDown = null;
yDown = null;
};
Hope this can help
I need your help because I've been on a project for hours and can't make any headway. An "animated" counter is to be installed on our website. This shows, for example, the monthly cost savings. The following code works great so far.
<script>
/* <![CDATA[ */
var ersparnis = 4600;
var inv = setInterval(function() {
if(ersparnis < 4800)
document.getElementById("counter_ersparnis").innerHTML = ++ ersparnis;
else
clearInterval(inv);
}, 500 / 100);
/*]]>*/
</script>
<h2>
+ <span id="counter_ersparnis"></span> €
</h2>
But now I want the Javascript to start only when the user scrolls to the relevant point. I have now tried to do this with a jQuery code from the Internet, but without success!
<script>
/* <![CDATA[ */
jQuery.fn.isOnScreen = function()
{
var win = jQuery(window);
var viewport = {
top : win.scrollTop(),
left : win.scrollLeft()
};
viewport.right = viewport.left + win.width();
viewport.bottom = viewport.top + win.height();
var bounds = this.offset();
bounds.right = bounds.left + this.outerWidth();
bounds.bottom = bounds.top + this.outerHeight();
return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));
};
jQuery(window).scroll(function()
{
if(jQuery('#element').isOnScreen())
{
var ersparnis = 4600;
var inv = setInterval(function() {
if(ersparnis < 4800)
document.getElementById("counter_ersparnis").innerHTML = ++ ersparnis;
else
clearInterval(inv);
}, 500 / 100);
/*]]>*/
</script>
<h2>
+ <span id="counter_ersparnis"></span> €
</h2>
} }
By the way, the whole thing should be implemented on a Jimdo site, so I also added the database with the following code in the head area.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js" type="text/javascript"></script>
You might hear it already, I'm not really familiar with CSS / HTML and Javascript. So it would be great if someone could offer me a plug and play solution. I usually get it rewritten, but not tinkered together (because I want three of these counters next to each other.
Try This im not a big proponent of jquery so its plain JavaScript.
const targetElement = document.querySelector('#element');
let isCounting = false;
var inv;
document.addEventListener('scroll', function(e) {
const bounding = targetElement.getBoundingClientRect();
if (
bounding.top >= 0 &&
bounding.left >= 0 &&
bounding.right <= (window.innerWidth || document.documentElement.clientWidth) &&
bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight)
) {
if(!isCounting ){
var ersparnis = 4600;
inv = setInterval(function() {
document.getElementById("counter_ersparnis").innerHTML = ++ ersparnis;
}, 500 / 100);
isCounting = true;
}
}else{
isCounting = false;
clearInterval(inv);
}
});
To make the code a bit cleaner and reuseable you could do this.
const targetElement = document.querySelector('#element');
let isCounting = false;
let inv;
const isVisible = function (elem) {
var bounding = elem.getBoundingClientRect();
return (
bounding.top >= 0 &&
bounding.left >= 0 &&
bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
);
};
function startCounter(){
var ersparnis = 4600;
inv = setInterval(function() {
document.getElementById("counter_ersparnis").innerHTML = ++ ersparnis;
}, 500 / 100);
isCounting = true;
}
function stopCounter(){
clearInterval(inv);
isCounting = false;
}
document.addEventListener('scroll', function(e) {
const visible = isVisible( targetElement );
if( visible && !isCounting ){
startCounter();
}else if( !visible && isCounting ){
stopCounter();
}
});
You can use Intersection Observer API to observe changes in the intersection of a target element with an ancestor element or with a top-level document's viewport:
let options = {
root: null, //--> viewport if it is null
rootMargin: '0px',
threshold: 1.0
}
const callback = function(entries, observer) {
entries.forEach(entry => {
let ersparnis = 4600;
const inv = setInterval(function() {
if (ersparnis < 4800)
entry.target.innerHTML = ++ersparnis;
else
clearInterval(inv);
}, 500 / 100);
});
};
let observer = new IntersectionObserver(callback, options);
const target = document.querySelector('#counter_ersparnis');
observer.observe(target);
I have a page with an iframe... Currently i used this code to load iframe onscroll....
Javascript:
function lazyLoad() {
for (var e = document.getElementsByClassName("lazy"), t = 0; t < e.length; t++) isInViewport(e[t]) && (e[t].src = e[t].getAttribute("data-src"))
}
function isInViewport(e) {
var t = e.getBoundingClientRect();
return t.bottom >= 0 && t.right >= 0 && t.top <= (window.innerHeight || document.documentElement.clientHeight) && t.left <= (window.innerWidth || document.documentElement.clientWidth)
}
function registerListener(e, t) {
window.addEventListener ? window.addEventListener(e, t) : window.attachEvent("on" + e, t)
}
registerListener("load", lazyLoad), registerListener("scroll", lazyLoad);
HTML:
<iframe data-src='http://some-link.com' src='' class='lazy'/>
But when I scroll again even if only slightly, the iframe is re-loaded again. Can anyone help me to create iframe is not loaded again after i scroll for the second time? Thank you!
DEMO: http://design-jarwo.blogspot.co.id/ and i'll use it on my blog www.kodejarwo.com
You must remove the scroll event listener after firing it:
function onScroll () {
if (lazyLoad()) {
window.removeEventListener('scroll', onScroll);
}
}
function onLoad () {
lazyLoad();
}
function lazyLoad() {
var loaded = false;
for (var e = document.getElementsByClassName("lazy"), t = 0; t < e.length; t++) {
isInViewport(e[t]) && (e[t].src = e[t].getAttribute("data-src"));
loaded = true;
}
return loaded;
}
function isInViewport(e) {
var t = e.getBoundingClientRect();
return t.bottom >= 0 && t.right >= 0 && t.top <= (window.innerHeight || document.documentElement.clientHeight) && t.left <= (window.innerWidth || document.documentElement.clientWidth)
}
function registerListener(e, t) {
window.addEventListener ? window.addEventListener(e, t) : window.attachEvent("on" + e, t)
}
registerListener("load", onLoad), registerListener("scroll", onScroll);
I'm working on this page. Main structure is some DIVs beneath each other. I need to do some transitions or animations when user scrolls from one to another. The height of the DIVs aren't the same. it is done only by min-height:100%. My JS doesn't work when I try to do any alert at the end of the DIV.
<div id="page">
<div class="section section_1"> ...content...</div>
<div class="section section_2">...content...</div>
<div class="section section_3">...content...</div>
<div class="section section_4">...content...</div>
</div>
This is the JS file
jQuery(
$('.section').on('scroll', function () {
if ($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) {
alert('end of div');
}
})
);
Do you have any ideas why this doesn't work? Or can you suggest me any other solution how to make this kind of animation?
Try This:
jQuery(function($) {
$('.section').bind('scroll', function() {
if($(this).scrollTop() + $(this).innerHeight() >= this.scrollHeight) {
alert('end reached');
}
})
});
Code Example for Local
Question's already been answered here.
Edited
Bind your alert as such:
var shown = document.getElementById("page").children;
function callback () {
alert('end of div');
}
function isElementInViewport(el) {
var eap,
rect = el.getBoundingClientRect(),
docEl = document.documentElement,
vWidth = window.innerWidth || docEl.clientWidth,
vHeight = window.innerHeight || docEl.clientHeight,
efp = function (x, y) { return document.elementFromPoint(x, y) },
contains = "contains" in el ? "contains" : "compareDocumentPosition",
has = contains == "contains" ? 1 : 0x14;
// Return false if it's not in the viewport
if (rect.right < 0 || rect.bottom < 0
|| rect.left > vWidth || rect.top > vHeight)
return false;
// Return true if any of its four corners are visible
return (
(eap = efp(rect.left, rect.top)) == el || el[contains](eap) == has
|| (eap = efp(rect.right, rect.top)) == el || el[contains](eap) == has
|| (eap = efp(rect.right, rect.bottom)) == el || el[contains](eap) == has
|| (eap = efp(rect.left, rect.bottom)) == el || el[contains](eap) == has
);
}
function fireIfElementVisible (el, callback) {
return function () {
if ( isElementInViewport(el) ) {
callback();
}
}
}
var handler = fireIfElementVisible (shown[shown.length - 1], callback);
$(document).on('DOMContentLoaded load resize scroll', handler);
Above function will return boolean on whether your element is currently viewable on screen.
A link to the Plunker.
I've been working on a button and list system in jQuery for awhile now. Recently I decided to make my code more reproducible. I want to make it so I just have to add classes or IDs, and I don't have to add any additional code. I'm very close to doing that for my entire site. So if you go to this site specifically you will see it in action.
If you click on any buttons, in any order, it will arrange chronologically.
The bugs come from closing them.
If you click at least three, close the middle one, then click a new button, the sort function falls apart and that closed middle one is now floating with the wrong class.
Below is my current jQuery. On my site, ignore the "All Years" button. I'll work on that after I figure out this bug.
//the variables needed for the floating buttons
var groupArray = $(".yearGroup");
var buttonArray = $(".buttonGroup");
var hideGroupArray = $(".hideGroup");
var closeBarArray = $(".closeBar");
var closeBar = $("#allCloseBar");
var allButtonArray = [];
sortElements = function(a,b)
{
if (a.text() < b.text())
{
return -1;
}
else if (a.text() > b.text())
{
return 1;
}
else
{
return 0;
}
}
$.each(buttonArray, function(i, item) {
$(this).click(function(){
console.log($(buttonArray[i]).text())
console.log($(closeBarArray[i]).text())
//for removing the tooltip when the button is clicked. Mostly for Firefox bug
$(".ui-tooltip-content").parents('div').remove();
$(hideGroupArray[i-1]).slideToggle(slideToggleDuration, function(){
htmlBody.animate({scrollTop: $(groupArray[i-1]).offset().top - 25}, {duration: timeDuration, easing: 'easeOutBack'});
$(buttonArray[i]).toggleClass("float", 1200);
if ($(groupArray[i-1]).height() > 0)
{
//This will stop any animations if the user scrolls.
htmlBody.bind("scroll mousedown DOMMouseScroll mousewheel keyup", function(e)
{
if ( e.which > 0 || e.type === "mousedown" || e.type === "mousewheel"){
htmlBody.stop().unbind('scroll mousedown DOMMouseScroll mousewheel keyup');
}
});
closeBar.addClass("floatCloseBar");
$(closeBarArray[i]).hide();
allButtonArray.splice(0, 0, $(buttonArray[i]));
var timer;
var delay = 1500;
$(buttonArray[i]).hover(function() {
//This will stop any animations if the user scrolls.
htmlBody.bind("scroll mousedown DOMMouseScroll mousewheel keyup", function(e)
{
if ( e.which > 0 || e.type === "mousedown" || e.type === "mousewheel"){
htmlBody.stop().unbind('scroll mousedown DOMMouseScroll mousewheel keyup');
}
});
var link = $(groupArray[i-1]);
var offset = link.offset();
var top2 = offset.top;
var left = offset.left;
var bottom = top2 + $(groupArray[i-1]).outerHeight();
//bottom = Math.abs(bottom - offset.top);
var right = $(window).width() - link.width();
right = Math.abs(offset.left - right);
var scrollDuration = 0;
if (inRange($(buttonArray[i]).offset().top, $(groupArray[i-1]).position().top, bottom))
{
//console.log("fast");
scrollDuration = 500;
//$(group).addClass("hoverYear");
}
else if ($(buttonArray[i]).offset().top <= $(groupArray[i-1]).offset().top && allButtonArray.length == 1)
{
//console.log("fast");
scrollDuration = 500;
//$(group).removeClass("hoverYear");
}
else if ($(buttonArray[i]).offset().top > 495 && $(buttonArray[i]).offset().top < 1700 && !inRange($(buttonArray[i]).offset().top, $(groupArray[i-1]).position().top, bottom))
{
scrollDuration = 1000;
//console.log("slow");
//$(group).removeClass("hoverYear");
}
else if ($(buttonArray[i]).offset().top > 1701 && $(buttonArray[i]).offset().top < 3000 && !inRange($(buttonArray[i]).offset().top, $(groupArray[i-1]).position().top, bottom))
{
scrollDuration = 1500;
//console.log("slower");
//$(group).removeClass("hoverYear");
}
else if ($(buttonArray[i]).offset().top > 3001 && $(buttonArray[i]).offset().top < 6000 && !inRange($(buttonArray[i]).offset().top, $(groupArray[i-1]).position().top, bottom))
{
scrollDuration = 2000;
//console.log("much slower");
//$(group).removeClass("hoverYear");
}
else if ($(buttonArray[i]).offset().top > 6001 && !inRange($(buttonArray[i]).offset().top, $(groupArray[i-1]).position().top, bottom))
{
scrollDuration = 2500;
console.log("the slowest");
//$(group).removeClass("hoverYear");
}
else
{
scrollDuration = 500;
}
//to prevent the various hover states to take control when the button isn't floating
if (!($(buttonArray[i])).hasClass("float"))
{
scrollDuration = 0;
console.log("doesnt have class")
}
// on mouse in, start a timeout
timer = setTimeout(function() {
//the delay for the hover scroll feature
htmlBody.animate({scrollTop: $(groupArray[i-1]).offset().top}, scrollDuration, 'easeInOutCubic');
}, delay);
}, function() {
// on mouse out, cancel the timer
clearTimeout(timer);
});
$.each(allButtonArray, function(j, val){
$(allButtonArray[j]).appendTo(closeBar);
console.log(allButtonArray.length);
arrowDown.show();
arrowUp.show();
arrowDown.prependTo(closeBar);
arrowUp.appendTo(closeBar);
//Changes the width of the buttons based upon how many are on the screen
if (allButtonArray.length > 7)
{
$("float").css('width', '7%');
$(val).css('width', '7%');
$(allButtonArray[0]).css('width','7%');
allButtonArray.sort(sortElements);
//console.log(val);
}
else if (allButtonArray.length <= 7)
{
$(val).css("width", '10%');
$("float").css("width", '10%');
allButtonArray.sort(sortElements);
//console.log(val);
}
});
}
if ($(groupArray[i-1]).height() == 0)
{
$(buttonArray[i]).css("width", '50%');
allButtonArray.splice(allButtonArray.indexOf($(buttonArray[i])), 1);
console.log(allButtonArray.length);
$(closeBarArray[i]).show();
$(buttonArray[i]).appendTo($(closeBarArray[i]));
arrowDown.show();
arrowUp.show();
arrowDown.prependTo(closeBar);
arrowUp.appendTo(closeBar);
}
if (group2001.height() == 0 && group2002.height() == 0 && group2003.height() == 0 && group2004.height() == 0 && group2005.height() == 0 && group2006.height() == 0 && group2007.height() == 0
&& group2008.height() == 0 && group2009.height() == 0 && group2010.height() == 0 && group2011.height() == 0 && group2012.height() == 0)
{
$(closeBarArray[i]).removeClass("floatCloseBar");
htmlBody.animate({scrollTop: revealAllButton.offset().top - 75}, 500);
arrowDown.hide();
arrowUp.hide();
//console.log($(document).height() + " the current height");
}
});
$(buttonArray[i]).toggleClass("openClose");
$(buttonArray[i]).toggleClass("openClose2");
});
});
function inRange(x, min, max){
return (x >= min && x <= max);
}
If you would like a reference to what worked previously, I could post that code. It is much more bulky and much less organized. I've tried many different things to eliminate the bug but I'm at a loss. My knowledge of JS scope is limited.
And thanks for any help, it is very much appreciated.