Skip to content

Commit c90bad7

Browse files
authored
Merge pull request #96 from majorimi/dev/parmalinkscroll_and_tabs_enhancements
Dev/parmalinkscroll and tabs enhancements
2 parents e18af1c + 0325ae6 commit c90bad7

39 files changed

+949
-106
lines changed

.github/docs/JsInterop.md

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ For code examples [see usage](https://github.com/majorimi/blazor-components/blob
1515
You can try it out by using the [demo app](https://blazorextensions.z6.web.core.windows.net/jsinterop).
1616

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

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

172-
173172
### `IScrollHandler` Functions
174-
- **`ScrollToElementAsync`**: **`Task ScrollToElementAsync(ElementReference elementReference)`**<br />
175-
Scrolls the given element into the page view area.
176-
- **`ScrollToElementByIdAsync`**: **`Task ScrollToElementByIdAsync(string id)`**<br />
177-
Finds element by Id and scrolls the given element into the page view area.
178-
- **`ScrollToElementByNameAsync`**: **`Task ScrollToElementByNameAsync(string name)`**<br />
179-
Finds element by name and scrolls the given element into the page view area.
173+
- **`ScrollToElementAsync`**: **`Task ScrollToElementAsync(ElementReference elementReference, bool smooth)`**<br />
174+
Scrolls the given element into the page view area. **Note: smooth scroll on element level might not supported by all browsers.**
175+
- **`ScrollToElementByIdAsync`**: **`Task ScrollToElementByIdAsync(string id, bool smooth)`**<br />
176+
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.**
177+
- **`ScrollToElementByNameAsync`**: **`Task ScrollToElementByNameAsync(string name, bool smooth)`**<br />
178+
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.**
180179
- **`ScrollToPageEndAsync`**: **`Task ScrollToPageEndAsync(bool smooth)`**<br />
181180
Scrolls to end of the page (X bottom).
182181
- **`ScrollToPageTopAsync`**: **`Task ScrollToPageTopAsync(bool smooth)`**<br />
@@ -197,18 +196,34 @@ Removes event listener for 'scroll' HTML event for the whole document/window by
197196
Implements `IAsyncDisposable` interface the injected service should be Disposed.
198197

199198
### `ElementReference` extensions
200-
- **`ScrollToElementAsync`**: **`Task ScrollToElementAsync(this ElementReference elementReference)`**<br />
201-
- **`ScrollToEndAsync`**: **`Task ScrollToEndAsync(this ElementReference elementReference)`**<br />
202-
- **`ScrollToTopAsync`**: **`Task ScrollToTopAsync(this ElementReference elementReference)`**<br />
203-
- **`ScrollToXAsync`**: **`Task ScrollToXAsync(this ElementReference elementReference, double xPos)`**<br />
204-
- **`ScrollToYAsync`**: **`Task ScrollToYAsync(this ElementReference elementReference, double yPos)`**<br />
205-
- **`GetScrollPositionAsync`**: **`Task<double> GetScrollPositionAsync(this ElementReference elementReference)`**<br />
199+
- **`ScrollToElementAsync`**: **`Task ScrollToElementAsync(this ElementReference elementReference, bool smooth = false)`**<br />
200+
Scrolls HTML page to given element. **Note: smooth scroll on element level might not supported by all browsers.**
201+
- **`ScrollToEndAsync`**: **`Task ScrollToEndAsync(this ElementReference elementReference, bool smooth = false)`**<br />
202+
Scrolls inside the given element to the bottom (end). **Note: smooth scroll on element level might not supported by all browsers.**
203+
- **`ScrollToTopAsync`**: **`Task ScrollToTopAsync(this ElementReference elementReference, bool smooth = false)`**<br />
204+
Scrolls inside the given element to the beginning (top). **Note: smooth scroll on element level might not supported by all browsers.**
205+
- **`ScrollToXAsync`**: **`Task ScrollToXAsync(this ElementReference elementReference, double xPos, bool smooth = false)`**<br />
206+
Scrolls inside the given element to the given X position. **Note: smooth scroll on element level might not supported by all browsers.**
207+
- **`ScrollToYAsync`**: **`Task ScrollToYAsync(this ElementReference elementReference, double yPos, bool smooth = false)`**<br />
208+
Scrolls inside the given element to the given Y position. **Note: smooth scroll on element level might not supported by all browsers.**
209+
- **`ScrollToAsync`**: **`Task ScrollToYAsync(this ElementReference elementReference, double xPos, double yPos, bool smooth = false)`**<br />
210+
Scrolls inside the given element to the given X and Y positions. **Note: smooth scroll on element level might not supported by all browsers.**
211+
- **`GetScrollXPositionAsync`**: **`Task<double> GetScrollXPositionAsync(this ElementReference elementReference)`**<br />
212+
Returns given element scroll X (left) position.
213+
- **`GetScrollYPositionAsync`**: **`Task<double> GetScrollYPositionAsync(this ElementReference elementReference)`**<br />
214+
Returns given element scroll Y (top) position.
206215
- **`IsElementHiddenAsync`**: **`Task<bool> IsElementHiddenAsync(this ElementReference elementReference)`**<br />
216+
Returns given element is visible on HTML document or not.
207217
- **`IsElementHiddenBelowAsync`**: **`Task<bool> IsElementHiddenBelowAsync(this ElementReference elementReference)`**<br />
218+
Returns given element is below of the view port.
208219
- **`IsElementHiddenAboveAsync`**: **`Task<bool> IsElementHiddenAboveAsync(this ElementReference elementReference)`**<br />
220+
Returns given element is above of the view port.
209221
- **`ScrollToElementInParentAsync`**: **`Task ScrollToElementInParentAsync(this ElementReference parent, ElementReference innerElement)`**<br />
222+
Scrolls inside the given parent element to the given inner element.
210223
- **`ScrollInParentByIdAsync`**: **`Task ScrollInParentByIdAsync(this ElementReference parent, string id)`**<br />
224+
Scrolls inside the given parent element to the given inner element by Id.
211225
- **`ScrollInParentByClassAsync`**: **`Task ScrollInParentByClassAsync(this ElementReference parent, string className)`**<br />
226+
Scrolls inside the given parent element to the given first found inner element by class name.
212227

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

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

330+
## Browser History JS (See: [demo app](https://blazorextensions.z6.web.core.windows.net/jsinterop#history-js))
331+
**Browser History JS** is an injectable `INavigationHistoryService` service** to access HTML History API functionality.
332+
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.
333+
334+
### Functions
335+
- **`GetLengthAsync`**: **`ValueTask<int> GetLengthAsync()`** <br />
336+
Returns an Integer representing the number of elements in the session history, including the currently loaded page.
337+
- **`GetScrollRestorationAsync`**: **`ValueTask<string> GetScrollRestorationAsync()`** <br />
338+
Allows web applications to explicitly set default scroll restoration behavior on history navigation. This property can be either `auto` or `manual`.
339+
- **`BackAsync`**: **`ValueTask BackAsync()`** <br />
340+
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).
341+
- **`ForwardAsync`**: **`ValueTask ForwardAsync()`** <br />
342+
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).
343+
- **`GoAsync`**: **`ValueTask GoAsync(int delta)`** <br />
344+
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.
345+
- **`ReplaceStateAsync`**: **`ValueTask ReplaceStateAsync(ExpandoObject? state, string title, string url)`** <br />
346+
Updates the most recent entry on the history stack to have the specified data, title, and, if provided, URL.
347+
- **`PushStateAsync`**: **`ValueTask PushStateAsync(ExpandoObject? state, string title, string url)`** <br />
348+
Pushes the given data onto the session history stack with the specified title (and, if provided, URL).
349+
316350

