lazy loading images on scroll and "come into view" - javascript

I am using Lazy as a lazy image loading plugin. I have a div where I load divs like this:
<div class="nano-content" id="lScroll">
/*... MORE LIKE THIS ... */
<div class="card">
<div class="city-selected city-medium clickChampion pointer"
data-champ-id="1">
<article>
<div class="info">
<div class="city">
CHAMPNAME
</div>
</div>
</article>
<figure class="cFigure lazy" data-src="images/champions/CHAMPNAME_0.png"></figure>
</div>
</div>
/*... MORE LIKE THIS ... */
</div>
So I initiate the plugin and it works for the first ones visible and when I scroll:
var $lazy = $('#lScroll .lazy');
if ($lazy.length) {
$lazy.Lazy({
appendScroll: $('#lScroll')
});
}
But now I have a function that "filters" the divs by their attributes when I enter sth in my search input and it fails to load the image when the according div is shown:
$(document).on("keyup", "#searchVod", function () {
var $search = $(this);
var $sVal = $search.val().toLowerCase();
if ($sVal !== "") {
$(".vodCard").hide();
$('[data-champ*="' + $sVal + '"]').show();
$('[data-role*="' + $sVal + '"]').show();
} else {
$(".vodCard").show();
}
});
I tried bind: "event" /w and w/out delay: 0 (loading the plugin in the search function) but when I searched it would load ALL images immediately in the background.
Any hint highly appreciated
UPDATE: I just noticed in Chrome DevTab after entering one letter in my searchbox it loads ALL the images and eventually the one I am searching for (if its the last it takes some time (30MB sth)

There is an excellent library called Lozad.js which can help you to make it easier to load your images like lazy load do but in easier way.
You can download it here from Github.
Demo page here.
Explanation:
This library will load your images one by one on scrolling to each image anchor by class name.
Example
HTML:
At the header ->
<script src="https://cdn.jsdelivr.net/npm/lozad"></script>
Image element should looks like this:
<img class="lozad" data-src="image.png">
Javascript
// Initialize library
lozad('.lozad', {
load: function(el) {
el.src = el.dataset.src;
el.onload = function() {
el.classList.add('fade')
}
}
}).observe()
Hope it will help you.
Best,
Ido.

Related

Getting Uncaught TypeError but link works fine

Although there are some questions similar, ive read it and cant solve my problem.
Hope someone direct some light on this in order to help not only me but others out there.
I have added JS file to my child theme (wordpress) via functions.php and then added Event listener to ID.
The problem inhabits on the :Uncaught TypeError: Cannot read property 'addEventListener' of null
at custom.js?ver=5.4:1
Although when i click the object it goes correctly to the link, the error shows on console.
on functions.php ive added:
function my_customm_scripts() {
wp_enqueue_script( 'custom-js', get_stylesheet_directory_uri() . '/custom.js', array( 'jquery' ),'',true );
}
add_action( 'wp_enqueue_scripts', 'my_customm_scripts' );
and in my custom.js ive added:
document.getElementById('hercule').addEventListener('click', function() {
location.href = 'https://somedomain.com'
}, false);
im shure its straightforward but ive checked so many solutions without success
Thx for your time
J.
<div class="hoverfora wpb_animate_when_almost_visible wpb_slideInUp slideInUp wpb_column vc_column_container vc_col-sm-4 wpb_start_animation animated" id="hercule">
<div class="vc_column-inner vc_custom_1587337223984">
<div class="wpb_wrapper">
<div class="service_table_holder">
<ul class="service_table_inner">
<li class="service_table_title_holder background_color_type" style="">
<div class="service_table_title_inner">
<div class="service_table_title_inner2">
<h3 class="service_title" style="">Web design</h3>
<i class="qode_icon_font_awesome fa fa-desktop fa-3x" style="color: #efcd21 !important;"></i>
</div>
</div>
</li>
<li class="service_table_content" style="">Development de websites .
<p></p>
</li>
</ul>
</div>
</div>
</div>
</div>
I think that is
window.location.href = 'https://somedomain.com'
Try this instead,
If you are sure that your html source contains the element with id="hercule". Then you can try
window.onload = function () {
document.getElementById('hercule').addEventListener('click', function() {
location.href = 'https://somedomain.com'
// alert("clicked div");
}, false);
};
Make sure that all your onload processes are written in a single place. Otherwise the browser will keep and execute only last found window.onload function.
This code of yours:
document.getElementById('hercule')
is looking for a DOM element with id="hercule". Apparently, your page does not contain such an element at the time the custom.js is being run, so document.getElementById('hercule') is returning null, then a TypeError is thrown when addEventListener method is called on a null object.
Look for an element on your HTML page that contains id="hercule". If you can't find it, your problem has been identified.
Edit:
Subsequent information reveals that the custom.js JavaScript is trying to access a div with id="hercule" before it exists. The solution is to delay the start of the custom function until the div exists.
Normally, waiting for the window's load event is sufficient, but it is unclear in this case that will work, as "hercule" may be generated by another JavaScript function that won't complete by the time of the load event.
One solution is simply to continue to look for "hercule" until it's found:
// USE THIS SECTION IN YOUR CODE:
// keep looking for "hercule"
function lookForHercule() {
const hercule = document.getElementById('hercule');
if (hercule) {
// add the 'click' listener to 'hercule'
hercule.addEventListener('click', function() {
hercule.innerHTML = "You clicked hercule, redirecting to somedomain.com";
location.href = 'https://somedomain.com'
}, false);
return;
}
console.log('"hercule" not found');
setTimeout(lookForHercule, 2000);
}
// start looking
lookForHercule();
// END OF SECTION TO USE IN YOUR CODE
// THE CODE BELOW IS FOR THIS DEMO ONLY, DO NOT USE IN YOUR CODE:
// FOR DEMO ONLY:
// add 'hercule' after 10 seconds to simulate delay
setTimeout(() => {
const wrapper = document.getElementById('wrapper');
const hercule = document.createElement('div');
hercule.id = 'hercule';
hercule.innerHTML = "I am hercule. Clicking me will redirect to somedomain.com";
wrapper.appendChild(hercule);
}, 10000);
/* this will change cursor to finger when hovering over hercule */
#hercule:hover {
cursor: pointer;
}
<div id="wrapper">
<h4>Search for 'hercule'</h4>
</div>

