Hitmare Chelien
Hitmare Chelien

Reputation: 23

Change input field on keyup to match MAC address format

I don't have much experience with JavaScript or jQuery.

I tried to use Tampermonkey to auto correct the input field for a MAC address.

The site wants a MAC address formatted as 00:00:00:00:00:00.

So I wrote this script for Tampermonkey so it automatically adds the colons while I'm typing:

// ==UserScript==
// @name         Name
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Adds colons to the mac adress of the Mac Field
// @author       You
// @match        Somesite
// @grant        none
// @require http://code.jquery.com/jquery-latest.js
// ==/UserScript==
document.getElementById("MAC").addEventListener('keyup', function() { 
  var mac = document.getElementById('MAC').value;
  var macs = mac.split('');
  var colons = ["2", "5", "8", "11", "14"];
  for (var col in colons) {
    if (macs[col] == "-") {
      macs[col] = ":";
    } else if (macs[col] != "") {

    } else if (macs[col] != ":") {
      var colo = col + 1;
      macs[colo] = macs[col];
      macs[col] = ":";
    }
  }
  mac = macs.toString();
});
<input id=MAC />

But it don't work. The ID of the inputfield is MAC.

Where and how much did I do wrong?

SOLUTION

Thanks to @i-wrestled-a-bear-once and @freginold for the , my oppion, best solutions

I'm using now a slightly changed version from @freginold

var back = true;
function isHex(char) {
  // check if char is a hex char
  if (!isNaN(parseInt(char))) {
    return true;
  } else {
    switch (char.toLowerCase()) {
      case "a":
      case "b":
      case "c":
      case "d":
      case "e":
      case "f":
        return true;
    }
    return false;
  }
}
document.getElementById("MAC").addEventListener('keydown', function() {
    var key = event.keyCode || event.charCode;

   if( key == 8 || key == 46 ) {
       back = false;
   }
});

document.getElementById("MAC").addEventListener('keyup', function() {
    var key = event.keyCode || event.charCode;


  var mac = document.getElementById('MAC').value;
  var newMac = mac.replace("-", ""); // remove any dashes
  if ((isHex(mac[mac.length - 1]) && (isHex(mac[mac.length - 2])) && (mac.length <= 16) && (back))) {
    // if last two chars are numbers, insert a colon
    newMac = newMac + ":";

  }
back = true;
  document.getElementById('MAC').value = newMac; // put new value into input field

});

Upvotes: 1

Views: 4708

Answers (6)

Christopher Cushman
Christopher Cushman

Reputation: 11

built on @KungWaz's answer by using jQuery and supporting backspace/delete

$("#MAC").keydown(function(e) {
  // firefox has different values for keys
  if ([186, 189, 59, 173, 32].includes(e.which))
    return false;
});

