mirror of
https://github.com/dotnetcore/BootstrapBlazor.git
synced 2025-12-20 02:16:40 +08:00
!1957 feat(#I4E4ZI): add IpAddress component
* chore: bump version to 5.15.1 * feat: 增加超过三位保护 * chore: update css/scripts bundle file * doc: 更新组件示例 * feat: 增加 Ip 地址组件功能 * chore: 增加 Ip 地址脚本 * refactor: 增加 IpAddress 组件 * Merge remote-tracking branch 'origin/pack' into dev-ip * Merge branch 'dev' into dev-ip * chore: set preview to true * chore: update checkout version * chore: install preview sdk * chore: update sdk version * chore: update pack script * feat: 增加 Ip 测试网页
This commit is contained in:
6
.github/workflows/pack.yml
vendored
6
.github/workflows/pack.yml
vendored
@@ -23,6 +23,12 @@ jobs:
|
||||
with:
|
||||
dotnet-version: 5.0.x
|
||||
|
||||
- name: Setup .NET Core 6
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
include-prerelease: true
|
||||
|
||||
- name: Publish to Nuget
|
||||
env:
|
||||
NUGET_API_KEY: ${{secrets.NUGET_API_KEY}}
|
||||
|
||||
5
src/BootstrapBlazor.Shared/Pages/Samples/Ips.razor
Normal file
5
src/BootstrapBlazor.Shared/Pages/Samples/Ips.razor
Normal file
@@ -0,0 +1,5 @@
|
||||
@page "/ips"
|
||||
|
||||
<IpAddress @bind-Value="@Value" />
|
||||
|
||||
<div>@Value</div>
|
||||
22
src/BootstrapBlazor.Shared/Pages/Samples/Ips.razor.cs
Normal file
22
src/BootstrapBlazor.Shared/Pages/Samples/Ips.razor.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Shared.Pages
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public partial class Ips
|
||||
{
|
||||
private string? Value { get; set; }
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -453,6 +453,12 @@ namespace BootstrapBlazor.Shared.Shared
|
||||
Url = "locator"
|
||||
},
|
||||
new()
|
||||
{
|
||||
IsNew = true,
|
||||
Text = Localizer["Ip"],
|
||||
Url = "ips"
|
||||
},
|
||||
new()
|
||||
{
|
||||
IsNew = true,
|
||||
Text = Localizer["Print"],
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>5.15.0</Version>
|
||||
<Version>5.15.1</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
|
||||
|
||||
10
src/BootstrapBlazor/Components/IpAddress/IpAddress.css
Normal file
10
src/BootstrapBlazor/Components/IpAddress/IpAddress.css
Normal file
@@ -0,0 +1,10 @@
|
||||
.ipaddress {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
min-width: 138px;
|
||||
}
|
||||
|
||||
.ipaddress .ipv4-cell {
|
||||
border: none;
|
||||
max-width: 26px;
|
||||
}
|
||||
185
src/BootstrapBlazor/Components/IpAddress/IpAddress.js
Normal file
185
src/BootstrapBlazor/Components/IpAddress/IpAddress.js
Normal file
@@ -0,0 +1,185 @@
|
||||
(function ($) {
|
||||
// private functions
|
||||
var backup = function (index) {
|
||||
var input = this;
|
||||
if (index !== undefined) {
|
||||
input.prevValues[index] = $($(input).find(".ipv4-cell")[index]).val();
|
||||
} else {
|
||||
$(input).find(".ipv4-cell").each(function (i, cell) {
|
||||
input.prevValues[i] = $(cell).val();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var revert = function (index) {
|
||||
var input = this;
|
||||
if (index !== undefined) {
|
||||
$($(input).find(".ipv4-cell")[index]).val(input.prevValues[index]);
|
||||
} else {
|
||||
$(input).find(".ipv4-cell").each(function (i, cell) {
|
||||
$(cell).val(input.prevValues);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var selectCell = function (index) {
|
||||
var input = this;
|
||||
if (index === undefined && index < 0 && index > 3) return;
|
||||
$($(input).find(".ipv4-cell")[index]).focus();
|
||||
};
|
||||
|
||||
var isValidIPStr = function (ipString) {
|
||||
if (typeof ipString !== "string") return false;
|
||||
|
||||
var ipStrArray = ipString.split(".");
|
||||
if (ipStrArray.length !== 4) return false;
|
||||
|
||||
return ipStrArray.reduce(function (prev, cur) {
|
||||
if (prev === false || cur.length === 0) return false;
|
||||
return (Number(cur) >= 0 && Number(cur) <= 255) ? true : false;
|
||||
}, true);
|
||||
};
|
||||
|
||||
var getCurIPStr = function () {
|
||||
var str = "";
|
||||
this.find(".ipv4-cell").each(function (index, element) {
|
||||
str += (index == 0) ? $(element).val() : "." + $(element).val();
|
||||
});
|
||||
return str;
|
||||
};
|
||||
|
||||
// function for text input cell
|
||||
var getCursorPosition = function () {
|
||||
var cell = this;
|
||||
if ('selectionStart' in cell) {
|
||||
// Standard-compliant browsers
|
||||
return cell.selectionStart;
|
||||
} else if (document.selection) {
|
||||
// IE
|
||||
cell.focus();
|
||||
var sel = document.selection.createRange();
|
||||
var selLen = document.selection.createRange().text.length;
|
||||
sel.moveStart('character', -cell.value.length);
|
||||
return sel.text.length - selLen;
|
||||
}
|
||||
throw new Error("cell is not an input");
|
||||
};
|
||||
|
||||
$.extend({
|
||||
bb_ipv4_input: function (ele) {
|
||||
var $ele = $(ele);
|
||||
ele.prevValues = [];
|
||||
|
||||
$ele.find(".ipv4-cell").focus(function () {
|
||||
$(this).select(); // input select all when tab in
|
||||
$ele.toggleClass("selected", true);
|
||||
});
|
||||
|
||||
$ele.find(".ipv4-cell").focusout(function () {
|
||||
$ele.toggleClass("selected", false);
|
||||
});
|
||||
|
||||
$ele.find(".ipv4-cell").each(function (index, cell) {
|
||||
$(cell).keydown(function (e) {
|
||||
if (e.keyCode >= 48 && e.keyCode <= 57 || e.keyCode >= 96 && e.keyCode <= 105) { // numbers, backup last status
|
||||
backup.call(ele, index);
|
||||
}
|
||||
else if (e.keyCode == 37 || e.keyCode == 39) { // left key ,right key
|
||||
if (e.keyCode == 37 && getCursorPosition.call(cell) === 0) {
|
||||
selectCell.call(ele, index - 1);
|
||||
e.preventDefault();
|
||||
}
|
||||
else if (e.keyCode == 39 && getCursorPosition.call(cell) === $(cell).val().length) {
|
||||
selectCell.call(ele, index + 1);
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
else if (e.keyCode == 9) { // allow tab
|
||||
}
|
||||
else if (e.keyCode == 8 || e.keyCode == 46) { // allow backspace, delete
|
||||
}
|
||||
else {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
$(cell).keyup(function (e) {
|
||||
if (e.keyCode >= 48 && e.keyCode <= 57 || e.keyCode >= 96 && e.keyCode <= 105) { // numbers
|
||||
var val = $(this).val();
|
||||
var num = Number(val);
|
||||
|
||||
if (num > 255)
|
||||
revert.call(ele, index);
|
||||
else if (val.length > 1 && val[0] === "0")
|
||||
revert.call(ele, index);
|
||||
else if (val.length === 3)
|
||||
selectCell.call(ele, index + 1)
|
||||
}
|
||||
if (e.key === 'Backspace') {
|
||||
if ($(this).val() === '') {
|
||||
$(this).val('0');
|
||||
var i = index - 1;
|
||||
if (i > -1) {
|
||||
selectCell.call(ele, i)
|
||||
}
|
||||
else {
|
||||
selectCell.call(ele, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (e.key === '.') {
|
||||
selectCell.call(ele, index + 1)
|
||||
}
|
||||
if (e.key === 'ArrowRight') {
|
||||
selectCell.call(ele, index + 1)
|
||||
}
|
||||
if (e.key === 'ArrowLeft') {
|
||||
selectCell.call(ele, index - 1)
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var process = function (act, v) {
|
||||
if (act == "rwd") {
|
||||
(v === undefined) ? this.toggleClass("rwd") : this.toggleClass("rwd", v);
|
||||
}
|
||||
|
||||
if (act == "value") {
|
||||
if (v === undefined) // get func
|
||||
return getCurIPStr.call(this);
|
||||
|
||||
// set func
|
||||
if (!isValidIPStr(v)) throw new Error("invalid ip address");
|
||||
|
||||
var strArray = v.split(".");
|
||||
this.find(".ipv4-cell").each(function (index, cell) {
|
||||
$(cell).val(strArray[index]);
|
||||
});
|
||||
}
|
||||
|
||||
if (act == "valid") {
|
||||
return isValidIPStr(getCurIPStr.call(this));
|
||||
}
|
||||
|
||||
if (act == "clear") {
|
||||
this.find(".ipv4-cell").each(function (index, cell) {
|
||||
$(cell).val("");
|
||||
});
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
var rtn = this;
|
||||
if ($.type(action) === "object") { // set multiple values
|
||||
var props = action;
|
||||
for (var prop in props)
|
||||
process.call(this, prop, action[prop]);
|
||||
} else { // set one value
|
||||
rtn = process.call(this, action, value);
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
});
|
||||
|
||||
}(jQuery));
|
||||
1
src/BootstrapBlazor/Components/IpAddress/IpAddress.min.js
vendored
Normal file
1
src/BootstrapBlazor/Components/IpAddress/IpAddress.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
(function(e){var t=function(t){var n=this;t!==undefined?n.prevValues[t]=e(e(n).find(".ipv4-cell")[t]).val():e(n).find(".ipv4-cell").each(function(t,r){n.prevValues[t]=e(r).val()})},n=function(t){var n=this;t!==undefined?e(e(n).find(".ipv4-cell")[t]).val(n.prevValues[t]):e(n).find(".ipv4-cell").each(function(t,r){e(r).val(n.prevValues)})},r=function(t){var n=this;if(t===undefined&&t<0&&t>3)return;e(e(n).find(".ipv4-cell")[t]).focus()},i=function(e){if(typeof e!="string")return!1;var t=e.split(".");return t.length!==4?!1:t.reduce(function(e,t){return e===!1||t.length===0?!1:Number(t)>=0&&Number(t)<=255?!0:!1},!0)},s=function(){var t="";return this.find(".ipv4-cell").each(function(n,r){t+=n==0?e(r).val():"."+e(r).val()}),t},o=function(){var e=this;if("selectionStart"in e)return e.selectionStart;if(document.selection){e.focus();var t=document.selection.createRange(),n=document.selection.createRange().text.length;return t.moveStart("character",-e.value.length),t.text.length-n}throw new Error("cell is not an input")};e.fn.ipv4_input=function(u,a){this.each(function(){if(e(this).hasClass("ipv4-input"))return;var i=this;i.prevValues=[],e(i).toggleClass("ipv4-input",!0),e(i).html('<input type="text" class="ipv4-cell" /><label class="ipv4-dot">.</label><input type="text" class="ipv4-cell" /><label class="ipv4-dot">.</label><input type="text" class="ipv4-cell" /><label class="ipv4-dot">.</label><input type="text" class="ipv4-cell" />'),e(this).find(".ipv4-cell").focus(function(){e(this).select(),e(i).toggleClass("selected",!0)}),e(this).find(".ipv4-cell").focusout(function(){e(i).toggleClass("selected",!1)}),e(this).find(".ipv4-cell").each(function(s,u){e(u).keydown(function(n){n.keyCode>=48&&n.keyCode<=57||n.keyCode>=96&&n.keyCode<=105?t.call(i,s):n.keyCode==37||n.keyCode==39?n.keyCode==37&&o.call(u)===0?(r.call(i,s-1),n.preventDefault()):n.keyCode==39&&o.call(u)===e(u).val().length&&(r.call(i,s+1),n.preventDefault()):n.keyCode!=9&&n.keyCode!=8&&n.keyCode!=46&&n.preventDefault()}),e(u).keyup(function(t){if(t.keyCode>=48&&t.keyCode<=57||t.keyCode>=96&&t.keyCode<=105){var o=e(this).val(),u=Number(o);u>255?n.call(i,s):o.length>1&&o[0]==="0"?n.call(i,s):o.length===3&&r.call(i,s+1)}})})});var f=function(t,n){t=="rwd"&&(n===undefined?this.toggleClass("rwd"):this.toggleClass("rwd",n));if(t=="value"){if(n===undefined)return s.call(this);if(!i(n))throw new Error("invalid ip address");var r=n.split(".");this.find(".ipv4-cell").each(function(t,n){e(n).val(r[t])})}return t=="valid"?i(s.call(this)):(t=="clear"&&this.find(".ipv4-cell").each(function(t,n){e(n).val("")}),this)},l=this;if(e.type(u)==="object"){var c=u;for(var h in c)f.call(this,h,u[h])}else l=f.call(this,u,a);return l}})(jQuery);
|
||||
16
src/BootstrapBlazor/Components/IpAddress/IpAddress.razor
Normal file
16
src/BootstrapBlazor/Components/IpAddress/IpAddress.razor
Normal file
@@ -0,0 +1,16 @@
|
||||
@namespace BootstrapBlazor.Components
|
||||
@inherits ValidateBase<string>
|
||||
|
||||
@if (IsShowLabel)
|
||||
{
|
||||
<label class="form-label" required="@Required" for="@Id">@DisplayText</label>
|
||||
}
|
||||
<div @attributes="@AdditionalAttributes" class="@ClassName" id="@Id" @ref="IPAddressElement">
|
||||
<input type="number" class="input-number-fix ipv4-cell" min="0" max="255" disabled="@Disabled" value="@Value1" @onchange="ValueChanged1" />
|
||||
<span>.</span>
|
||||
<input type="number" class="input-number-fix ipv4-cell" min="0" max="255" disabled="@Disabled" value="@Value2" @onchange="ValueChanged2" />
|
||||
<span>.</span>
|
||||
<input type="number" class="input-number-fix ipv4-cell" min="0" max="255" disabled="@Disabled" value="@Value3" @onchange="ValueChanged3" />
|
||||
<span>.</span>
|
||||
<input type="number" class="input-number-fix ipv4-cell" min="0" max="255" disabled="@Disabled" value="@Value4" @onchange="ValueChanged4" />
|
||||
</div>
|
||||
107
src/BootstrapBlazor/Components/IpAddress/IpAddress.razor.cs
Normal file
107
src/BootstrapBlazor/Components/IpAddress/IpAddress.razor.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// BootstrapInputTextBase 组件
|
||||
/// </summary>
|
||||
public partial class IpAddress
|
||||
{
|
||||
private string? Value1 { get; set; } = "0";
|
||||
|
||||
private string? Value2 { get; set; } = "0";
|
||||
|
||||
private string? Value3 { get; set; } = "0";
|
||||
|
||||
private string? Value4 { get; set; } = "0";
|
||||
|
||||
private ElementReference IPAddressElement { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得 class 样式集合
|
||||
/// </summary>
|
||||
protected string? ClassName => CssBuilder.Default("ipaddress form-control")
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="firstRender"></param>
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
|
||||
if (firstRender)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync(IPAddressElement, "bb_ipv4_input");
|
||||
}
|
||||
}
|
||||
|
||||
private void ValueChanged1(ChangeEventArgs args)
|
||||
{
|
||||
Value1 = args.Value?.ToString();
|
||||
if (string.IsNullOrEmpty(Value1))
|
||||
{
|
||||
Value1 = "0";
|
||||
}
|
||||
if (Value1.Length > 3)
|
||||
{
|
||||
Value1 = Value1[0..3];
|
||||
}
|
||||
|
||||
UpdateValue();
|
||||
}
|
||||
|
||||
private void ValueChanged2(ChangeEventArgs args)
|
||||
{
|
||||
Value2 = args.Value?.ToString();
|
||||
if (string.IsNullOrEmpty(Value2))
|
||||
{
|
||||
Value2 = "0";
|
||||
}
|
||||
if (Value2.Length > 3)
|
||||
{
|
||||
Value2 = Value2[0..3];
|
||||
}
|
||||
UpdateValue();
|
||||
}
|
||||
|
||||
private void ValueChanged3(ChangeEventArgs args)
|
||||
{
|
||||
Value3 = args.Value?.ToString();
|
||||
if (string.IsNullOrEmpty(Value3))
|
||||
{
|
||||
Value3 = "0";
|
||||
}
|
||||
if (Value3.Length > 3)
|
||||
{
|
||||
Value3 = Value3[0..3];
|
||||
}
|
||||
UpdateValue();
|
||||
}
|
||||
|
||||
private void ValueChanged4(ChangeEventArgs args)
|
||||
{
|
||||
Value4 = args.Value?.ToString();
|
||||
if (string.IsNullOrEmpty(Value4))
|
||||
{
|
||||
Value4 = "0";
|
||||
}
|
||||
if (Value4.Length > 3)
|
||||
{
|
||||
Value4 = Value4[0..3];
|
||||
}
|
||||
UpdateValue();
|
||||
}
|
||||
|
||||
private void UpdateValue()
|
||||
{
|
||||
CurrentValueAsString = $"{Value1}.{Value2}.{Value3}.{Value4}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
<PropertyGroup>
|
||||
<IsPackable>true</IsPackable>
|
||||
<PackageIcon>logo.png</PackageIcon>
|
||||
<!--<PackageReadmeFile>readme.md</PackageReadmeFile>-->
|
||||
<PackageReadmeFile>readme.md</PackageReadmeFile>
|
||||
<PackageReleaseNotes>https://gitee.com/LongbowEnterprise/BootstrapBlazor/wikis</PackageReleaseNotes>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="logo.png" Pack="true" PackagePath="" />
|
||||
<!--<None Include="readme.md" Pack="true" PackagePath="" />-->
|
||||
<None Include="readme.md" Pack="true" PackagePath="" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user