317351
# Configuration
318352

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

356392

.github/docs/PermaLink.md

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

42+
### Events
43+
- **`PermalinkDetected`: `event EventHandler<PermalinkDetectedEventArgs>** <br />
44+
Event handler for parmalinks detected on navigation.
45+
3846
## `PermaLinkElement` component
3947

4048
### Properties
@@ -68,9 +76,17 @@ Callback function called when Permalink icon clicked and **`PermaLinkIconActions
6876
## PermaLinkBlazorServerInitializer
6977
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.**
7078

79+
### Properties
80+
- **`SmootScroll`: `bool { get; set; }` (default: false)** <br />
81+
Scroll should be jump or smoothly scroll. **Note: smooth scroll on element level might not supported by all browsers.**
82+
7183
## PermalinkBlazorWasmInitializer
7284
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.**
7385

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

7692
## Installation
@@ -141,7 +157,7 @@ Also instance should be disposed.
141157
```
142158
@*Permalink initialize*@
143159
@using Majorsoft.Blazor.Components.PermaLink
144-
<PermalinkBlazorWasmInitializer />
160+
<PermalinkBlazorWasmInitializer SmoothScroll="false" />
145161
```
146162

147163
#### Server hosted projects
@@ -208,7 +224,7 @@ It has to be instantiated manually by using the following code. Also instance sh
208224
```
209225
@*Permalink initialize*@
210226
@using Majorsoft.Blazor.Components.PermaLink
211-
<PermaLinkBlazorServerInitializer />
227+
<PermaLinkBlazorServerInitializer SmoothScroll="false" />
212228
```
213229