Loop through element and change based on link attribute

Trying to figure this out. I am inexperienced at jQuery, and not understanding how to loop through elements and match one.
I have 3 divs:
<div class="first-image">
<img src="images/first.png">
</div>
<div class="second-image">
<img src="images/second.png">
</div>
<div class="third-image">
<img src="images/third.png">
</div>
And off to the side, links in a div named 'copy' with rel = first-image, etc.:
...
Clicking the link will fade up the image in the associated div (using GSAP TweenMax)
Here is the function I've been working on to do this... but I am not fully understanding how to loop through all the "rel" elements, and make a match to the one that has been clicked on.
<script>
//pause slideshow on members to ledger when text is clicked, and show associated image
$(function() {
$('.copy').on('click','a',function(e) {
e.preventDefault();
var slideName = $(this).attr('rel');
$("rel").each(function(i){
if (this.rel == slideName) {
console.log(this);
}
});
//var change_screens_tween = TweenMax.to('.'+slideName+'', 1, {
//autoAlpha:1
//});
});
});
</script>
What am I doing wrong? I don't even get an error in my browser. :-(
Thanks to the answer below, I got farther. Here is my revised code.
$('[rel]').each(function(k, v){
if (v == slideName) {
var change_screens_tween = TweenMax.to('.'+slideName+'', 1, {
autoAlpha:1
});
} else {
var change_screens_tween = TweenMax.to('.'+slideName+'', 1, {
autoAlpha:0
});
}
});
});
This is starting to work, but makes the screenshots appear and then instantly fade out. And it only works once. Any thoughts?
Add brackets around rel, like so:
$('[rel]').each(function() {
if ($(this).attr('rel') == slideName) {
console.log(this);
}
});

Html page jumps when clicking link

Building a frontend and getting a bit baffled since I´m unable to stop the browser to jump when triggering a click event on an img.
I thought that either event.preventDefault() or return false would do it but I am obviously missing something and is completely at a loss about what to try next!
Here is the code
$("#imgViewer-thumbs").find("img").click(function (event) {
event.preventDefault();
var $imgViewPane = $("#imgViewPane"),
$selectedImage = $imgViewPane.find(".selected-image"),
$clickedImage = $(this),
$clickedImageIndex = $clickedImage.prevAll().length + 1,
$maxIndex = $clickedImageIndex + $clickedImage.nextAll().length,
$targetImage = $imgViewPane.find(":nth-child(" + $clickedImageIndex + ")");
if (!$targetImage.hasClass("selected-image")) {
$selectedImage.fadeOut(100, function () {
$targetImage.addClass("selected-image");
$selectedImage.removeClass("selected-image");
$targetImage.fadeIn(100);
});
}
console.log('Returning false');
return false;
}
);
EDIT:
Setup the imageviewer in jsfiddle here http://jsfiddle.net/tEXaa/
The problem is that image container "#imgViewPane" doen't hold the height. So then the prev image fades out "#imgViewPane" loses height and as a result the page loses scroll position.
I updated your fiddle: http://jsfiddle.net/tEXaa/1/
I had the same problem but with clicking anchor tags, and the problem wasn't with any jquery code but with negative margins.
Instead of using something like this
<div width="600px">
<div id="top-left" style="height:200px;"> some content </div>
<div id="top-right" style="margin-top:-200px;> content"</div>
</div>
use
<div width="600px">
<div id="top-left" style="float:left;"> some content </div>
<div id="top-right" style="float:right;> content"</div>
</div>

