Skip to content

Commit

Permalink
Update resize
Browse files Browse the repository at this point in the history
  • Loading branch information
artemiusgreat committed Feb 11, 2024
1 parent 45502d5 commit 9901116
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 37 deletions.
4 changes: 2 additions & 2 deletions Libs/ScriptContainer.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
Expand All @@ -8,7 +8,7 @@

<PropertyGroup>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Version>1.1.9</Version>
<Version>1.2.0</Version>
<Authors>artemiusgreat</Authors>
<Copyright>indemos.com</Copyright>
<PackageProjectUrl>http://indemos.com</PackageProjectUrl>
Expand Down
107 changes: 84 additions & 23 deletions Libs/ScriptControl.razor.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,105 @@
function ScriptModule(instance, options) {

this.events = [];
this.sizeScheduler = null;
this.sizeObservers = [];
this.serviceInstance = instance;

this.getDocBounds = () => {
/// <summary>
/// Get window size
/// </summary>
this.getDocBounds = () => this.getElementBounds(document.body);

/// <summary>
/// Get element size
/// </summary>
/// <param name="element"></param>
this.getElementBounds = element => {
const bounds = element.getBoundingClientRect();
return {
X: document.body.clientWidth,
Y: document.body.clientHeight
X: element.clientWidth || element.scrollWidth || bounds.width,
Y: element.clientHeight || element.scrollHeight || bounds.height
};
};

this.getElementBounds = (element) => {
const bounds = element.getBoundingClientRect();
return {
X: bounds.width,
Y: bounds.height
/// <summary>
/// Subscribe to custom event
/// </summary>
/// <param name="element"></param>
/// <param name="event"></param>
/// <param name="action"></param>
this.subscribe = (element, event, action) => {
let scheduler = null;
let index = this.sizeObservers.length;
let change = e => {
clearTimeout(scheduler);
scheduler = setTimeout(() => {
this.serviceInstance && this
.serviceInstance
.invokeMethodAsync(action, e, index, event)
.catch(o => this.unsubscribe());
}, options.interval || 100);
};
element.addEventListener(event, change, false);
this.events.push({ element, event, change });
return this.events.length - 1;
};

this.onSize = () => {
clearTimeout(this.sizeScheduler);
this.sizeScheduler = setTimeout(() => {
this
.serviceInstance
.invokeMethodAsync("OnSizeChange", this.getDocBounds())
.catch(o => this.unsubscribe());
}, options.interval);
/// <summary>
/// Unsubscribe from custom event
/// </summary>
/// <param name="index"></param>
this.unsubscribe = index => {
this.events.forEach((o, i) => {
if (this.events[index] || i === index) {
o.element.removeEventListener(o.event, o.change);
this.events[i] = null;
}
});
this.events = this.events.filter(o => o);
};

this.subscribe = (element, e, done) => {
element.addEventListener(e, done, false);
this.events.push({ element, e, done });
/// <summary>
/// Subscribe to element resize
/// </summary>
/// <param name="element"></param>
/// <param name="action"></param>
this.subscribeToSize = (element, action) => {
let scheduler = null;
let index = this.sizeObservers.length;
let change = e => {
clearTimeout(scheduler);
scheduler = setTimeout(() => {
this.serviceInstance && this
.serviceInstance
.invokeMethodAsync(action, e, index, "resize")
.catch(o => this.unsubscribeFromSize());
}, options.interval || 100);
};
this.sizeObservers.push(new ResizeObserver(change).observe(element));
return this.sizeObservers.length - 1;
};

this.unsubscribe = () => {
this.events.forEach(o => o.element.removeEventListener(o.e, o.done));
/// <summary>
/// Unsubscribe from size observer
/// </summary>
/// <param name="index"></param>
this.unsubscribeFromSize = index => {
this.sizeObservers.forEach((o, i) => {
if (this.sizeObservers[index] || i === index) {
this.sizeObservers[i].disconnect();
this.sizeObservers[i] = null;
}
});
this.sizeObservers = this.sizeObservers.filter(o => o);
};

this.subscribe(window, "resize", this.onSize);
try {
this.unsubscribeFromSize();
this.subscribeToSize(document.body, "OnChangeAction");
} catch (e) {
this.unsubscribe();
this.subscribe(window, "resize", "OnChangeAction");
}
};

export function getScriptModule(instance, options) {
Expand Down
15 changes: 7 additions & 8 deletions Libs/ScriptService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
using Microsoft.JSInterop;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using static System.Collections.Specialized.BitVector32;

namespace ScriptContainer
{
Expand Down Expand Up @@ -40,7 +42,7 @@ public class ScriptService : IAsyncDisposable
/// <summary>
/// On size event
/// </summary>
public Action<ScriptMessage> OnSize { get; set; } = o => { };
public Action<dynamic, int, string> OnChange { get; set; } = (o, i, action) => { };

/// <summary>
/// Get document bounds
Expand Down Expand Up @@ -81,11 +83,6 @@ public async Task<ScriptService> CreateModule(IDictionary<string, object> option

options ??= new Dictionary<string, object>();

if (options.TryGetValue("interval", out var interval) is false)
{
options["interval"] = 100;
}

_serviceInstance = DotNetObjectReference.Create(this);
_scriptModule = await _runtime.InvokeAsync<IJSObjectReference>("import", "./_content/ScriptContainer/ScriptControl.razor.js");
_scriptInstance = await _scriptModule.InvokeAsync<IJSObjectReference>("getScriptModule", _serviceInstance, options);
Expand All @@ -97,17 +94,19 @@ public async Task<ScriptService> CreateModule(IDictionary<string, object> option
/// Script proxy
/// </summary>
/// <param name="message"></param>
/// <param name="index"></param>
/// <param name="action"></param>
/// <returns></returns>
[JSInvokable]
public void OnSizeChange(ScriptMessage message) => OnSize(message);
public void OnChangeAction(dynamic message, int index, string action) => OnChange(message, index, action);

/// <summary>
/// Dispose
/// </summary>
/// <returns></returns>
public async ValueTask DisposeAsync()
{
OnSize = o => { };
OnChange = (o, i, action) => { };

if (_scriptInstance is not null)
{
Expand Down
2 changes: 1 addition & 1 deletion Samples/SampleClient/Pages/Index.razor
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
await ScaleService.CreateModule();
await GetBounds();

ScaleService.OnSize = async message => await GetBounds();
ScaleService.OnChange = async (message, index, action) => await GetBounds();
}

protected async Task GetBounds()
Expand Down
21 changes: 19 additions & 2 deletions Samples/SampleServer/Pages/Index.razor
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
@inject IJSRuntime runtime

<div class="element-container">
<button @onclick="Setup">
<button @onclick="Increase">
Setup
</button>
<div class="doc">
Expand All @@ -27,6 +27,15 @@
<li>@ItemBH</li>
</ul>
</div>
@if (Rows.Any())
{
<ul>
@foreach (var row in Rows)
{
<li>@row</li>
}
</ul>
}
</div>

@code
Expand All @@ -42,6 +51,7 @@
public ElementReference ElementB { get; set; }
public ElementReference CanvasA { get; set; }
public ElementReference CanvasB { get; set; }
public IList<string> Rows { get; set; } = new string[0];

protected override async Task OnAfterRenderAsync(bool setup)
{
Expand All @@ -53,6 +63,13 @@
await base.OnAfterRenderAsync(setup);
}

protected void Increase()
{
Rows = Rows.Any() ?
new string[0] :
Enumerable.Range(0, 50).Select(o => $"{o}").ToList();
}

protected async Task Setup()
{
ScaleService?.DisposeAsync();
Expand All @@ -61,7 +78,7 @@
await ScaleService.CreateModule();
await GetBounds();

ScaleService.OnSize = async message => await GetBounds();
ScaleService.OnChange = async (message, index, action) => await GetBounds();
}

protected async Task GetBounds()
Expand Down
1 change: 0 additions & 1 deletion Samples/SampleServer/wwwroot/css/site.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ html, body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
height: 100%;
overflow: auto;
display: grid;
}

main, article, .element-container {
Expand Down

0 comments on commit 9901116

Please sign in to comment.