Skip to content

Commit

Permalink
Merge pull request #96 from majorimi/dev/parmalinkscroll_and_tabs_enh…
Browse files Browse the repository at this point in the history
…ancements

Dev/parmalinkscroll and tabs enhancements
  • Loading branch information
majorimi authored Sep 10, 2021
2 parents e18af1c + 0325ae6 commit c90bad7
Show file tree
Hide file tree
Showing 39 changed files with 949 additions and 106 deletions.
68 changes: 52 additions & 16 deletions .github/docs/JsInterop.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ For code examples [see usage](https://github.com/majorimi/blazor-components/blob
You can try it out by using the [demo app](https://blazorextensions.z6.web.core.windows.net/jsinterop).

# Features

- **Click JS**:
- `ClickBoundariesElement` is a component which wraps the given content to a DIV and subscribes to all click events: `OnOutsideClick`, `OnInsideClick`.
- Also an **injectable `IClickBoundariesHandler` service** for callback event handlers.
Expand All @@ -31,8 +30,9 @@ You can try it out by using the [demo app](https://blazorextensions.z6.web.core.
- **Language JS**: is an **injectable `ILanguageService` service** for detect the browser language preference.
- **Browser Date JS**: is an **injectable `IBrowserDateService` service** is a simple JS call to `new Date();` to retrieve client machine date and time.
- **Browser Theme JS**: is an **injectable `IBrowserThemeService` service** to handle Browser color scheme queries and changes.
- **Geo JS**: is an **injectable `IGeolocationService` service** for detect the device Geolocation (GPS position, speed, heading, etc.).
- **Geo JS**: is an **injectable `IGeolocationService` service** for detect the device [Geolocation API](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation_API) (GPS position, speed, heading, etc.).
- **Head JS**: is an **injectable `IHtmlHeadService` service** for accessing and setting HTML document `Head tags`.
- **Browser History JS**: is an **injectable `INavigationHistoryService` service** to access [HTML History API](https://developer.mozilla.org/en-US/docs/Web/API/History) functionality.

## Click JS (See: [demo app](https://blazorextensions.z6.web.core.windows.net/jsinterop#click-js))
**NOTE: Blazor supports `@onclick` event which is equivalent with `OnInsideClick`.
Expand Down Expand Up @@ -169,14 +169,13 @@ Exposes a Blazor `ElementReference` of the wrapped around HTML element. It can b
- **`DisposeAsync()`: `ValueTask IAsyncDisposable()` interface** <br />
Component implements `IAsyncDisposable` interface Blazor framework components also can `@implements IAsyncDisposable` where the injected service should be Disposed.


### `IScrollHandler` Functions
- **`ScrollToElementAsync`**: **`Task ScrollToElementAsync(ElementReference elementReference)`**<br />
Scrolls the given element into the page view area.
- **`ScrollToElementByIdAsync`**: **`Task ScrollToElementByIdAsync(string id)`**<br />
Finds element by Id and scrolls the given element into the page view area.
- **`ScrollToElementByNameAsync`**: **`Task ScrollToElementByNameAsync(string name)`**<br />
Finds element by name and scrolls the given element into the page view area.
- **`ScrollToElementAsync`**: **`Task ScrollToElementAsync(ElementReference elementReference, bool smooth)`**<br />
Scrolls the given element into the page view area. **Note: smooth scroll on element level might not supported by all browsers.**
- **`ScrollToElementByIdAsync`**: **`Task ScrollToElementByIdAsync(string id, bool smooth)`**<br />
Finds element by Id and scrolls the given element into the page view area. **Note: smooth scroll on element level might not supported by all browsers.**
- **`ScrollToElementByNameAsync`**: **`Task ScrollToElementByNameAsync(string name, bool smooth)`**<br />
Finds element by name and scrolls the given element into the page view area. **Note: smooth scroll on element level might not supported by all browsers.**
- **`ScrollToPageEndAsync`**: **`Task ScrollToPageEndAsync(bool smooth)`**<br />
Scrolls to end of the page (X bottom).
- **`ScrollToPageTopAsync`**: **`Task ScrollToPageTopAsync(bool smooth)`**<br />
Expand All @@ -197,18 +196,34 @@ Removes event listener for 'scroll' HTML event for the whole document/window by
Implements `IAsyncDisposable` interface the injected service should be Disposed.

### `ElementReference` extensions
- **`ScrollToElementAsync`**: **`Task ScrollToElementAsync(this ElementReference elementReference)`**<br />
- **`ScrollToEndAsync`**: **`Task ScrollToEndAsync(this ElementReference elementReference)`**<br />
- **`ScrollToTopAsync`**: **`Task ScrollToTopAsync(this ElementReference elementReference)`**<br />
- **`ScrollToXAsync`**: **`Task ScrollToXAsync(this ElementReference elementReference, double xPos)`**<br />
- **`ScrollToYAsync`**: **`Task ScrollToYAsync(this ElementReference elementReference, double yPos)`**<br />
- **`GetScrollPositionAsync`**: **`Task<double> GetScrollPositionAsync(this ElementReference elementReference)`**<br />
- **`ScrollToElementAsync`**: **`Task ScrollToElementAsync(this ElementReference elementReference, bool smooth = false)`**<br />
Scrolls HTML page to given element. **Note: smooth scroll on element level might not supported by all browsers.**
- **`ScrollToEndAsync`**: **`Task ScrollToEndAsync(this ElementReference elementReference, bool smooth = false)`**<br />
Scrolls inside the given element to the bottom (end). **Note: smooth scroll on element level might not supported by all browsers.**
- **`ScrollToTopAsync`**: **`Task ScrollToTopAsync(this ElementReference elementReference, bool smooth = false)`**<br />
Scrolls inside the given element to the beginning (top). **Note: smooth scroll on element level might not supported by all browsers.**
- **`ScrollToXAsync`**: **`Task ScrollToXAsync(this ElementReference elementReference, double xPos, bool smooth = false)`**<br />
Scrolls inside the given element to the given X position. **Note: smooth scroll on element level might not supported by all browsers.**
- **`ScrollToYAsync`**: **`Task ScrollToYAsync(this ElementReference elementReference, double yPos, bool smooth = false)`**<br />
Scrolls inside the given element to the given Y position. **Note: smooth scroll on element level might not supported by all browsers.**
- **`ScrollToAsync`**: **`Task ScrollToYAsync(this ElementReference elementReference, double xPos, double yPos, bool smooth = false)`**<br />
Scrolls inside the given element to the given X and Y positions. **Note: smooth scroll on element level might not supported by all browsers.**
- **`GetScrollXPositionAsync`**: **`Task<double> GetScrollXPositionAsync(this ElementReference elementReference)`**<br />
Returns given element scroll X (left) position.
- **`GetScrollYPositionAsync`**: **`Task<double> GetScrollYPositionAsync(this ElementReference elementReference)`**<br />
Returns given element scroll Y (top) position.
- **`IsElementHiddenAsync`**: **`Task<bool> IsElementHiddenAsync(this ElementReference elementReference)`**<br />
Returns given element is visible on HTML document or not.
- **`IsElementHiddenBelowAsync`**: **`Task<bool> IsElementHiddenBelowAsync(this ElementReference elementReference)`**<br />
Returns given element is below of the view port.
- **`IsElementHiddenAboveAsync`**: **`Task<bool> IsElementHiddenAboveAsync(this ElementReference elementReference)`**<br />
Returns given element is above of the view port.
- **`ScrollToElementInParentAsync`**: **`Task ScrollToElementInParentAsync(this ElementReference parent, ElementReference innerElement)`**<br />
Scrolls inside the given parent element to the given inner element.
- **`ScrollInParentByIdAsync`**: **`Task ScrollInParentByIdAsync(this ElementReference parent, string id)`**<br />
Scrolls inside the given parent element to the given inner element by Id.
- **`ScrollInParentByClassAsync`**: **`Task ScrollInParentByClassAsync(this ElementReference parent, string className)`**<br />
Scrolls inside the given parent element to the given first found inner element by class name.

## Resize JS (See: [demo app](https://blazorextensions.z6.web.core.windows.net/jsinterop#resize-js))
**Resize JS** is an **injectable `IResizeHandler` service** for Window (global) and HTML Elements resize event callback handlers.
Expand Down Expand Up @@ -275,7 +290,6 @@ Removes event listener for `prefers-color-scheme` HTML event for the Browser.
- **`DisposeAsync`: `ValueTask IAsyncDisposable()` interface** <br />
Implements `IAsyncDisposable` interface the injected service should be Disposed.


## Geolocation JS (See: [demo app](https://blazorextensions.z6.web.core.windows.net/jsinterop#geo-js))
**Geolocation JS** is an injectable `IGeolocationService` service for **detect the device Geolocation (GPS position, speed, heading, etc.)**.
It is using the Geolocation API which allows users to provide their location to web applications if they desire.
Expand Down Expand Up @@ -313,6 +327,26 @@ If you have multiple fav icon tags set in the Head first call `GetHtmlFavIconsAs
- **`DisposeAsync`: `ValueTask IAsyncDisposable()` interface** <br />
Implements `IAsyncDisposable` interface the injected service should be Disposed.

## Browser History JS (See: [demo app](https://blazorextensions.z6.web.core.windows.net/jsinterop#history-js))
**Browser History JS** is an injectable `INavigationHistoryService` service** to access HTML History API functionality.
It is useful when don't want to rely on Blazor `NavigationManager` which does not have access to full History list and when it navigates trigger a page load/update.

### Functions
- **`GetLengthAsync`**: **`ValueTask<int> GetLengthAsync()`** <br />
Returns an Integer representing the number of elements in the session history, including the currently loaded page.
- **`GetScrollRestorationAsync`**: **`ValueTask<string> GetScrollRestorationAsync()`** <br />
Allows web applications to explicitly set default scroll restoration behavior on history navigation. This property can be either `auto` or `manual`.
- **`BackAsync`**: **`ValueTask BackAsync()`** <br />
This asynchronous method goes to the previous page in session history, the same action as when the user clicks the browser's Back button. Equivalent to history.go(-1).
- **`ForwardAsync`**: **`ValueTask ForwardAsync()`** <br />
This asynchronous method goes to the next page in session history, the same action as when the user clicks the browser's Forward button; this is equivalent to history.go(1).
- **`GoAsync`**: **`ValueTask GoAsync(int delta)`** <br />
Asynchronously loads a page from the session history, identified by its relative location to the current page, for example -1 for the previous page or 1 for the next page.
- **`ReplaceStateAsync`**: **`ValueTask ReplaceStateAsync(ExpandoObject? state, string title, string url)`** <br />
Updates the most recent entry on the history stack to have the specified data, title, and, if provided, URL.
- **`PushStateAsync`**: **`ValueTask PushStateAsync(ExpandoObject? state, string title, string url)`** <br />
Pushes the given data onto the session history stack with the specified title (and, if provided, URL).


# Configuration

Expand Down Expand Up @@ -351,6 +385,8 @@ Add using statement to your Blazor <component/page>.razor file. Or globally refe
@using Majorsoft.Blazor.Components.Common.JsInterop.BrowserDate
@*Only if you want to use Browser ColorTheme*@
@using Majorsoft.Blazor.Components.Common.JsInterop.BrowserColorTheme
@*Only if you want to use Browser History*@
@using Majorsoft.Blazor.Components.Common.JsInterop.History
```


Expand Down
20 changes: 18 additions & 2 deletions .github/docs/PermaLink.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,17 @@ For more details see Usage section.
### Functions
- **`WatchPermaLinks()`**: **`void WatchPermaLinks()`** <br />
Starts a navigation watcher which will check for Permalinks in the URLs.
- **`ChangePermalink()`**: **`void ChangePermalink(string? newPermalink, bool doNotNavigate)`** <br />
Modify the current URL with given new peralink value and trigger navigation or just update browser History.
- **`CheckPermalink()`**: **`string? CheckPermalink(bool triggerEvent = false)`** <br />
Checks the current URL for permalink again and re-triggers `PermalinkDetected` event if requested.
- **`Dispose()`: `@implements IDisposable` interface** <br />
Component implements `IDisposable` interface Blazor framework will call it when parent removed from render tree.

### Events
- **`PermalinkDetected`: `event EventHandler<PermalinkDetectedEventArgs>** <br />
Event handler for parmalinks detected on navigation.

## `PermaLinkElement` component

### Properties
Expand Down Expand Up @@ -68,9 +76,17 @@ Callback function called when Permalink icon clicked and **`PermaLinkIconActions
## PermaLinkBlazorServerInitializer
Available from v1.4.0 It is convenient wrapper component to initialize navigation watcher in your Blazor Server App `MainLayout.razor` page. **Only one Initializer component allowed per Application.**

### Properties
- **`SmootScroll`: `bool { get; set; }` (default: false)** <br />
Scroll should be jump or smoothly scroll. **Note: smooth scroll on element level might not supported by all browsers.**

## PermalinkBlazorWasmInitializer
Available from v1.4.0 It is convenient wrapper component to initialize navigation watcher in your Blazor WebAssembly App `MainLayout.razor` page. **Only one Initializer component allowed per Application.**

### Properties
- **`SmootScroll`: `bool { get; set; }` (default: false)** <br />
Scroll should be jump or smoothly scroll. **Note: smooth scroll on element level might not supported by all browsers.**

# Configuration

## Installation
Expand Down Expand Up @@ -141,7 +157,7 @@ Also instance should be disposed.
```
@*Permalink initialize*@
@using Majorsoft.Blazor.Components.PermaLink
<PermalinkBlazorWasmInitializer />
<PermalinkBlazorWasmInitializer SmoothScroll="false" />
```

#### Server hosted projects
Expand Down Expand Up @@ -208,7 +224,7 @@ It has to be instantiated manually by using the following code. Also instance sh
```
@*Permalink initialize*@
@using Majorsoft.Blazor.Components.PermaLink
<PermaLinkBlazorServerInitializer />
<PermaLinkBlazorServerInitializer SmoothScroll="false" />
```

#### Creating permalink (#) navigation points inside a Blazor page
Expand Down
45 changes: 41 additions & 4 deletions .github/docs/Tabs.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ Sets all `TabItem` elements height in `px`.
Sets all `TabItem` elements element width in `px`.
- **`Disabled`: `bool { get; set; }` (default: false)** <br />
Determines whether all the rendered HTML elements should be disabled or not.
- **`AllowTabActivationByPermalink`: `bool { get; set; }` (default: true)** <br />
Enables or disables `TabItem` activation with URL Permalink fragment.
**NOTE: in order to make TabActivation work `Majorsoft.Blazor.Components.PermaLink` component is used and it MUST [set up correctly](https://github.com/majorimi/blazor-components/blob/master/.github/docs/PermaLink.md#configuration)!**
- **`Animate`: `bool { get; set; }` (default: true)** <br />
Determines to apply CSS animation and transion on Tab changes or not.
- **`TabPositon`: `TabPositons { get; set; }` (default: TabPositons.Left)** <br />
Expand Down Expand Up @@ -67,6 +70,9 @@ Required HTML content to show content of current TabItem.
Determines whether the current rendered TabItem should be disabled or not.
- **`Hidden`: `bool { get; set; }` (default: false)** <br />
Determines whether the current rendered TabItem should be hidden or not.
- **`Permalink`: `string { get; set; }` (default: "")** <br />
Permalink value to append to the URL and activate the `TabItem` based on matching value.
**NOTE: in order to make TabActivation work `Majorsoft.Blazor.Components.PermaLink` component is used and it MUST [set up correctly](https://github.com/majorimi/blazor-components/blob/master/.github/docs/PermaLink.md#configuration)!**

**Arbitrary HTML attributes e.g.: `tabindex="1"` will be passed to the corresponding rendered HTML element `<input>`**.

Expand All @@ -88,11 +94,42 @@ Add using statement to your Blazor `<component/page>.razor` file. Or globally re
@using Majorsoft.Blazor.Components.Tabs
```

### Dependences
**Majorsoft.Blazor.Components.Tabs** package "partially" depends on other Majorsoft Nuget packages:
- [Majorsoft.Blazor.Components.Common.JsInterop](https://www.nuget.org/packages/Majorsoft.Blazor.Components.Common.JsInterop)
which handles JS Interop for many features e.g. scrolling, etc.
- [Majorsoft.Blazor.Components.Common.PermaLink](https://www.nuget.org/packages/Majorsoft.Blazor.Components.PermaLink)
which track navigations (URL changes) and identify permalink elements.

**NOTE: only TabItem activation feature depend on Permalink. If you don't want to use that feature just leave `Permalink` parameters empty and do not setup PermalinkWatcher.
Also later this feature can be disabled by `AllowTabActivationByPermalink = false`.**

### `TabsPanel` and `TabItem` usage

Following code example shows how to use **`TabsPanel`** with **`TabItem`** component in your Blazor App.

**NOTE: to use TabActivation feature `Permalink="Tab1"` must be set and Permalink services must be [configured correctly](https://github.com/majorimi/blazor-components/blob/master/.github/docs/PermaLink.md#configuration)!**

```
@*Simple tab usage*@
<TabsPanel>
<TabItems>
<TabItem>
<Header>Tab1</Header>
<Content>Tab1</Content>
</TabItem>
<TabItem>
<Header>Tab2</Header>
<Content>Tab2</Content>
</TabItem>
<TabItem>
<Header>Tab3</Header>
<Content>Tab3</Content>
</TabItem>
</TabItems>
</TabsPanel>
@*Advanced tab usage*@
<TabsPanel @ref="_tabs"
ActiveColor="@_activeColor"
InactiveColor="@_inactiveColor"
Expand All @@ -105,26 +142,26 @@ Following code example shows how to use **`TabsPanel`** with **`TabItem`** comp
Animate="@_isAnimated"
OnTabChanged="OnTabChanged">
<TabItems>
<TabItem id="tab1" @ref="_tab1">
<TabItem id="tab1" @ref="_tab1" Disabled="false" Permalink="Tab1" Hidden="false">
<Header><strong>Tab 1</strong></Header>
<Content>
<h1>The first tab</h1>
</Content>
</TabItem>
<TabItem @ref="_tab2">
<TabItem @ref="_tab2" Disabled="false" Permalink="Tab2" Hidden="false">
<Header><i>Tab 2</i></Header>
<Content>
<h1>The second tab</h1>
</Content>
</TabItem>
<TabItem id="tab3" @ref="_tab3" Disabled="@_isTabDisabled" Hidden="@_isTabHidden">
<TabItem id="tab3" @ref="_tab3" Disabled="@_isTabDisabled" Permalink="Tab3" Hidden="@_isTabHidden">
<Header><u>Can disable</u></Header>
<Content>
<h1>This tab can be disabled</h1>
<p>And also any <code>TabItem</code> can be disabled by using <code>Disabled</code> property.</p>
</Content>
</TabItem>
<TabItem id="tab4" @ref="_tab4">
<TabItem id="tab4" @ref="_tab4" Disabled="false" Permalink="Tab4" Hidden="false">
<Header>Header icon <i class="fa fa-home"></i></Header>
<Content>
<h1>Tab with icon in header</h1>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Majorsoft.Blazor.Components.Common.JsInterop.GlobalMouseEvents;
using Majorsoft.Blazor.Components.Common.JsInterop.Head;
using Majorsoft.Blazor.Components.Common.JsInterop.Language;
using Majorsoft.Blazor.Components.Common.JsInterop.Navigation;
using Majorsoft.Blazor.Components.Common.JsInterop.Resize;
using Majorsoft.Blazor.Components.Common.JsInterop.Scroll;

Expand Down Expand Up @@ -44,6 +45,7 @@ public static IServiceCollection AddJsInteropExtensions(this IServiceCollection
services.AddTransient<IHtmlHeadService, HtmlHeadService>();
services.AddTransient<IBrowserDateService, BrowserDateService>();
services.AddTransient<IBrowserThemeService, BrowserThemeService>();
services.AddTransient<INavigationHistoryService, NavigationHistoryService>();

return services;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<RepositoryType>Git</RepositoryType>
<Description>Blazor component that provides useful functionality and event notifications which can be achieved only with JS Interop e.g. scroll, clipboard, focus, resize, language detection, GEO location, etc. Part of Majorsoft Blazor library.</Description>
<PackageReleaseNotes>See Releases here: https://github.com/majorimi/blazor-components/releases</PackageReleaseNotes>
<PackageTags>.Net5 Blazor Js Interop Click Scroll Focus BoundRect</PackageTags>
<PackageTags>.Net5 Blazor Js Interop Click Scroll Resize Focus BoundRect Browser Geolocation Head History ColorTheme</PackageTags>
<PackageLicenseFile>License.txt</PackageLicenseFile>
<Title>Blazor Components JsInterop</Title>
</PropertyGroup>
Expand Down
Loading

0 comments on commit c90bad7

Please sign in to comment.