Intersect.js

The Intersect() plugin is a class that is dependent upon the IntersectionObserver native javascript class. The function of this plugin is to make it easier to use the native IntersectionObserver with added functionalities.

Initializing plugin
The plugin is added as part of the core javascript urls of the application. However, it is not loaded by default. By using the unique name, we can load the javascript file first before we can have access to the plugin. The intersectJS is the unique name assigned to this script. Let's include the script below in the head section of our project template file:
  @load('intersectJS')
                         
Once the script is included in our file, we can go on to initialize the Intersect plugin at the footer of the web page.
  <script>

     let Intersect = new Intersect;

     console.log(Intersect);

  </script>
                         
When we do a console.log() of the plugin, we will have some returned object that resembles the format below:
  <script>

  Object {  }

     <prototype>: Object { … }
        constructor class Intersect {}
        observe function observe(el)
        item function item(el)
        onScroll function onScroll(el)
        status function status(el)

  </script>
                         
Each of the objects method have their specific functions and these are explained below:

constructor
This is a reference to the object itself which is automatically added when the plugin is instantiated. It mostly does not provide any more functionality on the plugin

observe
This method is called when an object is expected to be observed. It takes an object that contains details of the element to be observed and a callback function. Assumming we have an html button as shown below:
  <button class="btn">cancel</button>
  <button class="btn">submit</button>
                         
We can easily observe these two buttons using the observe() method. This is shown below:
  Intersect = new Intersect;

  Intersect.observe({

     el : ".btn",
     callback : function(entry, observer) {
        console.log(entry);
     }

  })
                         
In the code sample above, the el is used for selecting the buttons to be observed, while the callback will be triggered once the button is in view. Notice that the class selector .btn was used to select the buttons above. Once the button is in view, the entry will return that resembles the format below:
    boundingClientRect: DOMRect { x: 12, y: 11.916671752929688, width: 95.19999694824219, … }
    index: 0
    intersectionRatio: 1
    intersectionRect: DOMRect { x: 12, y: 11.916671752929688, width: 95.19999694824219, … }
    intersections: 0
    inview: true
    isIntersecting: true
    selector: ".btn"
    rootBounds: DOMRect { x: 0, y: 0, width: 678.4000244140625, … }
    target: <button class="btn">
    time: 1188.7
    unobserve: function unobserve()
                         
The object returned above is similar to the entry object returned in an IntersectionObserver API with only slight differences. Some new keys were returned which are index, intersections, inview, target and unobserve().
KeysFunction
index Identifies the count number of a target element is a selected group list
intersections Identifies the total number of intersections made by an element
inview Alias or alternative for isIntersecting.
selector Returns the element's query selector (i.e el)
target Defines the entry target element.
unobserve() Defines the method to unobserve an observed element.
Once we observe an element, we can easily unobserve it as shown below:
  Intersect = new Intersect;

  Intersect.observe({

     el : ".btn",
     
     callback : function(entry) {

        if(entry.inview) entry.unobserve()

     }

  })     
                              
With this returned object index, we can even perform more amazing operations like the sample below where we logged a console message when the second selected button is unobserved.
  Intersect = new Intersect;

  Intersect.observe({

     el : ".btn",
     
     callback : function(entry) {

        if(entry.inview && entry.index === 1) {
          entry.unobserve();
          console.log('second button unobserved!')
        }

     }

  })     
                              
Amazingly, the Intersect plugin makes it easier to use the intersection class for multiple elements just as seen above.

onScroll
This method is called when an object is expected to be observed through an onScroll event. Once used, the Intersection will return the status of the selected elements on every scroll. Although, it is not ideal to use onScroll events on items but it can be helpful in some cases.

  <button class="btn">cancel</button>
  <button class="btn">submit</button>
                         
We can easily observe through the onScroll() method as shown below:
  Intersect = new Intersect;

  Intersect.onScroll({

     el : ".btn",

     callback : function(entry) {
        
          if(entry.inview) {
               console.log(`button ${entry.index + 1} is in intersecting`)
               entry.unobserve()
          }else{
               console.log('scrolling...')
          }

     }

  })
                         
In the code sample above, notice that we used the unobserve() method when the element is finally intersecting. This does not stop the scroll event from happening. Once the unobserve() is called, internally, the element will no longer be observed and this will make the unobserved() method return true. In order to truly end the scroll event, we can use the item() method instead or set the status() method's onScroll key as "scroll-item".

status
This method is called when the status of an element is needed to be retrieved. Although, it can use the onScroll event, by default, the element status is only returned when the observed element is intersecting. When the onScroll key is set as "scroll" or "scroll-item", the onScroll event will be triggered. The only difference between these two options is that while "scroll" does not truly stop a scroll event until the last observed element is unobserved, the scroll-item option truly removes the scroll event and is used on a single element.

  <button class="btn">cancel</button>
  <button class="btn">submit</button>
                         
Using the status method, we can obtain the status of an element as shown below:
  Intersect = new Intersect;

  Intersect.status({

     onScroll : "intersect",

     el : ".btn",

     callback : function(entry) {
        
          if(entry.inview) {
               console.log(entry)
               entry.unobserve()
          }

     }

  })
                         
  Object {    
     
     boundingClientRect: DOMRect { x: 12, y: -3309.833251953125, width: 95.19999694824219, … }
     
     element: {
       aboveWindowTop true
       belowWindowTop false
       fromWindowTop -3309
       index 0
       id ""
       isIntersecting false
       selector ".btn"
       zeroDownwards true
       zeroPoint false
       zeroUpwards false          
     },
     
     id: ""
     index: 0
     intersectionRatio: 0
     intersectionRect: DOMRect { x: 0, y: 0, width: 0, … }
     intersections: 0
     inview: false
     isIntersecting: false
     selector: ".btn"
     rootBounds: DOMRect { x: 0, y: 0, width: 678.4000244140625, … }
     selector: ".btn"
     scrollPoint: 4083.88330078125
     target: <button class="btn">
     time: 566.8
     unobserve: function unobserve()
     unobserved: function unobserved()
  }
                         
In the sample above the "onScroll" key is set as intersect. Which is the default option. This ensures that the status of the element is only returned once it is intersecting. This also means that this default option does not use the scroll event rather it uses only the intersection observer. Notice that in the code sample above some new keys were added. These keys include the element, scrollPoint, unobserved(). The scrollPoint usually returns the current position of the element observed, while the element key contains futher information about the target element which are listed and explained in the table below:
KeysFunction
aboveWindowTop Returns true when the element is entirely above the browsers top and not in view
belowWindowTop Returns true when at least a part of the element is in below the top browser's screen
fromWindowTop Returns the distance of the element from the window's top screen.
isIntersecting Returns true when the target element is intersecting
zeroDownwards Returns true when the target element's current position from the top window is at zero or lower
zeroPoint Returns true when the target element's current position from the top window is at zero
zeroUpwards Returns true when the target element's current position from the top window is at zero or above
The unobserved() method is only useful on scroll event when the onScroll key's option is set as "scroll".
  Intersect = new Intersect;

  Intersect.status({

     onScroll : 'scroll'

     el : ".btn",

     callback : function(entry) {
        
          if(entry.inview) {
               //code block 1
               entry.unobserve()
               console.log('element unobserved!')
          }elseif(entry.unobserved()){
               //code block 2
               console.log('element has been unobserved!')
          }

     }

  })
                         
In the code above, the "code block 1" will continue to run until the element is unobserved. Once the element is unobserved, since the element is a scroll event, the "code block 2" will be triggered an continue to run. The scroll option is equivalent to the onScroll() method discussed earlier. It is important to note that as long as there is still at least one element observed, the scroll event will run internally. Once the last element is unobserved, the scroll element will be removed. Another equivalent option to use is the srcoll-item which is only used on a single element. The element will be observed and once it is unobserved, the scroll event will be removed.
  Intersect = new Intersect;

  Intersect.status({

     onScroll : 'scroll-item'

     el : ".btn",

     callback : function(entry) {
        
          if(entry.inview) {
               entry.unobserve()
               console.log('element unobserved and scroll event detached!')
          }

     }

  })
                         
In the above, notice that when the option "scroll-item" is used, the entry.unobserved() is no longer used. This is because once the scroll event is detached, we can no longer detect if the element has been unobserved. Also, although we are using a class selector, only one element can be selected. If the number of selected elements returned is more than one, the Intersection object will return an error.

item
This method is the same as when the option "scroll-item" is used within the root status() method.

  <button class="btn">cancel</button>
  <button class="btn">submit</button>
                         
We can easily observe through the onScroll() method as shown below:
  Intersect = new Intersect;

  Intersect.item({

     el : ".btn",

     callback : function(entry) {
        
          if(entry.inview) {
               console.log('element unobserved and scroll event detached!')
               entry.unobserve()
          }

     }

  })
                         

Setting options
In the javascript IntersectionObserver API we can set options for rootMargin and threshold. This can also be defined for the Intersection plugin as shown below:


  Intersect = new Intersect();

  Intersect.item({

     el: ".btn",

     threshold: [0],

     rootMargin: "0px",

     callback: function(entry) {
        
          if(entry.inview) {
               console.log('element unobserved and scroll event detached!')
               entry.unobserve()
          }

     }

  })
                         
Aside from the el and callback keys, any key defined in the item(), observe() and onScroll() methods will be added as an option for the IntersectionObserver API.