javascript load image on scroll - javascript

i want to build my own lazy images using only javascript.
so far, this is my code :
<img src="images1.jpg" data-src="images2.jpg" />
var body = document.body,
html = document.documentElement;
var height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight),
screen = screen.height;
img = document.getElementsByTagName("img");
window.addEventListener("scroll", function() {
for(var i = 0; i < img.length; i++) {
if (img[i].clientHeight >= height - screen) {
var data = img[i].getAttribute("data-src");
img[i].setAttribute('src','');
img[i].setAttribute("src", data);
}
}
});
the problem is, the image data-src did not execute into src attribute on scroll event.
i want it to execute when the images about 200px before the viewport.
how to doing this? and what's wrong with my code? is it possible that my if condition not correct?

Your code works just fine, you need to add }); at the end, though.
var body = document.body,
html = document.documentElement,
height = Math.max(
body.scrollHeight,
body.offsetHeight,
html.clientHeight,
html.scrollHeight,
html.offsetHeight),
screen = screen.height;
img = document.getElementsByTagName("img");
window.addEventListener("scroll", function() {
for(var i = 0; i < img.length; i++) {
if (img[i].clientHeight >= height - screen) {
var data = img[i].getAttribute("data-src");
img[i].setAttribute('src', data);
}
}
});
<img src="https://placeholdit.imgix.net/~text?txtsize=63&bg=FF6347&txtclr=ffffff&txt=Image-1&w=350&h=250"
data-src="https://placeholdit.imgix.net/~text?txtsize=63&bg=63FF47&txtclr=ffffff&txt=Image-1&w=350&h=250" />
<img src="https://placeholdit.imgix.net/~text?txtsize=63&bg=FF6347&txtclr=ffffff&txt=Image-2&w=350&h=250"
data-src="https://placeholdit.imgix.net/~text?txtsize=63&bg=63FF47&txtclr=ffffff&txt=Image-2&w=350&h=250" />
<img src="https://placeholdit.imgix.net/~text?txtsize=63&bg=FF6347&txtclr=ffffff&txt=Image-3&w=350&h=250"
data-src="https://placeholdit.imgix.net/~text?txtsize=63&bg=63FF47&txtclr=ffffff&txt=Image-3&w=350&h=250" />
<img src="https://placeholdit.imgix.net/~text?txtsize=63&bg=FF6347&txtclr=ffffff&txt=Image-4&w=350&h=250"
data-src="https://placeholdit.imgix.net/~text?txtsize=63&bg=63FF47&txtclr=ffffff&txt=Image-4&w=350&h=250" />
I don't get what you mean by "200px before the viewport". Could you explain it better? If you don't want all images to change at the same time, should consider the offetTop of each image and the scrollTop position. http://jsbin.com/xexeho/edit?html,js,output

If you can mention the dimensions of the images, it would make more sense. However I am still trying to attempt to answer your question as I think the scroll event in your code wasn't triggering at all. Try making your img tag slightly below the viewport so that scroll works
Also for the calculation use window.innerHeight as it gives right height of the viewport subtracting height of the addressbar etc.
<img src="images1.jpg" data-src="images2.jpg" style="position:absolute;top:1169px"/>
<script>
var body = document.body,
html = document.documentElement;
var height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight),
screen = window.height;
img = document.getElementsByTagName("img");
window.addEventListener("scroll", function() {
console.log("Checking if the scroll event is triggered...");
for(var i = 0; i < img.length; i++) {
if (img[i].clientHeight >= height - screen) {
var data = img[i].getAttribute("data-src");
img[i].setAttribute('src','');
img[i].setAttribute("src", data);
}
}
});
</script>
OR
try using events like mousewheel and/or DOMMouseScroll which does not expect body to be actually scrollable.
Hope this helps!

Checkout source of lazy loading plugin from todd motto.
It's pretty useful view others implementation.

Related

Adjust automatically iframes' height acording to the contents in Avada (WP Theme) tabs

