diff --git a/BlazorReorder.sln b/BlazorReorder.sln index 7a7e994..e620a90 100644 --- a/BlazorReorder.sln +++ b/BlazorReorder.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 17.2.32314.265 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorReorderExample", "BlazorReorderExample\BlazorReorderExample.csproj", "{43EF61CE-4621-48DB-8648-AA686391D140}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorReorderList", "BlazorReorderList\BlazorReorderList.csproj", "{3DCD1165-CC1D-4015-A6D4-CE97E8A4A72B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {43EF61CE-4621-48DB-8648-AA686391D140}.Debug|Any CPU.Build.0 = Debug|Any CPU {43EF61CE-4621-48DB-8648-AA686391D140}.Release|Any CPU.ActiveCfg = Release|Any CPU {43EF61CE-4621-48DB-8648-AA686391D140}.Release|Any CPU.Build.0 = Release|Any CPU + {3DCD1165-CC1D-4015-A6D4-CE97E8A4A72B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3DCD1165-CC1D-4015-A6D4-CE97E8A4A72B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3DCD1165-CC1D-4015-A6D4-CE97E8A4A72B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3DCD1165-CC1D-4015-A6D4-CE97E8A4A72B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/BlazorReorderExample/BlazorReorderExample.csproj b/BlazorReorderExample/BlazorReorderExample.csproj index 55d6b38..ed4f999 100644 --- a/BlazorReorderExample/BlazorReorderExample.csproj +++ b/BlazorReorderExample/BlazorReorderExample.csproj @@ -11,6 +11,10 @@ + + + + compressed diff --git a/BlazorReorderExample/Pages/FetchData.razor b/BlazorReorderExample/Pages/FetchData.razor deleted file mode 100644 index 7d004a5..0000000 --- a/BlazorReorderExample/Pages/FetchData.razor +++ /dev/null @@ -1,57 +0,0 @@ -@page "/fetchdata" -@inject HttpClient Http - -Weather forecast - -

Weather forecast

- -

This component demonstrates fetching data from the server.

- -@if (forecasts == null) -{ -

Loading...

-} -else -{ - - - - - - - - - - - @foreach (var forecast in forecasts) - { - - - - - - - } - -
DateTemp. (C)Temp. (F)Summary
@forecast.Date.ToShortDateString()@forecast.TemperatureC@forecast.TemperatureF@forecast.Summary
-} - -@code { - private WeatherForecast[]? forecasts; - - protected override async Task OnInitializedAsync() - { - forecasts = await Http.GetFromJsonAsync("sample-data/weather.json"); - } - - public class WeatherForecast - { - public DateTime Date { get; set; } - - public int TemperatureC { get; set; } - - public string? Summary { get; set; } - - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); - } -} diff --git a/BlazorReorderExample/Pages/Index.razor b/BlazorReorderExample/Pages/Index.razor index b30b450..e35d82a 100644 --- a/BlazorReorderExample/Pages/Index.razor +++ b/BlazorReorderExample/Pages/Index.razor @@ -17,8 +17,6 @@ Welcome to your new reorderer list. @code { - public record ListItem(string title, string url, string details); - public List list = new() { new ListItem("Google", "google.com", "Again looking for a bug ..."), diff --git a/BlazorReorderExample/Program.cs b/BlazorReorderExample/Program.cs index 3253411..4c8572b 100644 --- a/BlazorReorderExample/Program.cs +++ b/BlazorReorderExample/Program.cs @@ -7,5 +7,8 @@ builder.RootComponents.Add("#app"); builder.RootComponents.Add("head::after"); builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); +builder.Services.AddTransient>(); await builder.Build().RunAsync(); + +public record ListItem(string title, string url, string details); diff --git a/BlazorReorderExample/Shared/NavMenu.razor b/BlazorReorderExample/Shared/NavMenu.razor index fe91085..40bc214 100644 --- a/BlazorReorderExample/Shared/NavMenu.razor +++ b/BlazorReorderExample/Shared/NavMenu.razor @@ -19,11 +19,6 @@ Counter - diff --git a/BlazorReorderExample/_Imports.razor b/BlazorReorderExample/_Imports.razor index 54c372c..d29d73b 100644 --- a/BlazorReorderExample/_Imports.razor +++ b/BlazorReorderExample/_Imports.razor @@ -8,3 +8,4 @@ @using Microsoft.JSInterop @using BlazorReorderExample @using BlazorReorderExample.Shared +@using BlazorReorderList diff --git a/BlazorReorderExample/wwwroot/index.html b/BlazorReorderExample/wwwroot/index.html index c77cffe..4e48664 100644 --- a/BlazorReorderExample/wwwroot/index.html +++ b/BlazorReorderExample/wwwroot/index.html @@ -20,39 +20,6 @@ 🗙 - - diff --git a/BlazorReorderList/BlazorReorderList.csproj b/BlazorReorderList/BlazorReorderList.csproj new file mode 100644 index 0000000..f7e5d11 --- /dev/null +++ b/BlazorReorderList/BlazorReorderList.csproj @@ -0,0 +1,25 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + + + + true + PreserveNewest + + + + diff --git a/BlazorReorderList/Model.cs b/BlazorReorderList/Model.cs new file mode 100644 index 0000000..8b4f6da --- /dev/null +++ b/BlazorReorderList/Model.cs @@ -0,0 +1,5 @@ +namespace BlazorReorderList; + +public record point(int x, int y); +public record clientRect(float left, float top, float right, float bottom, float x, float y, float width, float height); + diff --git a/BlazorReorderExample/Shared/Reorder.razor b/BlazorReorderList/Reorder.razor similarity index 89% rename from BlazorReorderExample/Shared/Reorder.razor rename to BlazorReorderList/Reorder.razor index 5f751a8..e899b99 100644 --- a/BlazorReorderExample/Shared/Reorder.razor +++ b/BlazorReorderList/Reorder.razor @@ -1,5 +1,6 @@ @typeparam TItem -@inject IJSRuntime JS +@using Microsoft.JSInterop +@inject ReorderJsInterop js @if (debug) { @@ -31,9 +32,6 @@ [Parameter, EditorRequired] public List Items { get; set; } = null!; [Parameter] public bool withShadow { get; set; } = true; - public record point(int x, int y); - public record clientRect(float left, float top, float right, float bottom, float x, float y, float width, float height); - private bool shouldRender = true; private DotNetObjectReference>? dotNetHelper; ElementReference container; @@ -63,7 +61,7 @@ if (firstRender) { dotNetHelper = DotNetObjectReference.Create(this); - await JS.InvokeVoidAsync("initEvents", dotNetHelper); + await js.initEvents(dotNetHelper); } } @@ -72,9 +70,9 @@ ghost = item; ghostElem = itemElem[index]; elemIndex = index; - elemWidth = await JS.InvokeAsync("getWidth", ghostElem); - elemPosition = await JS.InvokeAsync("getPosition", ghostElem); - elemClickPosition = await JS.InvokeAsync("getPoint", m); + elemWidth = await js.getWidth(ghostElem); + elemPosition = await js.getPosition(ghostElem); + elemClickPosition = await js.getPoint(m); Log($"onPress ({elemPosition.x}, {elemPosition.y}) {item}"); await onMove(elemClickPosition); } @@ -154,7 +152,7 @@ // checks if mouse x/y is on top of an item async Task isOnTop(ElementReference item, point pos) { - var box = await JS.InvokeAsync("getClientRect", item); + var box = await js.getClientRect(item); Log($"\npos x: {pos.x}, y: {pos.y}\n item: left:{box.left}, width:{box.width}\nitem: top:{box.top}, height:{box.height}", true); var isx = (pos.x > box.left && pos.x < (box.left + box.width)); var isy = (pos.y > box.top && pos.y < (box.top + box.height)); diff --git a/BlazorReorderExample/Shared/Reorder.razor.css b/BlazorReorderList/Reorder.razor.css similarity index 100% rename from BlazorReorderExample/Shared/Reorder.razor.css rename to BlazorReorderList/Reorder.razor.css diff --git a/BlazorReorderExample/Shared/Reorder.razor.scss b/BlazorReorderList/Reorder.razor.scss similarity index 100% rename from BlazorReorderExample/Shared/Reorder.razor.scss rename to BlazorReorderList/Reorder.razor.scss diff --git a/BlazorReorderList/ReorderJsInterop.cs b/BlazorReorderList/ReorderJsInterop.cs new file mode 100644 index 0000000..5745535 --- /dev/null +++ b/BlazorReorderList/ReorderJsInterop.cs @@ -0,0 +1,55 @@ +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Web; +using Microsoft.JSInterop; + +namespace BlazorReorderList; + +public class ReorderJsInterop : IAsyncDisposable +{ + private readonly Lazy> moduleTask; + + public ReorderJsInterop(IJSRuntime jsRuntime) + { + moduleTask = new(() => jsRuntime.InvokeAsync( + "import", "./_content/BlazorReorderList/ReorderJsInterop.js").AsTask()); + } + + public async ValueTask initEvents(DotNetObjectReference> dotNetInstance) + { + var module = await moduleTask.Value; + await module.InvokeVoidAsync("initEvents", dotNetInstance); + } + + public async ValueTask getWidth(ElementReference el) + { + var module = await moduleTask.Value; + return await module.InvokeAsync("getWidth", el); + } + + public async ValueTask getPosition(ElementReference el) + { + var module = await moduleTask.Value; + return await module.InvokeAsync("getPosition", el); + } + + public async ValueTask getPoint(MouseEventArgs ev) + { + var module = await moduleTask.Value; + return await module.InvokeAsync("getPoint", ev); + } + + public async ValueTask getClientRect(ElementReference el) + { + var module = await moduleTask.Value; + return await module.InvokeAsync("getClientRect", el); + } + + public async ValueTask DisposeAsync() + { + if (moduleTask.IsValueCreated) + { + var module = await moduleTask.Value; + await module.DisposeAsync(); + } + } +} diff --git a/BlazorReorderList/_Imports.razor b/BlazorReorderList/_Imports.razor new file mode 100644 index 0000000..7728512 --- /dev/null +++ b/BlazorReorderList/_Imports.razor @@ -0,0 +1 @@ +@using Microsoft.AspNetCore.Components.Web diff --git a/BlazorReorderList/wwwroot/ReorderJsInterop.js b/BlazorReorderList/wwwroot/ReorderJsInterop.js new file mode 100644 index 0000000..7a50de4 --- /dev/null +++ b/BlazorReorderList/wwwroot/ReorderJsInterop.js @@ -0,0 +1,31 @@ + +var _w = window, + _b = document.body, + _d = document.documentElement; + +// get position of mouse/touch in relation to viewport +export function getPoint(e) { + var scrollX = Math.max(0, _w.pageXOffset || _d.scrollLeft || _b.scrollLeft || 0) - (_d.clientLeft || 0), + scrollY = Math.max(0, _w.pageYOffset || _d.scrollTop || _b.scrollTop || 0) - (_d.clientTop || 0), + pointX = e ? (Math.max(0, e.pageX || e.clientX || 0) - scrollX) : 0, + pointY = e ? (Math.max(0, e.pageY || e.clientY || 0) - scrollY) : 0; + + return { x: pointX, y: pointY }; +} + +export function initEvents(dotNetInstance) { + window.addEventListener("mousemove", (e) => dotNetInstance.invokeMethodAsync("onMove", getPoint(e)), true); + window.addEventListener("touchmove", (e) => dotNetInstance.invokeMethodAsync("onMove", getPoint(e)), true); + window.addEventListener("mouseup", (e) => dotNetInstance.invokeMethodAsync("onRelease", e), true); + window.addEventListener("touchend", (e) => dotNetInstance.invokeMethodAsync("onRelease", e), true); +} + +export function getWidth(e) { + return e.offsetWidth; +} +export function getPosition(e) { + return { x: e.offsetLeft, y: e.offsetTop }; +} +export function getClientRect(e) { + return e.getBoundingClientRect(); +}