When I click I on load more link it load more results I need to change it from when I click to link when I Scroll To AJAXloaded Div
My Html Code
<div id="AJAXloaded">
<div class="loadmore">
<ul class="pagination">
<li class="active">
<a id="load-more">مشاهدة المزيد ...
<img id="lodingGif" src="{{Request::root()}}/public/upload/logo/loading.gif" height="25" width="25" style="display: none;">
</a>
</li>
</ul>
</div>
</div>
My JS Code
$(document).on("click","#load-more",function() {
page=page+1;
loadMoreData(page);
});
This is a perfect use case for the IntersectionObserver API
From the docs:
The Intersection Observer API provides a way to asynchronously observe
changes in the intersection of a target element with an ancestor
element or with a top-level document's viewport. [...] Intersection
information is needed for many reasons, such as:
Implementing "infinite scrolling" web sites, where more and more content is loaded and rendered as you scroll, so that the user doesn't
have to flip through pages.
var options = {
root: document.querySelector('#AJAXloaded'),
rootMargin: '0px',
threshold: 0,
};
var observer = new IntersectionObserver(callback, options);
function callback() {
// element scrolled into viewport
}
Browser support is quite good (except for IE). If you need to support older browsers there are a couple of polyfills available. But since they use polling and don't work in every situation I would personally just leave the button for those browsers and remove it for browsers supporting IntersectionObserver.
var supportsIntersectionObserver = 'IntersectionObserver' in window;
if(supportsIntersectionObserver) { button.remove(); }
How to add infinite scrolling to Blogger blogs?
If you don’t care about the details and you only want to enable the feature on your blog, click on the button below and add the code to your blog. Infinite scrolling should just work on your blog, in most cases. If you have a custom template, though, you may need to tweak the code a little. (Scroll down to “Frequently asked question” section for details.
If clicking on this button does nothing, or it doesn’t work for some reason, you can add this code manually:
Add a HTML/JavaScript gadget to your blog.
Leave the gadget’s title empty.
Paste the following code as the gadget’s content:
(function($) {
var loadingGif = 'https://lh3.googleusercontent.com/-FiCzyOK4Mew/T4aAj2uVJKI/AAAAAAAAPaY/x23tjGIH7ls/s32/ajax-loader.gif';
var olderPostsLink = '';
var loadMoreDiv = null;
var postContainerSelector = 'div.blog-posts';
var loading = false;
var win = $(window);
var doc = $(document);
// Took from jQuery to avoid permission denied error in IE.
var rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi;
function loadDisqusScript(domain) {
$.getScript('http://' + domain + '.disqus.com/blogger_index.js');
}
function loadMore() {
if (loading) {
return;
}
loading = true;
if (!olderPostsLink) {
loadMoreDiv.hide();
return;
}
loadMoreDiv.find('a').hide();
loadMoreDiv.find('img').show();
$.ajax(olderPostsLink, {
'dataType': 'html'
}).done(function(html) {
var newDom = $('<div></div>').append(html.replace(rscript, ''));
var newLink = newDom.find('a.blog-pager-older-link');
var newPosts = newDom.find(postContainerSelector).children();
$(postContainerSelector).append(newPosts);
// Loaded more posts successfully. Register this pageview with
// Google Analytics.
if (window._gaq) {
window._gaq.push(['_trackPageview', olderPostsLink]);
}
// Render +1 buttons.
if (window.gapi && window.gapi.plusone && window.gapi.plusone.go) {
window.gapi.plusone.go();
}
// Render Disqus comments.
if (window.disqus_shortname) {
loadDisqusScript(window.disqus_shortname);
}
// Render Facebook buttons.
if (window.FB && window.FB.XFBML && window.FB.XFBML.parse) {
window.FB.XFBML.parse();
}
// Render Twitter widgets.
if (window.twttr && window.twttr.widgets && window.twttr.widgets.load) {
window.twttr.widgets.load();
}
if (newLink) {
olderPostsLink = newLink.attr('href');
} else {
olderPostsLink = '';
loadMoreDiv.hide();
}
loadMoreDiv.find('img').hide();
loadMoreDiv.find('a').show();
loading = false;
});
}
function getDocumentHeight() {
return Math.max(
win.height(),
doc.height(),
document.documentElement.clientHeight);
}
function handleScroll() {
var height = getDocumentHeight();
var pos = win.scrollTop() + win.height();
if (height - pos < 150) {
loadMore();
}
}
function init() {
if (_WidgetManager._GetAllData().blog.pageType == 'item') {
return;
}
olderPostsLink = $('a.blog-pager-older-link').attr('href');
if (!olderPostsLink) {
return;
}
var link = $('Load more posts');
link.click(loadMore);
var img = $('<img src="' + loadingGif + '" style="display: none;">');
win.scroll(handleScroll);
loadMoreDiv = $('<div style="text-align: center; font-size: 150%;"></div>');
loadMoreDiv.append(link);
loadMoreDiv.append(img);
loadMoreDiv.insertBefore($('#blog-pager'));
$('#blog-pager').hide();
}
$(document).ready(init);
})(jQuery);
Related
I have a working bottom function in JavaScript to detect if the user scrolls at the bottom. However, a problem comes when the user has a strange resolution (like windows scale) or when you zoom. The function is not working anymore and can't detect the bottom.
Here is what I did :
const bottom = e.target.scrollHeight - e.target.scrollTop === e.target.clientHeight;
if (bottom) {
this.props.getNewValues();
}
Is there a way to avoid that? Even when you don't zoom, this is not working for people displaying the site on a TV or something like this (like a friend of mine did)
Thanks you
EDIT : I'm applying this on a precise element and I repeat that my solution is working except by unzooming. Unzooming provides float values that made the response not really accurate (it goes from 1 to 50px of difference based on the zoom made)
I use this function (can't take credit as someone else wrote it - sorry for no credit - it was ages ago). Maybe you can adapt this to your use case:
(function($) {
//CHECK SCROLLED INTO VIEW UTIL
function Utils() {
}
Utils.prototype = {
constructor: Utils,
isElementInView: function (element, fullyInView) {
var pageTop = $(window).scrollTop();
var pageBottom = pageTop + $(window).height();
var elementTop = $(element).offset().top;
var elementBottom = elementTop + $(element).height();
if (fullyInView === true) {
return ((pageTop < elementTop) && (pageBottom > elementBottom));
} else {
return ((elementTop <= pageBottom) && (elementBottom >= pageTop));
}
}
};
var Utils = new Utils();
//END CHECK SCROLLED INTO VIEW UTIL
//USING THE ELEMENT IN VIEW UTIL
//this function tells what to do do when the element is or isnt in view.
//var inView = Utils.isElementInView(el, false); Where FALSE means the element doesnt need to be completely in view / TRUE would mean the element needs to be completely in view
function IsEInView(el) {
var inView = Utils.isElementInView(el, false);
if(inView) {
//console.log('in view');
} else {
//console.log('not in view');
}
};
//Check to make sure the element you want to be sure is visible is present on the page
var variableOfYourElement = $('#variableOfYourElement');
//if it is on this page run the function that checks to see if it is partially or fully in view
if( variableOfYourElement.length ) {
//run function on page load
IsEInView(variableOfYourElement);
//run function if the element scrolls into view
$(window).scroll(function(){
IsEInView(variableOfYourElement);
});
}
//END USING THE ELEMENT IN VIEW UTIL
})(jQuery);
i'm searching for solution, that can expand SafeFrame custom ad from inside of custom creative in Google DFP, is that possible somehow?
There are 2 possible solutions:
1) using SafeFrame API
pros:
u can use it "out of the box"
you can use it on any website, no custom code on website is needed
it's safe to use
cons:
it's limited to fill just visible area of website
need to wait, until ad unit is visible to the user
2) code your own API with window.postMessage() javascript method
cons:
you need to add custom code to your website
it's a possible threat, if you use some 3th party creatives
pros:
you can do almost anything with your website from your creative
1) using SafeFrame API
This API is realatively easy to use, you can see some examples in
GPT Safeframe preview tool.
First you need to update your DFP initialization script in <head> of your website
var pageConfig = {
allowOverlayExpansion: true,
allowPushExpansion: true,
sandbox: true
};
googletag.pubads().setSafeFrameConfig(pageConfig);
This will allow to expand SafeFrame ads on your website. More about this in
Control SafeFrame Container behavior through GPT.
Now you can create custom creative and serve it as SafeFrame on your website. Here is my one example. This Example can "wait" util it's visible, and then will expand to height of <div id="container"> that is inside of SafeFrame:
<div id="container">
some lines to make container height<br>
line<br>
line<br>
line<br>
line<br>
line<br>
line<br>
line<br>
line<br>
line<br>
line<br>
line<br>
line<br>
line<br>
line<br>
line<br>
line<br>
line<br>
</div>
<script>
// global expanded indicator variable, because API don't have any
var expanded = false;
function expand() {
var self= $sf.ext.geom().self;
var config = {
push: true, // we want to push expanded content
b: 0
};
var el = document.getElementById('container');
var containerHeight = el.offsetHeight;
// get height from bottom, that need to be expanded
var expandBottom = containerHeight - self.h;
// if container is whole inside a SafeFrame, it will not expand
if(expandBottom < 0) return;
config.b = expandBottom;
$sf.ext.expand(config);
}
function expandDelayed(forceExpand) {
// expand will run just once, or you can force it to run again
// but collapse first is needed
if(expanded && forceExpand || !expanded) {
$sf.ext.collapse();
expanded = false;
// there must be some timeout, because .collapse(); method is deplayed somehow
setTimeout(expand, 0);
}
}
$sf.ext.register(160, 150, function(status, data) {
// this code will do whole magic of "waiting" for right moment
if (status === 'geom-update') {
expandDelayed();
}
// change global expanded status
if (status === 'expanded') {
expanded = true;
}
});
// init
expandDelayed();
</script>
2. code your own API with window.postMessage() javascript method
First, you need to put this code, to your DFP initialization script in <head> of your website. This code will add an ID of Ad slot as #hash-tag to <iframe>'s src so you can get it from inside of your creative.
googletag.pubads().addEventListener('slotRenderEnded', function (event) {
var containerId = event.slot.getSlotElementId();
var containerEl = document.getElementById(containerId);
if (containerEl === null) return;
var iframeEl = containerEl.querySelectorAll('iframe')[0];
// it's delayed by 10 milliseconds, because iframe is not yet fully rendered
// and limited to max to 10 seconds to wait
var timeoutFunction = function () {
var src = "#" + containerId;
// `src` attribute is null, when iframe is FriendlyIframe, and
// when it's present, then it's SafeFrame
if (iframeEl.getAttribute('src') !== null) {
src = iframeEl.getAttribute('src').replace(/#.*/, "") + src;
} else {
var name = iframeEl.getAttribute('name') + "#" + containerId;
iframeEl.setAttribute('name', name);
}
iframeEl.setAttribute('src', src);
};
setTimeout(timeoutFunction, 10);
});
Second, you need to add this code to your website, better as separated .js file.
function onMessageReceivedGetStyle(e) {
// this will filter just setStyle commands from correct origin
if (
!(e.origin === 'http://tpc.googlesyndication.com' || e.origin === 'https://tpc.googlesyndication.com') ||
typeof e.data !== 'object' ||
typeof e.data.id !== 'string' ||
e.data.cmd !== 'setStyle' ||
typeof e.data.params !== 'object'
) {
return;
}
// remove # character from id, we don't use jquery
var elementId = e.data.id.replace(/#/, "");
var wrapperEl = document.getElementById(elementId);
if (wrapperEl === null) {
return;
}
var elements = [wrapperEl];
// you can target child elements too with query parameter
if (typeof e.data.query === 'string' && e.data.query) {
elements = wrapperEl.querySelectorAll(e.data.query);
}
elements.forEach(function (element) {
Object.keys(e.data.params).forEach(function (param) {
element.style[param] = e.data.params[param];
});
});
}
if (window.addEventListener) {
addEventListener('message', onMessageReceivedGetStyle, false);
}
else {
if (window.attachEvent) {
attachEvent('onmessage', onMessageReceivedGetStyle);
}
else {
window.onmessage = onMessageReceivedGetStyle;
}
}
And third thing is your custom code in custom type of creative in DFP. Here is example, that is similar to that in
first example, but here this script can wait until all content and image is loaded and then will expand/shrink your
iframe with creative:
<div id="container">
<a href="#" target="_blank">
<img src="%%FILE:JPG1%%">
</a>
<a href="#" target="_blank">
<img src="%%FILE:JPG2%%">
</a>
</div>
<style>
a {
display: block;
margin-bottom: .5em;
}
img {
display: block;
max-width: 100%;
}
*:last-child {
margin-bottom: 0;
}
</style>
<script>
var container = document.getElementById('container');
function resizeOutsideSafeFrame() {
if (!window.top.postMessage) {
return false;
}
// get ID of your Ad unit <div> with this creative
var divGptAdId = '%%PATTERN:url%%';
if (divGptAdId.indexOf('#') !== -1) {
divGptAdId = divGptAdId.split('#')[1];
} else {
divGptAdId = window.location.hash;
}
if(!divGptAdId) {
if (window.name.indexOf('#') !== -1) {
divGptAdId = window.name.split('#')[1];
}
}
if(!divGptAdId) {
return;
}
// set with to fullwidth, and height to height of container inside creative
var width = '100%';
var height = container.offsetHeight + 'px';
// send our request to website
window.top.postMessage({
cmd: 'setStyle',
id: divGptAdId,
query: 'div, iframe', // we want to target child div and iframe and don't change container styles
params: {
display: 'block',
height: height,
width: width
}
}, '*');
}
document.onreadystatechange = function () {
// resize iframe when all is loaded
if (document.readyState == "complete") {
resizeOutsideSafeFrame();
}
};
// first resize must occur little bit later
setTimeout(resizeOutsideSafeFrame, 100);
</script>
That's all. When you want to change anything on your website from inside of iframe, you can code your own cmd on your
website and call this command from inside of the iframe.
Edit 1:
just noticed now, that var divGptAdId = '%%PATTERN:url%%; will not return correct id of div on the page in #hash way, so now it's needed to give him a correct container div id change:
if(!divGptAdId) {
return;
}
to
if(!divGptAdId) {
divGptAdId = 'div-gpt-ad-container-div-id-1';
}
I couldn't find any solid documentation on this so the example from PayteR helped me immensely! I had to play with the new dimension to get the ad to expand the right way.
Here is some sample code I created from PayteR's example:
/* Main object for namespacing */
var Ad = function(obj) {};
/*
Register your ad with the dimensions of the current ad.
- This is basically an event handler for the the ad frame.
- 728 initial ad width
- 90 initial ad height
*/
Ad.prototype.registerExpand = function() {
$sf.ext.register(728, 90, function(status, data){});
};
/* Expand function to be called on click or load */
Ad.prototype.expandAd = function() {
/* Get the current geometry of your ad */
var self = $sf.ext.geom().self;
/*
Set the new geometry
- Increase height 315 pixels
- Expand downward by setting the bottom to the new height minus the current height
*/
$sf.ext.expand({
h: 315,
b: 315 - self.h
});
};
/* Intialize, register, and expand */
var ad = new Ad();
ad.registerExpand();
ad.expandAd();
I want to update the class of a link when the window scrolls into the linked container. It works fine on some browsers, but the browser crashes on iOS.
Any idea why or how I can improve on this?
HTML:
<ul id="section-follow" data-default="background-none" data-active="background-red">
<li class="">First</li>
<li class="">Second</li>
<li class="">Third</li>
<li class="">Fourth</li>
</ul>
Javascript:
function SectionFollow() {
if ($('#section-follow').length) {
var sections = {},
_height = $(window).height(),
i = 0;
var classDefault = $('#section-follow').attr('data-default');
var classActive = $('#section-follow').attr('data-active');
$('.follow').each(function() {
sections[this.id] = $(this).offset().top;
});
var pos = $(this).scrollTop();
for (i in sections) { // Each section
if (sections[i] < pos + (_height * .5)) { // 50% from top
$('#section-follow li a').removeClass(classActive).addClass(classDefault);
$('a[href="#'+i+'"]').removeClass(classDefault).addClass(classActive); //
if (history.pushState) { // Update the URL hash
history.pushState(null, null, window.location.origin + window.location.pathname + window.location.search + $('a[href="#'+i+'"]').attr('href')); // Set the hash using the history api if available to tackle Chromes repaint bug on hash change
} else {
window.location.hash = $('a[href="#'+i+'"]').attr('href');
// Otherwise fallback to the hash update for sites that don't support the history api
}
} // End if 50% from the top
} // End each section
} // End if section follow exists
} // End SectionFollow
$(window).scroll(function() {
SectionFollow();
});
I am using the Jquery inview plugin and I am trying to load some elements whenever the user reached the footer of the page. While doing this, I discovered a bug where if the user holds the scroll-click and drags the mouse towards the bottom, in some cases the elements will not load anymore until the footer is out of the view and then back into the view.
Here is the function that I have so far to load the elements when the footer is in the viewport:
//Infinite load function. Uses jquery.inview
$scope.addMoreElements = function(){
$scope.limitElementsPerPage += 16;
$('.footer').on('inview', function(event, isInView) {
if (isInView) {
// element is now visible in the viewport
$scope.limitElementsPerPage += 16;
} else {
// element has gone out of viewport
//do nothing
}
});
};
I am using Angularjs as well as jQuery for this project. Essentially, what I think I need is something that checks at about 1-2 seconds if the element is still in view. I am not exactly sure I should do this at the moment. This is what I tried to do to solve this issue:
$scope.$watch($('.footer'), function(){
$('.footer').on('inview', function(event, isInView) {
setTimeout(function(){
while(isInView){
console.log('test')
}
}, 1000);
});
});
This unfortunately, will crash the browser (I am not sure how I would go about doing this with the setTimeout or the other related functions).
Any help or ideas on how to do this would be greatly appreciated.
Thank you in advance.
InView adds a new event for elements, that triggers when the element enters the viewport. Probably some times you just have the footer in the viewport at all times, so that is why it fails.
I think you need to redesign the logic of the page to use the 'scroll' event on whatever element contains the added items and scrolls for the infinite view and in that event to check if the footer is in the viewport, not if it enters.
Personally I use this extension for checking if it is in the viewport:
(function($) {
$.inviewport = function(element, settings) {
var wh=$(window).height();
var wst=$(window).scrollTop();
var et=$(element).offset().top;
var eh=$(element).height();
return !(wh + wst <= et)&&!(wst >= et + eh);
};
$.extend($.expr[':'], {
"in-viewport": function(a, i, m) {
return $.inviewport(a);
}
});
})(jQuery);
Here are couple of functions you can use:
var getScrollY = function(){
var supportPageOffset = window.pageXOffset !== undefined;
var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat");
var y = supportPageOffset ? window.pageYOffset : isCSS1Compat ?
document.documentElement.scrollTop : document.body.scrollTop;
return y;
}
function get_elem_y( elem ) {
var box = elem.getBoundingClientRect();
return box.top + getScrollY();
}
And then you can listen to the scroll event, assume footer is something like <div id="footer">...</div>
var footer = document.getElementById("footer"); // get footer
var b_foot_visible = false;
window.addEventListener("scroll", function() {
var y = get_elem_y(footer);
var pageHeight = ( window.innerHeight || document.body.clientHeight);
if((getScrollY() + pageHeight) > y ) {
// footer is visible
if(!b_foot_visible) {
// TODO: add something
b_foot_visible = true;
}
} else {
// footer is not visible
if(b_foot_visible) {
// TODO: remove something
b_foot_visible = false;
}
}
});
Thus, when the scrollY + pages height reaches the footer elements Y coordinate you can do something to display things for the footer.
You might also add check in the beginning to test if the footer is already visible.
Is there a way to affect a div that is out of view? Ex: when you scroll down the page and the div is no longer visible.
I have an embedded youtube video and I would like to mute it only when the video is no longer in view.
This will mute every video player that is not visible:
$(function() {
var $w = $(window), oldw = 0, oldh = 0, oldt = 0;
function checkVideoVisible() {
if (oldw !== $w.width() || oldh !== $w.height() ||
oldt !== $w.scrollTop()) {
oldw = $w.width();
oldh = $w.height();
oldt = $w.scrollTop();
var top = oldt, bottom = oldt + oldh;
$("video").each(function() {
var $this = $(this);
if ($this.offset().top + $this.height() >= top &&
$this.offset().top < bottom) {
$this.prop("muted", false);
} else {
$this.prop("muted", true);
}
});
}
}
Now to trigger the checking, you can either use a timer:
var timerId = setInterval(checkVideoVisible, 200);
}
Or handle the scroll event:
$w.on("scroll", checkVideoVisible);
}
In the latter case, you will also need to perform a check when any change is made to the dom.
Use this as its probably your best bet im guessing as you;ve posted no code that a pre-written lib will help you
JQ Visible Lib
To implement you need to give your element an id and reference it in script tags or in a js file like this:
$('#element').visible() will return true if visible.
You can then add the part to mute/pause the video based on that state.