!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:
Argo
2021-10-16 08:54:22 +00:00
parent 3240c8845b
commit abaa4eb0da
14 changed files with 364 additions and 6 deletions

View File

@@ -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}}

View File

@@ -0,0 +1,5 @@
@page "/ips"
<IpAddress @bind-Value="@Value" />
<div>@Value</div>

View 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; }
}
}

View File

@@ -453,6 +453,12 @@ namespace BootstrapBlazor.Shared.Shared
Url = "locator"
},
new()
{
IsNew = true,
Text = Localizer["Ip"],
Url = "ips"
},
new()
{
IsNew = true,
Text = Localizer["Print"],

View File

@@ -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'">

View File

@@ -0,0 +1,10 @@
.ipaddress {
display: flex;
flex-wrap: nowrap;
min-width: 138px;
}
.ipaddress .ipv4-cell {
border: none;
max-width: 26px;
}

View 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));

View 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);

View 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>

View 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}";
}
}
}

View File

@@ -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