214230
#### Creating permalink (#) navigation points inside a Blazor page

.github/docs/Tabs.md

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ Sets all `TabItem` elements height in `px`.
3737
Sets all `TabItem` elements element width in `px`.
3838
- **`Disabled`: `bool { get; set; }` (default: false)** <br />
3939
Determines whether all the rendered HTML elements should be disabled or not.
40+
- **`AllowTabActivationByPermalink`: `bool { get; set; }` (default: true)** <br />
41+
Enables or disables `TabItem` activation with URL Permalink fragment.
42+
**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)!**
4043
- **`Animate`: `bool { get; set; }` (default: true)** <br />
4144
Determines to apply CSS animation and transion on Tab changes or not.
4245
- **`TabPositon`: `TabPositons { get; set; }` (default: TabPositons.Left)** <br />
@@ -67,6 +70,9 @@ Required HTML content to show content of current TabItem.
6770
Determines whether the current rendered TabItem should be disabled or not.
6871
- **`Hidden`: `bool { get; set; }` (default: false)** <br />
6972
Determines whether the current rendered TabItem should be hidden or not.
73+
- **`Permalink`: `string { get; set; }` (default: "")** <br />
74+
Permalink value to append to the URL and activate the `TabItem` based on matching value.
75+
**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)!**
7076

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

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