I try to adjust automatically iframes' height acording to the contents inside Avada (WP Theme) tabs.
I found here, in stackoverflow, this code:
Before closing </body> tag:
<script type="text/javascript">
function getDocHeight(doc) {
doc = doc || document;
// stackoverflow.com/questions/1145850/
var body = doc.body, html = doc.documentElement;
var height = Math.max( body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight );
return height;
}
function setIframeHeight(id) {
var ifrm = document.getElementById(id);
var doc = ifrm.contentDocument? ifrm.contentDocument:
ifrm.contentWindow.document;
ifrm.style.visibility = 'hidden';
ifrm.style.height = "10px"; // reset to minimal height ...
// IE opt. for bing/msn needs a bit added or scrollbar appears
ifrm.style.height = getDocHeight( doc ) + 150 + "px";
ifrm.style.visibility = 'visible';
}
document.getElementById('ifrm').onload = function() { // Adjust the Id accordingly
setIframeHeight(this.id);
}
In each tab:
<iframe id="ifrm" src="https://TheTabUrl.com"></iframe>
It works for me but only in the first tab. I've 4 iframes in 4 different tabs in the same page.
Please, any idea about the way to make it work?
Thanx for your time in advance.
Greetings

Modifying all images (src) without id on page after onload

I ve given up finding a crossbrowser image solution which makes me happy.
I now want to make it the "mobile first" way of the cost of bandwith for destkops.
The plan: Ship mobile sized images to all clients.
Then i am able to get the viewport size of the browser which works fine.
My CSS is switching as the follows: <= 1000 px mobile view >=1001 desktop view.
But then: I thought i would save images in the same paths with different file extensions. Lets say i would save them as the follows
/img/myimage-mobile.jpg
/img/myimage-normal.jpg
/img/myimage-highres.jpg
initial load would look like
<img src="img/myimage-mobile.jpg" alt="#" />
Now my question: How can i get all img tags and change the extension of the src attribute? When detecting a viewport width >=1001 i want to replace all "-mobile.jpg" with "-normal.jpg" and larger ~1400 with "myimage-highres.jpg".
Thats what i got so far:
var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0)
var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0)
getting the viewport size and then i found this which is getting the entire src attribute:
var images = document.getElementsByTagName('img');
var srcList = [];
for(var i = 0; i < images.length; i++)
{
srcList.push(images[i].src);
srcList.push(images[i].src);
}
I don't think this is the best method but it does change the image paths but this will also work on window resize. If other developers want to edit this to clean it up or improve something then feel free to do so.
Would it not be better to detect the users device rather than using the browser height/width?
var defaultimg="normal";
function _Imgs(){
var imgsize;
var Pw=document.documentElement.clientWidth;
var Ph=document.documentElement.clientHeight;
if(Pw<800||Ph<300){ // Change this to Set width for mobiles
imgsize="mobile";
}else{
imgsize="normal";
}
var MyImgs=document.getElementsByTagName("IMG");
for(var i=0; i<MyImgs.length; i++) {
MyImgs[i].setAttribute("src",MyImgs[i].src.replace(defaultimg, imgsize));
}
//Change variable value to allow toggle on window resize
defaultimg=imgsize;
}
window.onload=_Imgs;
window.onresize=_Imgs;
With Jquery you can do it like this
$('img').each(function(){
var fix = $(this).attr('src').replace('mobile', 'normal');
$(this).attr('src', fix);
})
To detect the viewport size you can do this:
var height = window.innerHeight;
var width = window.innerWidth;
Then just make a function wrapping it all together:
window.onload = function(){
var height = window.innerHeight;
var width = window.innerWidth;
if(height < 1000 && width < 400){
$('img').each(function(){
var fix = $(this).attr('src').replace('mobile', 'normal');
$(this).attr('src', fix);
})
}
}
or with pure javascript:
window.onload = function(){
var height = window.innerHeight;
var width = window.innerWidth;
if(height < 1000 && width < 400){
var imgs = document.getElementsByTagName('img');
for(i=0;i<imgs.length;i++){
var fix = imgs[i].src.replace('mobile', 'normal');
imgs.src = fix;
}
}
}

How can I change div height automatically on resize with javascript?

