All posts by Chris West

JavaScript – Adding Cross-browser Event Listeners

Something that I need to use every once in a while is addEventListener, but unfortunately I can’t depend on its existence in all browsers. For this reason I decided to write the following cross-browser solution for providing a function that adds an event handler:

/**
 * Cross-browser function to add an event listener.
 * @param {!HTMLElement} elem  The DOM element to attach event to.
 * @param {string} eventName  The name of the event.
 * @param {!Function} fnHandler  The function to server as one of the specified
 *     event handlers.
 * @return {Function}  Returns the function that was added as an event handler.
 */
var addEvent = function(elem, eventName, fnHandler) {
  var fnToBind = function(e) {
    return fnHandler.call(elem, e || window.event);
  };
  
  // Add the event the W3C way.
  if (elem.addEventListener) {
    elem.addEventListener(eventName, fnToBind, false);
    return fnToBind;
  }
  
  eventName = 'on' + eventName;
  
  // Add the event the Microsoft way.
  if (elem.attachEvent) {
    return elem.attachEvent(eventName, fnToBind) ? fnToBind : null;
  }
  
  // Assign the handler directly to the object's event handler property.
  if(typeof elem[eventName] == 'function') {
    // Add the event by creating a function which will run both the current
    // handler and this new one.
    var f1 = elem[eventName], f2 = fnToBind;
    fnToBind = function() {
      var ret1, ret2;

      try { ret1 = f1.apply(this, arguments); }
      catch (e1) { setTimeout(function() { throw e1; }, 0); }

      try { ret2 = f2.apply(this, arguments); }
      catch (e2) { setTimeout(function() { throw e2; }, 0); }

      // If the previous handler returned a non-undefined value, return it,
      // otherwise return the value returned from the new handler.
      return ret1 === undefined ? ret2 : ret1;
    };
  }
  elem[eventName] = fnToBind;
  return fnToBind;
};

One thing to note is that this function will wrap your function in order to allow for the event object to always be passed as the first argument regardless of the browser. Enjoy! 8)

JavaScript – XOR In Any Base

After writing the Vernam Cipher post, I started thinking about alternatives to using bit-wise XOR in order to translate numbers. I started thinking about XOR for base 3. Therefore I concentrated on what makes XOR so great.

What makes XOR stand out from other operators is the fact that assuming the use of two numbers to generate a third number, you can always use the same operator with the third number and one of the first two numbers to generate the missing number. In other words, there is a one-to-one relationship between every combination and a given number.

Requirement

Let’s say that A and B are the numbers that will XOR’ed and C will be the result. In that case, the following six statements will always be true:

  • A ⊕ B = C
  • A ⊕ C = B
  • B ⊕ A = C
  • B ⊕ C = A
  • C ⊕ A = B
  • C ⊕ B = A

In binary this is true:

  • 0 ⊕ 0 = 0
  • 0 ⊕ 1 = 1
  • 1 ⊕ 0 = 1
  • 1 ⊕ 1 = 0

Results In Other Bases

After some trial and error I found a way to mimic this relationship with ternary:

A B A ⊕ B = C
0 0 0
0 1 2
0 2 1
1 0 2
1 1 1
1 2 0
2 0 1
2 1 0
2 2 2

After that here is an XOR table which works for base 4:

A B A ⊕ B = C
0 0 0
0 1 3
0 2 2
0 3 1
1 0 3
1 1 2
1 2 1
1 3 0
2 0 2
2 1 1
2 2 0
2 3 3
3 0 1
3 1 0
3 2 3
3 3 2

The Code

Do you notice the pattern? Do you notice how we could expand it to have multiple XOR translations for each base? After some testing to make sure everything worked out, I came up with the following function in JavaScript which can find the xor of any two numbers in any integer base greater than 1:

/**
 * @license Variable Base XOR - By Chris West - MIT License
 */
function xor(num1, num2, base, offset) {
  base = base > 2 ? base : 2;
  offset = offset || 0;
  return (base - (offset + num1 + num2) % base) % base;
}

The base for this function defaults to base 2. The offset defaults to 0 and can be used to generate an alternative value. The offset should only have a range of 0 to base - 1.

Final Notes

There may be quite a few ways of apply this to the real world but the first one that comes to mind deals with encryption. Instead of using bit-wise XOR now you have the option of using an XOR of any other base. Have fun with this and let me know what you think. 8)

JavaScript – Simple Vernam Cipher

If you have ever taken an encryption class, I am sure that you have heard of the Vernam Cipher. For fun today I decided to write a quick one in JavaScript which takes your message and the random key:

function vernam(msg, key) {
  var l = key.length;
  var fromCharCode = String.fromCharCode;
  return msg.replace(/[\s\S]/g, function(c, i) {
    return fromCharCode(key.charCodeAt(i % l) ^ c.charCodeAt(0));
  });
}

To you use this function you must supply both a message and a key. The returned string is the ciphertext that is to be sent to the desired recipient. Using this ciphertext and the same one-time key you used, the recipient will be able to decrypt the message.

It is true that the Vernam Cipher is unbreakable, but this is only due to the fact that you must supply a different random key every time you encrypt a message. Re-use of a cipher for multiple messages can lead to the messages being decrypted. If you are interested, read more about it here on Wikipedia (don’t worry, it is trustworthy :P ).