Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#498 done; added custom visibility ranges #501

Merged
merged 1 commit into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}

}
Loading