Now I have working on window load code, but can't make it work with window resize (height values will increase if I repeat the same function for resize event). Array is to show initial values after onload completed.
var arr = [];
window.onload = function() {
var newsBlocks = document.getElementsByClassName('news');
for (var i = 0; i < newsBlocks.length; i++) {
var newsBlock = newsBlocks[i];
var left = newsBlock.getElementsByTagName('article')[0];
var right = newsBlock.getElementsByTagName('article')[1];
var height = Math.max(left.offsetHeight, right.offsetHeight);
left.style.height = right.style.height = height.toString() + 'px';
arr.push(left.style.height);
console.log(arr);
}
};
Here is html:
<div class="main">
<section class="news">
<article>
<img src="images/t.png">
<h2>Heading</h2>
test text
</article>
<article>
<img src="images/t.png">
<h2>Heading</h2>
a lot of test text here
</article>
</div>
Pure JavaScript solution is appreciated. Thanks in advance for a help!
You should re-organize your code to be able to repaint the whole screen any time, and hook on the resize event, see: JavaScript window resize event
Resize event is called also on mobile devices, when they change orientation.
<div id=div1></div>
<script>
div1.style.height = (your preffered height)
</script>
same you can do with width.
it works for me ...
try the following code. It is working for me.
var buffer = 20; //scroll bar buffer
var divId = document.getElementById('yourDivID');
function pageY(elem) {
return elem.offsetParent ? (elem.offsetTop + pageY(elem.offsetParent)) : elem.offsetTop;
}
function resizeDiv() {
var height = document.documentElement.clientHeight;
height -= pageY(divId) + buffer;
height = (height < 0) ? 0 : height;
divId.style.height = height + 'px';
}
window.onresize = resizeDiv;

How can I inject a div into a webpage that moves on window resize?

Essentially, I'm creating a custom click & drag selection box. The problem is that the div is position absolutely, so it will scroll with the page, but it will not move with the page when the window is being resized. My attempted solution was to listen to the window resize, and move the div according to the change. The problem is that it will SEEM to work, but it will not move entirely accurately, so it will slowly move out of place if the window is resized slowly, or quickly move out of place if the window is resized quickly. It seems that the resize listener does not capture every resize event. I've narrowed the code down to the concept I'm using.
Try injecting this script into a page (I'm using the Chrome console and I haven't made any attempt for cross-compatibility because this will be used in a Chrome extension). It will attempt to resize only when the scrollbar is not active, to replicate the behavior of the page content. The client and scoll variables are interchangeable for recording the change in dimensions, but they are both there for testing purposes. I would love to see a solution which solves this problem using styling attributes. Thanks for your help!
var div = document.createElement("div");
div.style.position = "absolute";
div.style.backgroundColor = "#000";
div.style.width = div.style.height = div.style.left = div.style.top = "200px";
document.body.appendChild(div);
// get the highest z index of the document
function highestZIndex() {
var elems = document.getElementsByTagName("*");
var zIndex = 0;
var elem, value;
for (var i = 0; i < elems.length; i++) {
value = parseInt(document.defaultView.getComputedStyle(elems[i], null).zIndex, 10);
if (value > zIndex) {
zIndex = value;
elem = elems[i];
}
}
return {
elem: elem,
zIndex: zIndex
};
}
// set the div on top if it is not already
var highestZ = highestZIndex();
if (highestZ.elem != div) div.style.zIndex = highestZ.zIndex + 1;
// last width & height of client & scroll to calculate the change in dimensions
var clientWidth = document.body.clientWidth;
var clientHeight = document.body.clientHeight;
var scrollWidth = document.body.scrollWidth;
var scrollHeight = document.body.scrollHeight;
// move the div when the window is being resized
function resizeListener() {
var _clientWidth = document.body.clientWidth;
var _clientHeight = document.body.clientHeight;
var _scrollWidth = document.body.scrollWidth;
var _scrollHeight = document.body.scrollHeight;
// horizontal scrollbar is not enabled
if (_scrollWidth <= _clientWidth) {
div.style.left = parseInt(div.style.left.replace(/px/, ''), 10) + (_scrollWidth - scrollWidth) / 2 + 'px';
}
// vertical scrollbar is not enabled
if (_scrollHeight <= _clientHeight) {
div.style.top = parseInt(div.style.top.replace(/px/, ''), 10) + (_scrollHeight - scrollHeight) / 2 + 'px';
}
clientWidth = _clientWidth;
clientHeight = _clientHeight;
scrollWidth = _scrollWidth;
scrollHeight = _scrollHeight;
}
window.addEventListener("resize", resizeListener);
PS: Please, no jQuery solutions.
Since the resize listener isn't quite dependable with outside events, I've developed a simple "hack" to get the wanted results. The window overflow is forced to scroll and the body width & height are set to +1 so that the scrollbar is active, in which the div will then stay in place. Once the resize is complete, the overflow and body dimensions are restored. This may not be a desired solution for others who want the div to move on a manual window resize, but I am invoking the resize from JavaScript so it works perfectly for me.
The script in practice:
var overflow, overflowX, overflowY, bodyWidth, bodyHeight;
function startResize() {
// store the original overflow values
overflow = document.body.style.overflow;
overflowX = document.body.style.overflowX;
overflowY = document.body.style.overflowY;
bodyWidth = document.body.style.width;
bodyHeight = document.body.style.height;
// force the scrollbar
document.body.style.overflow = "scroll";
// activate the scrollbar
document.body.style.width = document.client.width + 1 + "px";
document.body.style.height = document.client.height + 1 + "px";
}
function stopResize() {
// restore the original overflow values; x & y are included because enabling the global overflow will update x and y
document.body.style.overflow = overflow;
document.body.style.overflowX = overflowX;
document.body.style.overflowY = overflowY;
// restore the original body width & height
document.body.style.width = bodyWidth;
document.body.style.height = bodyHeight;
}

