All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.patternfly.component.backtotop.BackToTop Maven / Gradle / Ivy

There is a newer version: 0.2.11
Show newest version
/*
 *  Copyright 2023 Red Hat
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.patternfly.component.backtotop;

import java.util.function.Supplier;

import org.gwtproject.event.shared.HandlerRegistration;
import org.jboss.elemento.Attachable;
import org.jboss.elemento.By;
import org.jboss.elemento.Elements;
import org.patternfly.component.BaseComponentFlat;
import org.patternfly.component.ComponentType;
import org.patternfly.component.WithText;
import org.patternfly.component.button.Button;
import org.patternfly.style.Classes;

import elemental2.dom.HTMLElement;
import elemental2.dom.MutationRecord;
import elemental2.dom.ScrollToOptions;

import static elemental2.dom.DomGlobal.document;
import static elemental2.dom.DomGlobal.window;
import static org.jboss.elemento.Elements.a;
import static org.jboss.elemento.Elements.div;
import static org.jboss.elemento.EventType.bind;
import static org.jboss.elemento.EventType.click;
import static org.jboss.elemento.EventType.scroll;
import static org.patternfly.component.IconPosition.end;
import static org.patternfly.component.button.Button.button;
import static org.patternfly.icon.IconSets.fas.angleUp;
import static org.patternfly.style.Classes.backToTop;
import static org.patternfly.style.Classes.hidden;
import static org.patternfly.style.Classes.modifier;

/**
 * The back to top component is a shortcut that allows users to quickly navigate to the top of a lengthy content page.
 *
 * @see https://www.patternfly.org/components/back-to-top
 */
public class BackToTop extends BaseComponentFlat
        implements WithText, Attachable {

    // ------------------------------------------------------ factory

    public static BackToTop backToTop() {
        return backToTop("Back to top");
    }

    public static BackToTop backToTop(String text) {
        return new BackToTop(text);
    }

    // ------------------------------------------------------ instance

    private static final int VISIBILITY_THRESHOLD = 400;

    private final Button button;
    private final ScrollToOptions scrollToOptions;
    private boolean alwaysVisible;
    private HTMLElement element;
    private Supplier elementSupplier;
    private HandlerRegistration hr;

    BackToTop(String text) {
        super(ComponentType.BackToTop, div().css(Classes.component(backToTop)).element());
        alwaysVisible = false;
        scrollToOptions = ScrollToOptions.create();
        scrollToOptions.setTop(0);
        scrollToOptions.setBehavior("smooth");
        button = button(a())
                .primary()
                .iconAndText(angleUp(), text, end)
                .href("#")
                .on(click, e -> {
                    e.preventDefault();
                    scrollUp();
                });
        element().appendChild(button.element());
        Attachable.register(this, this);
    }

    @Override
    public void attach(MutationRecord mutationRecord) {
        if (!alwaysVisible) {
            css(modifier(hidden));
            element = elementSupplier.get();
            if (element == null) {
                hr = bind(window, scroll.name, __ -> toggleVisible((int) window.scrollY));
            } else {
                hr = bind(element, scroll.name, __ -> toggleVisible((int) element.scrollTop));
            }
        }
    }

    @Override
    public void detach(MutationRecord mutationRecord) {
        if (hr != null) {
            hr.removeHandler();
        }
    }

    // ------------------------------------------------------ builder

    @Override
    public BackToTop text(String text) {
        button.text(text);
        return this;
    }

    /** Same as {@linkplain #alwaysVisible(boolean) alwaysVisible(true)} */
    public BackToTop alwaysVisible() {
        return alwaysVisible(true);
    }

    /** Flag to indicate Accordion content is alwaysVisible */
    public BackToTop alwaysVisible(boolean alwaysVisible) {
        this.alwaysVisible = alwaysVisible;
        return this;
    }

    public BackToTop scrollableSelector(String selector) {
        return scrollableSelector(() -> Elements.find(document, By.selector(selector)));
    }

    public BackToTop scrollableSelector(By selector) {
        return scrollableSelector(() -> Elements.find(document, selector));
    }

    public BackToTop scrollableSelector(HTMLElement element) {
        return scrollableSelector(() -> element);
    }

    public BackToTop scrollableSelector(Supplier element) {
        this.elementSupplier = element;
        return this;
    }

    @Override
    public BackToTop that() {
        return this;
    }

    // ------------------------------------------------------ api

    @Override
    public String text() {
        return button.text();
    }

    // ------------------------------------------------------ internal

    private void toggleVisible(int y) {
        Elements.toggle(element(), modifier(hidden), y < VISIBILITY_THRESHOLD);
    }

    private void scrollUp() {
        if (element != null) {
            element.scrollTo(scrollToOptions);
        } else {
            window.scrollTo(scrollToOptions);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy