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);
Related
window scrollIntoView doesn't work for safari and ipads. To resolve this issue, i have created a polyfill function following polyfill custom scroll.
Following is the code i have written for this polyfill function for scroll. it is working fine for the blog that i have shared above but this is not working in my code as the flow of the code and usage is same but still no luck.
function scroll(element) {
let start = null;
const target = element && element ? element.getBoundingClientRect().top : 0;
const firstPos = window.pageYOffset || document.documentElement.scrollTop;
let pos = 0;
(function () {
const browser = ['ms', 'moz', 'webkit', 'o'];
for (let x = 0, { length } = browser; x < length && !window.requestAnimationFrame; x++) {
window.requestAnimFrame = (function () {
return window.requestAnimationFrame
|| window.webkitRequestAnimationFrame
|| window.mozRequestAnimationFrame
|| function (callback) {
window.setTimeout(callback, 1000 / 60);
};
}());
window.cancelAnimationFrame = window[`${browser[x]}CancelAnimationFrame`]
|| window[`${browser[x]}CancelRequestAnimationFrame`];
}
}());
function showAnimation(timestamp) {
if (!start) { start = timestamp || new Date().getTime(); }
const elapsed = timestamp - start;
const progress = elapsed / 100;
const outQuad = function (n) {
return n * (2 - n);
};
const easeInPercentage = +(outQuad(progress)).toFixed(2);
console.log(easeInPercentage)
pos = (target === 0) ? (firstPos - (firstPos * easeInPercentage)) : (firstPos + (target * easeInPercentage));
window.scrollTo(0, pos);
if (target !== 0 && pos >= (firstPos + target) || target === 0 && pos <= 0) {
cancelAnimationFrame(start);
if (element) {
element.setAttribute('tabindex', -1);
element.focus();
}
pos = 0;
} else {
window.requestAnimationFrame(showAnimation);
}
}
window.requestAnimationFrame(showAnimation);
}
document.getElementById('seemorebutton')?.addEventListener('click', (e) => {
e.preventDefault();
scroll(document.getElementById('discoverEvents'));
});
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">
I have plugin jQuery-splitter that bind to document.documentElement:
$(document.documentElement).bind('mousedown.splitter touchstart.splitter', function(e) {
if (splitter_id !== null) {
current_splitter = splitters[splitter_id];
$('<div class="splitterMask"></div>').css('cursor', current_splitter.children().eq(1).css('cursor')).insertAfter(current_splitter);
current_splitter.settings.onDragStart(e);
}
}).bind('mouseup.splitter touchend.splitter touchleave.splitter touchcancel.splitter', function(e) {
if (current_splitter) {
$('.splitterMask').remove();
current_splitter.settings.onDragEnd(e);
current_splitter = null;
}
}).bind('mousemove.splitter touchmove.splitter', function(e) {
if (current_splitter !== null) {
var limit = current_splitter.limit;
var offset = current_splitter.offset();
if (current_splitter.orientation == 'vertical') {
var pageX = e.pageX;
if(e.originalEvent && e.originalEvent.changedTouches){
pageX = e.originalEvent.changedTouches[0].pageX;
}
var x = pageX - offset.left;
if (x <= current_splitter.limit) {
x = current_splitter.limit + 1;
} else if (x >= current_splitter.width() - limit) {
x = current_splitter.width() - limit - 1;
}
if (x > current_splitter.limit &&
x < current_splitter.width()-limit) {
current_splitter.position(x, true);
current_splitter.find('.splitter_panel').
trigger('splitter.resize');
//e.preventDefault();
}
} else if (current_splitter.orientation == 'horizontal') {
var pageY = e.pageY;
if(e.originalEvent && e.originalEvent.changedTouches){
pageY = e.originalEvent.changedTouches[0].pageY;
}
var y = pageY-offset.top;
if (y <= current_splitter.limit) {
y = current_splitter.limit + 1;
} else if (y >= current_splitter.height() - limit) {
y = current_splitter.height() - limit - 1;
}
if (y > current_splitter.limit &&
y < current_splitter.height()-limit) {
current_splitter.position(y, true);
current_splitter.find('.splitter_panel').
trigger('splitter.resize');
//e.preventDefault();
}
}
current_splitter.settings.onDrag(e);
}
});
And in user code when I use this code the click don't work when I click on splitter (div between panels) it work when I click on the panel.
var counter = 0;
$(document.documentElement).on('click', function(e) {
console.log('x');
var $target = $(e.target);
if ($target.is('.vsplitter, .hsplitter')) {
if (++counter == 2) {
console.log('double click');
$target.parents('.splitter_panel').eq(0).data('splitter').position(20);
counter = 0;
}
} else {
counter = 0;
}
});
When I comment out the $(document.documentElement).bind('mousedown.splitter touchstart.splitter' code I can double click on the splitter. Anybody have a clue why is this happening?
It was caused by .splitterMask div.
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.