Suggestions
tjbenton opened this issue · comments
I like how this doesn't require any dependencies!! I also like how performant it is, along with the small file file size, great work! I have a few suggestions to improve performance, extend functionality, and (potentially) decrease file size.
-
Remove elements from
this._nodes
after they have been revealed because you no longer need to check if they're in the viewport in update. -
Currently the
_destroy
method is not being used at all. This should run whenthis._nodes.length
is0
. So you can remove the overhead of those events. -
Instead of defining
this._nodes
in the constructor I would move it to _create and just add an argument to_create(selector)
. Ifselector
is undefined then just use the initial selector that was passed into the options. This way you can callLazyr._create
in some other function after the page loads and add other elements tothis._nodes
list. This would be useful if you ajaxed in images that weren't on the page when Lazyr was initially called. I would also update the name to be something else to be more semantic if you decide to implement it like this. -
In addition to
#3
updatedocument.querySelectorAll(this._optionsSelector)
to bethis._optionsContainer.querySelectorAll(selector || this._optionsSelector)
so that you're only getting elements inside of the defined container. -
Remove this updateSelector because it's not being used and just adding weight to the file size.
-
Remove getContainerHeight from _inViewport and just set
this.containerHeight = this._optionsContainer.innerHeight || this._optionsContainer.offsetHeight
inside of update outside of the loop. The reason for this is so that you don't have to get the container height for everynode
inthis._nodes
since it's highly unlikely that the container height will change before theupdate
function is complete. -
Move the hidden attribute check into the update for loop. This way you don't have to waste time doing the calculations to check if it's visible if it's hidden.
if(!node.hasAttribute(this._optionsAttrHidden) && this._inViewport(node)) { ... }
Those are my 2 cents.
@tjbenton thanks for the suggestions man. great stuff all around, and really appreciate the nicely written issue.
currently working on v1.5.0 which is more or less a complete rewrite (see the branch if you're interested). might end up making it v2.0.0, because I think implementing some of this stuff will break the existing API. feedback specific to each of the suggestions below:
- 1 - will be in v1.5.0
- 2, 3 - will be in v1.5.0. i'll check the list of elements length in
reveal
, and calldestroy
if its0
.create
will be written such that it can be called multiple times, and ill use a property to check if the event handlers are currently bound or not, to prevent them from being bound multiple times. in this case, it'd definitely make to rename it_init
or_start
- 4 - will be in v1.5.0 - really clever, nice work
- 5 -
updateSelector
exists currently to accommodate people adding images dynamically, though its not well documented. i think suggestion 2 & 3 will address this, so I'll remove it - 5i - will be in v1.5.0 - great point, doesn't make sense to check container height for every element since it wont change mid-
update
@callmecavs You're welcome. I added #7
after I posted the issue but you might consider removing this._optionsAttrHidden
. I'm not sure when this would be useful. Because you have to declare data-lazyr
and data-lazyr-hidden
on an element which doesn't make sense when you can just not add data-lazyr
for it to not run.
I'm adapting this lib to apply it to work with lazy showing items on the page. So that I can do what I did on this codepen and have it will run that animation when elements that are below the page come into view. Below is the solution that I'm using to handle responsive design states of elements. So that when elements are hidden on the page by a class of u-hide
or something like that. Then become visible on a page when the screen resizes via a class of u-show@md
. They will then still be lazy loaded on the page because they weren't removed from the nodes list.
/// @name is_hidden
/// @description
/// Helper function to see if an element hidden via it's styles. It's used because of responsive sites.
/// @markup {js}
/// if(!is_hidden(somenode)){
/// // do something with the node that is not hidden
/// }
is_hidden(node){
let style = window.getComputedStyle(node)
return style.getPropertyValue("visible") !== "hidden" && style.getPropertyValue("display") !== "none";
}
I wrote it in an es6 class but it would be easy to change to es5.
You might also consider adding a debounce function to the event listeners http://davidwalsh.name/javascript-debounce-function
@tjbenton interesting. i see your point about removing the hidden attribute - the thinking there was that there may be some cases where you want Layzr to check an image consistently, but only sometimes reveal it. the benefit of the hidden attribute as it exists is that you dont need to call create
or updateSelector
again to have it start tracking the image - just remove the hidden attribute when its okay to show it and the next time its in the viewport itll reveal. you're right about the check being better off in the update function tho, i'll move it in the next version.
the handlers are currently debounced, using requestAnimationFrame - see the debounce helper functions and the HTML5 Rocks article they were adapted from
@callmecavs Potentially this would be a good time to think about making Layzr a bit more generic for scroll listeners in general #50 The use-case with this is one selector that will be pushed further down the page and revealed again.
@zslabs at the end of the day this is a library for lazy loading images, not for "doing stuff on scroll". a repeat option doesn't make sense because once an image has been loaded, there's no longer a need to track it - it cant load twice, nor would it make sense for it to do so.
that being said, using the suggestions i left you on #50, i think you can definitely adapt layzr to work as a "doing stuff on scroll" library for your use case. if you're looking for a library that is directly geared towards "doing stuff on scroll", i can personally recommend waypoints.js
any chance to know the release date for v2?
back on track to release v2, likely this week. will include srcset
support! check my progress here: https://github.com/callmecavs/layzr.js/tree/v2.0.0