// Copyright (c) MudBlazor 2021 // MudBlazor licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using Microsoft.JSInterop; namespace Connected { public class ScrollSectionCenteredEventArgs { public ScrollSectionCenteredEventArgs(string id) { Id = id; } public string Id { get; init; } } public interface IScrollSpy : IAsyncDisposable { /// /// Start spying for scroll events for elements with the specified classes /// /// the class name (without .) to identify the containers to spy on /// public Task StartSpying(string elementsSelector); /// /// Center the viewport to DOM element with the given Id /// /// The Id of the DOM element, that should be centered /// Task ScrollToSection(string id); /// /// Center the viewport to the DOM element represented by the fragment inside the uri /// /// The uri which contains the fragment. If no fragment it scrolls to the top of the page /// Task ScrollToSection(Uri uri); event EventHandler ScrollSectionSectionCentered; /// /// Does the same as ScrollToSection but without the scrolling. This can be used to initially set an value /// /// /// Task SetSectionAsActive(String id); /// /// Get the current position of the centered section /// string CenteredSection { get; } } public class ScrollSpy : IScrollSpy { public string CenteredSection { get; private set; } private readonly IJSRuntime _js; private DotNetObjectReference _dotNetRef; [DynamicDependency(nameof(SectionChangeOccured))] public ScrollSpy(IJSRuntime js) { _js = js; _dotNetRef = DotNetObjectReference.Create(this); } public async Task StartSpying(string containerSelector) => await _js.InvokeVoidAsync ("mudScrollSpy.spying", containerSelector, _dotNetRef); [JSInvokable] public void SectionChangeOccured(string id) { CenteredSection = id; ScrollSectionSectionCentered?.Invoke(this, new ScrollSectionCenteredEventArgs(id)); } public event EventHandler ScrollSectionSectionCentered; public async Task ScrollToSection(string id) { CenteredSection = id; await _js.InvokeVoidAsyncWithErrorHandling ("mudScrollSpy.scrollToSection", id.Trim('#')); } public async Task SetSectionAsActive(string id) { CenteredSection = id; await _js.InvokeVoidAsyncWithErrorHandling ("mudScrollSpy.activateSection", id.Trim('#')); } public async Task ScrollToSection(Uri uri) => await ScrollToSection(uri.Fragment); public async ValueTask DisposeAsync() { try { _dotNetRef?.Dispose(); await _js.InvokeVoidAsyncWithErrorHandling("mudScrollSpy.unspy"); } catch (Exception) { } } } }