Skip to content

Commit

Permalink
#498 done; added custom visibility ranges
Browse files Browse the repository at this point in the history
  • Loading branch information
vaadin-miki committed Dec 15, 2023
1 parent bfaa8e6 commit 4d7e5a4
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 3 deletions.
2 changes: 1 addition & 1 deletion superfields/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ A wrapper for one instance of client-side `IntersectionObserver`. It allows obse

### `LazyLoad`

A simple wrapper to lazy load contents when the component gets into view.
A simple wrapper to lazy load contents when the component gets into view. By default, content is loaded when the component gets fully into view, but it is possible to configure it to load when only a part gets into view.

### `ObservedField`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ public static final class LazyLoadElement extends Div {}

private C lazyLoadedContent = null;

private double hiddenVisibilityRange = 0.0d;
private double shownVisibilityRange = 1.0d;

/**
* Creates lazy load wrapper for given contents. It will be displayed the first time this component becomes shown on screen.
* @param contents Contents to wrap for lazy loading.
Expand Down Expand Up @@ -116,15 +119,65 @@ public LazyLoad(SerializableSupplier<C> contentSupplier, SerializableSupplier<Co
}

private void onComponentObserved(ComponentObservationEvent event) {
if(event.isFullyVisible()) {
if(event.getVisibilityRange() >= this.getContentShownVisibilityRange()) {
this.onNowVisible();
if(this.onlyLoadedOnce)
this.observer.unobserve(this);
}
else if(event.isNotVisible())
else if(event.getVisibilityRange() <= this.getContentHiddenVisibilityRange())
this.onNowHidden();
}

/**
* Returns the current range for considering the lazy-loaded component hidden.
* @return A number between 0 (inclusive) and {@link #getContentShownVisibilityRange()} (inclusive).
* @see #setContentVisibilityRanges(double, double)
*/
public double getContentHiddenVisibilityRange() {
return this.hiddenVisibilityRange;
}

/**
* Returns the current range for considering the lazy-loaded component visible.
* @return A number between {@link #getContentHiddenVisibilityRange()} (inclusive) and 1 (inclusive).
* @see #setContentVisibilityRanges(double, double)
*/
public double getContentShownVisibilityRange() {
return this.shownVisibilityRange;
}

/**
* Defines visibility ranges. {@link LazyLoad} uses a {@link ComponentObserver} to decide if the content should be shown or not.
* By default, the component is lazy-loaded when {@link LazyLoad} is fully visible and hidden when it is fully invisible.
* Defining ranges allows for lazy-loading the contents when it becomes partially visible. Be sure to know what you are doing and why.
* @param hiddenOnOrBelow Visibility range at which or below which the component is considered hidden. Must be between 0 (inclusive) and the other parameter (inclusive).
* @param visibleOnOrAbove Visibility range at which or above which the component is considered visible. Must be between the other parameter (inclusive) and 1 (inclusive).
* @see <a href="https://github.com/vaadin-miki/super-fields/issues/498">issue 498</a>
* @throws IllegalArgumentException when either range is below 0, above 1, or the first parameter is greater than the second
*/
public void setContentVisibilityRanges(double hiddenOnOrBelow, double visibleOnOrAbove) {
if(hiddenOnOrBelow < 0 || visibleOnOrAbove > 1)
throw new IllegalArgumentException("component visibility boundaries must be between 0 and 1 (inclusive), but were %.3f and %.3f".formatted(hiddenOnOrBelow, visibleOnOrAbove));
else if(hiddenOnOrBelow > visibleOnOrAbove)
throw new IllegalArgumentException("visibility boundary for hiding the component (%.3f) must not be greater than the boundary for showing it (%.3f)".formatted(hiddenOnOrBelow, visibleOnOrAbove));
else {
this.shownVisibilityRange = visibleOnOrAbove;
this.hiddenVisibilityRange = hiddenOnOrBelow;
}
}

/**
* Chains {@link #setContentVisibilityRanges(double, double)} and returns itself.
* @param hiddenOnOrBelow Visibility range at which or below which the component is considered hidden. Must be between 0 (inclusive) and the other parameter (inclusive).
* @param visibleOnOrAbove Visibility range at which or above which the component is considered visible. Must be between the other parameter (inclusive) and 1 (inclusive).
* @return This.
* @see #setContentVisibilityRanges(double, double)
*/
public LazyLoad<C> withContentVisibilityRanges(double hiddenOnOrBelow, double visibleOnOrAbove) {
this.setContentVisibilityRanges(hiddenOnOrBelow, visibleOnOrAbove);
return this;
}

/**
* Called when the content becomes hidden.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package org.vaadin.miki.superfields.lazyload;

import com.github.mvysny.kaributesting.v10.MockVaadin;
import com.vaadin.flow.component.html.Span;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

/**
* @author miki
* @since 2023-12-15
*/
public class LazyLoadTest {

private LazyLoad<Span> lazyLoad;

@Before
public void setup() {
MockVaadin.setup();
this.lazyLoad = new LazyLoad<>(new Span("this is a test"));
}

@After
public void tearDown() {
MockVaadin.tearDown();
}

@Test(expected = IllegalArgumentException.class)
public void testVisibilityBelowZero() {
this.lazyLoad.setContentVisibilityRanges(-3, 0.5);
}

@Test(expected = IllegalArgumentException.class)
public void testVisibilityAboveOne() {
this.lazyLoad.setContentVisibilityRanges(0.1, 1.5);
}

@Test(expected = IllegalArgumentException.class)
public void testVisibilityNotInOrder() {
this.lazyLoad.setContentVisibilityRanges(0.9, 0.8);
}

@Test
public void testVisibilityRangesOk() {
Assert.assertEquals(0, this.lazyLoad.getContentHiddenVisibilityRange(), 0.000005);
Assert.assertEquals(1, this.lazyLoad.getContentShownVisibilityRange(), 0.000005);

this.lazyLoad.setContentVisibilityRanges(0.2, 0.75);
Assert.assertEquals(0.2, this.lazyLoad.getContentHiddenVisibilityRange(), 0.0005);
Assert.assertEquals(0.75, this.lazyLoad.getContentShownVisibilityRange(), 0.0005);
}

}

0 comments on commit 4d7e5a4

Please sign in to comment.