97+
### Dependences
98+
**Majorsoft.Blazor.Components.Tabs** package "partially" depends on other Majorsoft Nuget packages:
99+
- [Majorsoft.Blazor.Components.Common.JsInterop](https://www.nuget.org/packages/Majorsoft.Blazor.Components.Common.JsInterop)
100+
which handles JS Interop for many features e.g. scrolling, etc.
101+
- [Majorsoft.Blazor.Components.Common.PermaLink](https://www.nuget.org/packages/Majorsoft.Blazor.Components.PermaLink)
102+
which track navigations (URL changes) and identify permalink elements.
103+
104+
**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.
105+
Also later this feature can be disabled by `AllowTabActivationByPermalink = false`.**
106+
91107
### `TabsPanel` and `TabItem` usage
92108

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

111+
**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)!**
112+
95113
```
114+
@*Simple tab usage*@
115+
<TabsPanel>
116+
<TabItems>
117+
<TabItem>
118+
<Header>Tab1</Header>
119+
<Content>Tab1</Content>
120+
</TabItem>
121+
<TabItem>
122+
<Header>Tab2</Header>
123+
<Content>Tab2</Content>
124+
</TabItem>
125+
<TabItem>
126+
<Header>Tab3</Header>
127+
<Content>Tab3</Content>
128+
</TabItem>
129+
</TabItems>
130+
</TabsPanel>
131+
132+
@*Advanced tab usage*@
96133
<TabsPanel @ref="_tabs"
97134
ActiveColor="@_activeColor"
98135
InactiveColor="@_inactiveColor"
@@ -105,26 +142,26 @@ Following code example shows how to use **`TabsPanel`** with **`TabItem`** comp
105142
Animate="@_isAnimated"
106143
OnTabChanged="OnTabChanged">
107144
<TabItems>
108-
<TabItem id="tab1" @ref="_tab1">
145+
<TabItem id="tab1" @ref="_tab1" Disabled="false" Permalink="Tab1" Hidden="false">
109146
<Header><strong>Tab 1</strong></Header>
110147
<Content>
111148
<h1>The first tab</h1>
112149
</Content>
113150
</TabItem>
114-
<TabItem @ref="_tab2">
151+
<TabItem @ref="_tab2" Disabled="false" Permalink="Tab2" Hidden="false">
115152
<Header><i>Tab 2</i></Header>
116153
<Content>
117154
<h1>The second tab</h1>
118155
</Content>
119156
</TabItem>
120-
<TabItem id="tab3" @ref="_tab3" Disabled="@_isTabDisabled" Hidden="@_isTabHidden">
157+
<TabItem id="tab3" @ref="_tab3" Disabled="@_isTabDisabled" Permalink="Tab3" Hidden="@_isTabHidden">
121158
<Header><u>Can disable</u></Header>
122159
<Content>
123160
<h1>This tab can be disabled</h1>
124161
<p>And also any <code>TabItem</code> can be disabled by using <code>Disabled</code> property.</p>
125162
</Content>
126163
</TabItem>
127-
<TabItem id="tab4" @ref="_tab4">
164+
<TabItem id="tab4" @ref="_tab4" Disabled="false" Permalink="Tab4" Hidden="false">
128165
<Header>Header icon <i class="fa fa-home"></i></Header>
129166
<Content>
130167
<h1>Tab with icon in header</h1>

src/Majorsoft.Blazor.Components.Common.JsInterop/JsInteropExtension.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using Majorsoft.Blazor.Components.Common.JsInterop.GlobalMouseEvents;
1010
using Majorsoft.Blazor.Components.Common.JsInterop.Head;
1111
using Majorsoft.Blazor.Components.Common.JsInterop.Language;
12+
using Majorsoft.Blazor.Components.Common.JsInterop.Navigation;
1213
using Majorsoft.Blazor.Components.Common.JsInterop.Resize;
1314
using Majorsoft.Blazor.Components.Common.JsInterop.Scroll;
1415

@@ -44,6 +45,7 @@ public static IServiceCollection AddJsInteropExtensions(this IServiceCollection
4445
services.AddTransient<IHtmlHeadService, HtmlHeadService>();
4546
services.AddTransient<IBrowserDateService, BrowserDateService>();
4647
services.AddTransient<IBrowserThemeService, BrowserThemeService>();
48+
services.AddTransient<INavigationHistoryService, NavigationHistoryService>();
4749

4850
return services;
4951
}

src/Majorsoft.Blazor.Components.Common.JsInterop/Majorsoft.Blazor.Components.Common.JsInterop.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<RepositoryType>Git</RepositoryType>
1818
<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>
1919
<PackageReleaseNotes>See Releases here: https://github.com/majorimi/blazor-components/releases</PackageReleaseNotes>
20-
<PackageTags>.Net5 Blazor Js Interop Click Scroll Focus BoundRect</PackageTags>
20+
<PackageTags>.Net5 Blazor Js Interop Click Scroll Resize Focus BoundRect Browser Geolocation Head History ColorTheme</PackageTags>
2121
<PackageLicenseFile>License.txt</PackageLicenseFile>
2222
<Title>Blazor Components JsInterop</Title>
2323
</PropertyGroup>

0 commit comments

Comments
 (0)