Reputation: 385
I have this code: https://pastebin.com/zgJdYhzN in Javascript. It's supposed to fade in text when the scrolling function reaches a certain point and while this does work, there will be several pages using it and I'd like to avoid having to create several instances of this function. It would be better if I could just create a function and for every element that had the ".split" class, this would act upon it.
//EXECUTES ONLY ONCE
function once(fn, context) {
var result;
return function() {
if(fn) {
result = fn.apply(context || this, arguments);
fn = null;
}
return result;
};
}
// Usage
var split1 = once(function() {
fadeInText(".split1");
});
var pl = once(function() {
fadeInText(".pl");
});
var pl1 = once(function() {
fadeInText(".pl1");
});
var smallp = once(function() {
fadeInText(".smallp");
});
var smallp1 = once(function() {
fadeInText(".smallp1");
});
var smallp2 = once(function() {
fadeInText(".smallp2");
});
var smallp3 = once(function() {
fadeInText(".smallp3");
});
var head0 = once(function() {
fadeInText(".head0");
});
$(window).scroll(function() {
if( $(this).scrollTop() + $(window).height() > $(".split1").offset().top) {
split1();
}
if( $(this).scrollTop() + $(window).height() > $(".pl").offset().top) {
pl();
}
if( $(this).scrollTop() + $(window).height() > $(".pl1").offset().top) {
pl1();
}
if( $(this).scrollTop() + $(window).height() > $(".smallp").offset().top) {
smallp();
}
if( $(this).scrollTop() + $(window).height() > $(".smallp1").offset().top) {
smallp1();
}
if( $(this).scrollTop() + $(window).height() > $(".smallp2").offset().top) {
smallp2();
}
if( $(this).scrollTop() + $(window).height() > $(".smallp3").offset().top) {
smallp3();
}
if( $(this).scrollTop() + $(window).height() > $(".head0").offset().top) {
head0();
}
});
Upvotes: 2
Views: 77
Reputation: 392
Not sure if I'm missing why you need the once
method. Is there a reason you couldn't do something like this:
var selectors = ['.one', '.two', '.three'];
var elements = {};
selectors.forEach(function(selector){
elements[selector] = $(selector);
});
function elementOnScreen(selector) {
if(!elements[selector]){
return false;
}
return $(window).scrollTop() + $(window).height() > elements[selector].offset().top
}
$(window).scroll(function() {
selectors.forEach(function(selector) {
if(elementOnScreen(selector)){
fadeInText(selector);
delete elements[selector];
}
if(Object.keys(elements).length === 0){
$(window).off('scroll');
}
});
});
Upvotes: 1
Reputation: 138437
Just generate the functions for all elements using a loop:
const handlers = [".split1", ".pl" /*...*/]
.map(s => ({ el: $(s), show: once(() => fadeInText(s)) }));
$(window).scroll(function() {
for(const {el, show} of handlers) {
if( $(this).scrollTop() + $(window).height() > el.offset().top)
show();
}
});
You could also generate the handlers for all elements of a class:
const handlers = $(".split").toArray()
.map(s => ({ el: $(s), show: once(() => fadeInText(s)) }));
Upvotes: 0