2

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();
  }
});
Joshua Wilkeson
  • 159
  • 1
  • 12
  • 2
    You really should store `$(this)`, `$(window)`, `$(".split1")`, `$(".pl")`, `...` in variables "outside" (or in a closure) the scroll handler. Right now you're creating 24 jQuery objects (of whom 16 are always the same) on each call of the scroll handler. And that handler will be called _very_ often. – Andreas Mar 20 '18 at 15:06
  • I was thinking I could store them in a loop like foreach $('class) and assign an array with its respective index to them. – Joshua Wilkeson Mar 20 '18 at 15:13
  • Please clarify your requirement/question. In a comment you're saying that you only want to use one class (`.split`) instead of different ones. Then why do you have different functions, one for each class? One class, with one function. That's a simply `for` loop to check the elements... – Andreas Mar 20 '18 at 17:55

2 Answers2

1

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');
        }
    });
});
pixelscript
  • 392
  • 1
  • 8
0

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)) }));
Jonas Wilms
  • 120,546
  • 16
  • 121
  • 140