1

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

});
  • 2
    Have you tried debugging it? – rmlan Jan 24 '18 at 13:47
  • 2
    The immediate problem is that you don't do anything with the results of the function (presumably you want to set the field value to `mac`). There are other logic problems with the text replacement, but that's the first step. – Daniel Beck Jan 24 '18 at 13:49
  • 2
    Possible duplicate of [How can I insert a character after every n characters in javascript?](https://stackoverflow.com/questions/1772941/how-can-i-insert-a-character-after-every-n-characters-in-javascript) – Carsten Løvbo Andersen Jan 24 '18 at 13:59
  • @rmlan how can i debug it in Tampermonkey? @daniel-beck ohh yeah with the `mac = macs.toString();`part i totally had a logic mistake xD . changed it to `document.getElementById('MAC').value = macs.toString();`and now it enters in the field. now i can searc hthe error in the **correction logic** because i get a lot of commas in the field – Hitmare Chelien Jan 24 '18 at 14:01

6 Answers6

7
  • 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 />
I wrestled a bear once.
  • 22,983
  • 19
  • 69
  • 116
  • it deletes the ABCDF of my mac address as well :/ . but with numbers only it works – Hitmare Chelien Jan 24 '18 at 14:32
  • When type a letter as the first char, I get this error: `"Unable to get property 'join' of undefined or null reference`. When I type a number as the first char then a letter, it erases the letter. – freginold Jan 24 '18 at 14:40
  • @freginold - SO is not a free code writing service. My intent was never to write his code for him, it was to show him how to do it. My answer before was sufficient because it gave him all the tools he needed. But if you insist, I'll do some hand-holding. I've updated the answer. – I wrestled a bear once. Jan 24 '18 at 14:46
  • @Iwrestledabearonce. Not insisting anything; just pointing out where it didn't work. – freginold Jan 24 '18 at 14:48
  • i hope i didn't do anything wrong o.o. I'm very grateful about your codes and i have to admit that i'm learning as well from finished codes as well as from hints. – Hitmare Chelien Jan 24 '18 at 15:01
  • @HitmareChelien - You didn't do anything wrong (I actually upvoted your question), just a little frustrated that I lost an upvote for improving my answer when the improvement shouldn't have been necessary in the first place. Did this answer do what you wanted? If so feel free to mark it as accepted by clicking the checkmark :) – I wrestled a bear once. Jan 24 '18 at 15:08
1

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 />
freginold
  • 3,946
  • 3
  • 13
  • 28
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"/>
Carsten Løvbo Andersen
  • 26,637
  • 10
  • 47
  • 77
  • 1
    the code don't work `mac.split(':').join('');` would probably do nothing because a MAC Address like `A0B1C2D3E4F5` is entered . i changed it to `var macs = mac.split('').join('');` but it still didn't show any changes in the input field. but thanks anyway for the afford – Hitmare Chelien Jan 24 '18 at 14:19
  • if i enter `A0B1C2D3E4F5` then it works just fine on mine – Carsten Løvbo Andersen Jan 24 '18 at 14:40
0

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">
Vignesh Raja
  • 7,927
  • 1
  • 33
  • 42
0

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 />
KungWaz
  • 1,918
  • 3
  • 36
  • 61
0

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"/>