Bootstrap Collapse - open the given id fragment

Imagine a Bootstrap collapse with 3 parts
<div class="panel-group" id="accordion">
...
<div id="accordionOne" class="panel-heading"></div>
...
<div id="accordionTwo" class="panel-heading"></div>
...
<div id="accordionThree" class="panel-heading"></div>
</div>
Is there a simple way to make the plugin open the given HTTP fragment identifier ?
Example http://myproject/url#accordionTwo would open the second accordion
$("#accordionTwo").collapse('show');
To open the given HTTP fragment identifier, try this:
$(document).ready(function() {
var anchor = window.location.hash;
$(".collapse").collapse('hide');
$(anchor).collapse('show');
});
EDIT:
As pointed by bart in the comments:
be careful with targeting .collapse because this class is also used for the navigation bar when the viewport is xs.
This line will open the correct hash
location.hash && $(location.hash + '.collapse').collapse('show');
Yet another solution, a bit smaller and compact:
$(document).ready(function() {
var anchor = window.location.hash;
$(anchor).collapse('toggle');
});
For really simple and quick to implement hash routing, you could try something like Routie
routie({
accordionOne: function() {
$('#accordionOne').collapse('show');
},
accordionTwo: function() {
$('#accordionTwo').collapse('show');
},
accordionThree: function() {
$('#accordionThree').collapse('show');
}
});

How to implement multiple tinyscrollbars from a class?

I'm trying to implement multiple scrollbars with the plugin Tinyscrollabr.js
http://baijs.nl/tinyscrollbar/
To implement the scrollbars, i use a function scrollify like in this article :
http://www.eccesignum.org/blog/making-tinyscrollbarjs-easier-to-implement
HTML :
<ul id="myList">
<li id="scrollbar1" class="col">
<h2>Title 01</h2>
<div class="scrollBox"><!--Scrollable Content here--></div>
</li>
<li id="scrollbar2 class="col">
<h2>Title 02</h2>
<div class="scrollBox"><!--Scrollable Content here--></div>
</li>
<li id="scrollbar3 class="col">
<h2>Title 03</h2>
<div class="scrollBox"><!--Scrollable Content here--></div>
</li>
</ul>
Javascript :
function scrollify(element,options) { // '#element', {list:of,key:values}
var opt = options || {}
$(element).children().wrapAll('<div class="viewport"><div class="overview"></div></div>');
$(element).prepend('<div class="scrollbar"><div class="track"><div class="thumb"><div class="end"></div></div></div></div>');
$(element).tinyscrollbar(options);}
$scrollbar1 = $('#scrollbar1 .scrollBox') ;
$scrollbar2 = $('#scrollbar2 .scrollBox');
$scrollbar3 = $('#scrollbar3 .scrollBox');
$scrollbar4 = $('#scrollbar4 .scrollBox');
$(function() {
scrollify($scrollbar1);
scrollify($scrollbar2);
scrollify($scrollbar3);
scrollify($scrollbar4);
})
I would to make this more simple.
For example, i would to be able to make this :
$(function() {
scrollify('.scrollBox');
})
But tinyscrollbar need an id. With a class, it's load the first scrollbar and not the others. Firebug return this error message "f.obj[0] is undefined"
Sorry if my question is stupid, but how can I do for applying tinyscrollbar to a list of elements with a class ?
And then, after some actions how to update all this scrollbars with the function $allScrollbars.tinyscrollbar_update();
Thanks for help, I'm just beginning with javascript and i'm trying to learn.
I would count the number of elements with the class:
var scrollCount = $(".scrollbox").size();
Then use an iterating loop to call each of your IDs:
for (i=0; i<5; i++) {
scrollify($('#scrollbar' + i));
}
Also I would recommend using DIVs instead of the list setup you have, use the example from the link you shared as a starting point :)
Thanks KneeSkrap3r for your answer. It's a good solution to make this but i'm trying to do something in the case i' don't know the numbers of element to scroll.
I think I've found with something like this (it's a part from the first jquery plugin i'm trying to do ) where $el is all elemnts with the class"scrollbox".
$el.each(function(index)
{
var $scrolls = $(this);
function scrollify(element,options)
{ // '#element', {list:of,key:values}
var opt = options || {}
$(element).children().wrapAll('<div class="viewport"><div class="overview"></div></div>');
$(element).prepend('<div class="scrollbar"><div class="track"><div class="thumb"><div class="end"></div></div></div></div>');
$(element).tinyscrollbar(options);
}
scrollify($scrolls);
// Update heights
$(window).resize(function()
{ $scrolls.tinyscrollbar_update('relative');
});
})
Like this, it's seems to work but i don't know if i'm using good practice of javascript.
For the Html markup, I told the li elements for div, it's better for the semantic.
Thanks for tips ;-)

Categories

Resources