$("#MAC").keyup(function(e) {
  let start = $(this).prop("selectionStart")
  let end = $(this).prop("selectionEnd")
  let addedColon = false
  // ignore backspace and delete
  if ([8, 46].includes(e.which)) {
    return true
  }
  var macs = $(this).val().split('');
  var colons = [2, 5, 8, 11, 14];
  for (var col in colons) {
    if (colons[col] <= macs.length) {
      if (macs[colons[col]] !== ":") {
        if (macs[colons[col] - 1] == ":" || macs[colons[col] + 1] == ":") {
          // dont add colon if there is one nearby
          // that way you can edit the middle of the mac address
          continue
        }
        macs.splice(colons[col], 0, ":");
        addedColon = true
        $(this).focus()
      }
    }
  }
  $(this).val(macs.join('').substring(0, 17))
  if (start == end && addedColon) {
    //if not selecting text
    $(this)[0].setSelectionRange(start + 1, end + 1)
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id=MAC maxlength="17"/>

Upvotes: 0

freginold
freginold

Reputation: 3956

You could simplify it and check if the last two characters in the string are hex characters (0-9, A-F) and if so, insert a :. You can also use .replace() to remove any occurrence of - if you (or someone else) types a dash instead of a colon.

That way you can cover inserting colons if you don't type them at all, as well as converting any typed dashes to colons.

Here's a working example:

// ==UserScript==
// @name         Name
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Adds colons to the mac adress of the Mac Field
// @author       You
// @match        Somesite
// @grant        none
// @require http://code.jquery.com/jquery-latest.js
// ==/UserScript==
function isHex(char) {
  if (!isNaN(parseInt(char))) {
    return true;
  } else {
    switch (char.toLowerCase()) {
      case "a":
      case "b":
      case "c":
      case "d":
      case "e":
      case "f":
        return true;
        break;
    }
    return false;
  }
}

document.getElementById("MAC").addEventListener('keyup', function() {
  var mac = document.getElementById('MAC').value;
  if (mac.length < 2) {
    return;
  }
  var newMac = mac.replace("-", "");
  if ((isHex(mac[mac.length - 1]) && (isHex(mac[mac.length - 2])))) {
    newMac = newMac + ":";
  }
  document.getElementById('MAC').value = newMac;
});

document.getElementById('MAC').focus(); // autofocus for testing
<input id=MAC />

Upvotes: 1

I wrestled a bear once.
I wrestled a bear once.

Reputation: 23409

  • replace(/[^\d|A-Z]/g, '') removes any non alphanumeric chars
  • match(/.{1,2}/g) breaks the string into chunks of 2
  • join(":") joins the chunks and puts a colon in between them

// ==UserScript==
// @name         Name
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Adds colons to the mac adress of the Mac Field
// @author       You
// @match        Somesite
// @grant        none
// @require http://code.jquery.com/jquery-latest.js
// ==/UserScript==
document.getElementById("MAC").addEventListener('keyup', function() { 
  // remove non digits, break it into chunks of 2 and join with a colon
  this.value = 
    (this.value.toUpperCase()
    .replace(/[^\d|A-Z]/g, '')
    .match(/.{1,2}/g) || [])
    .join(":")
});
<input id=MAC />

Upvotes: 7

Vignesh Raja
Vignesh Raja

Reputation: 8781

Just tried a simple logic.

var macelem = document.getElementById("MAC");
macelem.addEventListener('keyup', function() {
    var mac = macelem.value,index=(mac.match(/\:/g)||[]).length;
    if(index < 5 && index*3+2 == mac.length)
    {
        mac += ":";index++;
    }
    macelem.value = mac.substr(0,17);
});
<input id="MAC">

Upvotes: 0

KungWaz
KungWaz

Reputation: 1956

This should do the trick for you, you replace or add the ":" where it is needed. Then you cap the length of the string before you add it back to the input, to avoid getting to long MAC addresses.

Btw, you had some problems with your colons[col] slection to get your code to work.

document.getElementById("MAC").addEventListener('keyup', function() { 
  var mac = document.getElementById('MAC').value;
  var macs = mac.split('');
  var colons = [2, 5, 8, 11, 14];
  for (var col in colons) {
  	if (colons[col] <= macs.length) {
      if (macs[colons[col]] !== ":") {
        macs.splice(colons[col], 0, ":");
      }
    }
  }
  document.getElementById('MAC').value = macs.join('').substring(0,17);
});
<input id=MAC />

Upvotes: 0

You can use the function chunk: (not my code, I just included it and modified your code to work with it.)

function chunk(str, n) {
    var ret = [];
    var i;
    var len;

    for(i = 0, len = str.length; i < len; i += n) {
       ret.push(str.substr(i, n))
    }

    return ret
};

Then your code should look like:

document.getElementById("MAC").addEventListener('keyup', function() { 
  var mac = document.getElementById('MAC').value;
  var macs = mac.split(':').join('');
  macs = chunk(macs, 2).join(':');
  document.getElementById('MAC').value = macs.toString();
});

demo

// ==UserScript==
// @name         Name
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Adds colons to the mac adress of the Mac Field
// @author       You
// @match        Somesite
// @grant        none
// @require http://code.jquery.com/jquery-latest.js
// ==/UserScript==
document.getElementById("MAC").addEventListener('keyup', function() { 
  var mac = document.getElementById('MAC').value;
  var macs = mac.split(':').join('');
  macs = chunk(macs, 2).join(':');
  document.getElementById('MAC').value = macs.toString();
});

function chunk(str, n) {
    var ret = [];
    var i;
    var len;

    for(i = 0, len = str.length; i < len; i += n) {
       ret.push(str.substr(i, n))
    }

    return ret
};
<input id=MAC maxlength="17"/>

Upvotes: 0

Related Questions