Auto-scroll to the bottom of a div

I have a div with overflow set to scroll which essentially streams data line by line off a file. I'd like to scroll automatically to the bottom of the div whenever the stream overflows, but without using a "Click here to scroll to bottom" button.
I already know of the scrollTop = scrollHeight solution, but that requires some kind of event trigger on the client's side. I don't want this element to be interactive; it should scroll by itself.
Is there any way to achieve this?
A lot of the scrollHeight implementations didn't work for me, offsetHeight seemed to do the trick.
Pretty sure that scrollHeight tries to move it to the bottom of the height of the static element, not the height of the scrollable area.
var pane = document.getElementById('pane');
pane.scrollTop = pane.offsetHeight;
There's no way to automatically scroll an element to the bottom. Use element.scrollTop = element.scrollHeight.
If you don't know when the element is going to resize, you could add a poller:
(function(){
var element = document.getElementById("myElement");
var lastHeight = element.scrollHeight;
function detectChange(){
var currentHeight = element.scrollHeight;
if(lastHeight != currentHeight){
element.scrollTop = currentHeight;
lastHeight = currentHeight;
}
}
detectChange();
setInterval(detectChange, 200); //Checks each 200ms = 5 times a second
})();
Some old code of mine with a running example that will stay at the bottom when new content is added, if the user scrolls it will not more it to the bottom.
var chatscroll = new Object();
chatscroll.Pane =
function(scrollContainerId)
{
this.bottomThreshold = 25;
this.scrollContainerId = scrollContainerId;
}
chatscroll.Pane.prototype.activeScroll =
function()
{
var scrollDiv = document.getElementById(this.scrollContainerId);
var currentHeight = 0;
if (scrollDiv.scrollHeight > 0)
currentHeight = scrollDiv.scrollHeight;
else
if (objDiv.offsetHeight > 0)
currentHeight = scrollDiv.offsetHeight;
if (currentHeight - scrollDiv.scrollTop - ((scrollDiv.style.pixelHeight) ? scrollDiv.style.pixelHeight : scrollDiv.offsetHeight) < this.bottomThreshold)
scrollDiv.scrollTop = currentHeight;
scrollDiv = null;
}

Categories