Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to base 36 encode with JavaScript / jQuery?

I'm thinking about using the encode/decode technique here (Encoding to base 36/decoding from base 36 is simple in Ruby)

how to implement a short url like urls in twitter?

Idea being to track user referrals, invite URLs. I can use Rails to decode, but it there a way to encode with Javascript or jQuery?

like image 890
AnApprentice Avatar asked Mar 03 '12 02:03

AnApprentice


2 Answers

The toString method on Number has an optional argument of radix:

(128482).toString(36);
128482..toString(36);
128482 .toString(36);
var num = 128482; num.toString(36);

Note this doesn't work, because numbers expect decimal digits after a period, not letters:

128482.toString(36);  // Syntax error

Also, you can decode with JS as well:

parseInt("2r4y", 36);

EDIT:

But if I want to remove look-alike characters (1-l or 0-O) what can I do?

The easiest is to reduce the base by number of characters you're skipping, then make a translation: Note that only one of 1-l or 0-O is a problem, since base36 encodes only lowercase (in which case you have 1-l, but not 0-O) which you can make uppercase (in which case, vice versa).

(128482).toString(36).replace(/[m-y]/, x => String.fromCharCode(x.charCodeAt(0) + 1))

If you want to have a base larger than 36, you would have to have your own base-changing function, as 36 is as high as toString supports. In that case, it is easy enough to make your own digit inventory as you want.

for working with long numbers?

Go ahead :) Note the n suffix that turns the number into BigInt:

1000000000000000000000000000000000000000000000000000000000n.toString(36)
// => "9edwccv83mch429oxmlxupo4z1bdaiusrm29s"
like image 52
Amadan Avatar answered Sep 19 '22 13:09

Amadan


For anyone looking for how to encode a string in base36 (since this question, How do i convert string to base36 in javascript , is redirected here) -

Here's what I came up with.

/* encode / decode strings to / from base36 

   based on: http://snipplr.com/view/12653/
*/

var base36 = {
    encode: function (str) {
        return Array.prototype.map.call(str, function (c) {
            return c.charCodeAt(0).toString(36);
        }).join("");
    },
    decode: function (str) {
        //assumes one character base36 strings have been zero padded by encodeAscii
        var chunked = [];
        for (var i = 0; i < str.length; i = i + 2) {
            chunked[i] = String.fromCharCode(parseInt(str[i] + str[i + 1], 36));
        }
        return chunked.join("");
    },
    encodeAscii: function (str) {
        return Array.prototype.map.call(str, function (c) {
            var b36 = base36.encode(c, "");
            if (b36.length === 1) {
                b36 = "0" + b36;
            }
            return b36;
        }).join("")
    },
    decodeAscii: function (str) {
        //ignores special characters/seperators if they're included
        return str.replace(/[a-z0-9]{2}/gi, function (s) {
            return base36.decode(s);
        })
    }
};

var foo = "a-Az-Z 0-9 !@#$%^&*()-_=+[{]};:',<.>/?`~";
var bar = base36.encodeAscii(foo);

console.log(foo);
console.log(base36.decode(bar));

console.log('');

var bar = "==/" + bar + "\\==";
console.log(bar)
console.log(base36.decodeAscii(bar));


//doesn't work
console.log('');
var myString = "some string";
var myNum = parseInt(myString, 36);
console.log(myNum.toString(36))

myString = "FooBarW000t";
myNum = parseInt(myString, 36);
console.log(myNum.toString(36))

myString = "aAzZ09!@#$%^&*()-_=+[{]};:',<.>/?`~";
myNum = parseInt(myString, 36);
console.log(myNum.toString(36))

/* 
Outputs:

a-Az-Z 0-9 !@#$%^&*()-_=+[{]};:',<.>/?`~
a-Az-Z 0-9 !@#$%^&*()-_=+[{]};:',<.>/?`~

==/2p191t3e192i0w1c191l0w0x1s0z10112m12161415192n1p172j3f2l3h1n1m13181o1a1q1b1r2o3i\==
==/a-Az-Z 0-9 !@#$%^&*()-_=+[{]};:',<.>/?`~\==

some
foobarw000w
aazz09
*/
like image 38
imjosh Avatar answered Sep 19 '22 13:09

imjosh