text-mask icon indicating copy to clipboard operation
text-mask copied to clipboard

Flexible Mask for IP addresses

Open mumairofficial opened this issue 8 years ago • 12 comments

First of all thank you and great work team,

I was wondering if you help me to create mask for IP address, and here what I have created

[/\d/, /\d/, /\d/, '.', /\d/, /\d/, /\d/, '.', /\d/, /\d/, /\d/, '.', /\d/, /\d/, /\d/]

it work fine for (192.168.111.083) format but I want to make it more flexible which accept following format

10.2.5.6 instead of 010.002.005.006

mumairofficial avatar Jun 09 '17 10:06 mumairofficial

Would be very Interessted in a solution for this!!!

BioPhoton avatar Jun 09 '17 20:06 BioPhoton

There is no an easy/built-in way to do this... but I'm sure it wouldn't be too difficult. You would need to create a mask function that validates the IP based on number of digits and placement of dots..

lozjackson avatar Jun 12 '17 17:06 lozjackson

Is anyone able to share more details on this?

zkewal avatar Jun 20 '17 06:06 zkewal

Just a guess since I'm only looking into using this module for something else and checking out any potential issues, but have you tried:

[/\d?/, /\d?/, /\d/, '.', /\d?/, /\d?/, /\d/, '.', /\d?/, /\d?/, /\d/, '.', /\d?/, /\d?/, /\d/]

I tested using /\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d/g in a regex tester and it seemed to capture what you're looking for.

Oops, thx @BioPhoton , the array is correct, but I forgot to escape the '.' in the regex, should be \d?\d?\d\.\d?\d?\d\.\d?\d?\d\.\d?\d?\d which finds any valid IP that's a substring, or \b\d?\d?\d\.\d?\d?\d\.\d?\d?\d\.\d?\d?\d\b if you want to bound it exactly.

Updated your link w/o bounding, w/ bounding

awreese avatar Aug 15 '17 17:08 awreese

Here's an online regex tester with this regex: https://regex101.com/r/3YQ4wC/1

BioPhoton avatar Aug 15 '17 20:08 BioPhoton

I am doing this:

const value = '1.2.3.4.5.6.7.8.9';
  const results = conformToMask(value, [/\d?/, /\d?/, /\d/, '.', /\d?/, /\d?/, /\d/, '.', /\d?/, /\d?/, /\d/, '.', /\d?/, /\d?/, /\d/]);
  console.log(results.conformedValue);

And I getting 1.2.3.4.5.6.7.8 as a result. Maybe someone knows what is wrong?

bezenson avatar Jan 11 '18 10:01 bezenson

My solution -

const ipMask = value => {
  const chars = value.split("");

  const createIpGroup = (charsArr, position) => [
    /[0-2]/,
    charsArr[position] === "2" ? /[0-5]/ : /[0-9]/,
    charsArr[position] === "2" ? /[0-5]/ : /[0-9]/
  ];

  const ipGroup1 = createIpGroup(chars, 0);
  const ipGroup2 = createIpGroup(chars, 4);
  const ipGroup3 = createIpGroup(chars, 8);
  const ipGroup4 = createIpGroup(chars, 12);

  return ipGroup1
    .concat(".")
    .concat(ipGroup2)
    .concat(".")
    .concat(ipGroup3)
    .concat(".")
    .concat(ipGroup4);
};

<MaskedInput mask={ipMask} placeholder="000.000.000.000" />

AAtamaniuk avatar Dec 16 '18 12:12 AAtamaniuk

@AAtamaniuk - Have you done anything with ip6?

amcdnl avatar Feb 05 '19 15:02 amcdnl

image

@AAtamaniuk that's still not quite flexible, but to be fair, I don't really see a ux friendly way masking ipv4 or ipv6

fxck avatar Mar 25 '19 08:03 fxck

Faced with the same problem, at least found a way through the pipe function:

const props = {
  mask: value => Array(value.length).fill(/[\d.]/),
  pipe: value => {
    if (value === '.' || value.endsWith('..')) return false;

    const parts = value.split('.');

    if (
      parts.length > 4 ||
      parts.some(part => part === '00' || part < 0 || part > 255)
    ) {
      return false;
    }

    return value;
  },
};

https://codesandbox.io/s/1v32jk0x7q

biocoderh avatar Apr 21 '19 22:04 biocoderh

few improvements to the previous post:

const props = {
  guide: true,
  mask: value => {
    let result = [];
    const chunks = value.split(".");

    for (let i = 0; i < 4; ++i) {
      const chunk = (chunks[i] || "").replace(/_/gi, "");

      if (chunk === "") {
        result.push(/\d/, /\d/, /\d/, ".");
        continue;
      } else if (+chunk === 0) {
        result.push(/\d/, ".");
        continue;
      } else if (
        chunks.length < 4 ||
        (chunk.length < 3 && chunks[i].indexOf("_") !== -1)
      ) {
        if (
          (chunk.length < 2 && +`${chunk}00` > 255) ||
          (chunk.length < 3 && +`${chunk}0` > 255)
        ) {
          result.push(/\d/, /\d/, ".");
          continue;
        } else {
          result.push(/\d/, /\d/, /\d/, ".");
          continue;
        }
      } else {
        result.push(...new Array(chunk.length).fill(/\d/), ".");
        continue;
      }
    }

    result = result.slice(0, -1);
    return result;
  },
  pipe: value => {
    if (value === "." || value.endsWith("..")) return false;

    const parts = value.split(".");

    if (
      parts.length > 4 ||
      parts.some(part => part === "00" || part < 0 || part > 255)
    ) {
      return false;
    }

    return value;
  }
};

now it works with placeholder Capture https://codesandbox.io/embed/react-text-mask-ip-kg27g

fqf avatar Jul 13 '19 01:07 fqf

more some improvements. :)

If the result of the mask is not important to you.

const props = {
  guide: false,
  mask: (value, data) => {
    const mask = Array(value.length).fill(/[\d.]/)
    const chunks = value.split('.');

    for (let i = 0; i < 4; ++i) {
      const chunk = (chunks[i] || "");

      if (255 % +chunk === 255) {
        mask[value.length - 1] = '.';
        mask[value.length] = /[\d.]/;
      }
    }

    return mask;
  },
  pipe: value => {
    if (value === "." || value.endsWith("..")) return false;

    const parts = value.split(".");

    if (
      parts.length > 4 ||
      parts.some(part => part === "00" || part < 0 || part > 255)
    ) {
      return false;
    }

    return value;
  }
};

eilskn avatar Oct 28 '20 14:10 eilskn