JavaScript Ninja – Unicode Aware Base64

I think examples are more effective than a long explanation.

Have a look at the code below:

(function(window, document, username_placeover_query, password_placeover_query, USERNAME, PASSWORD){
  "use strict";
  
/*┌─────────────────────────────────────────────────────────────────────────────┐
  │ NOTE.                                                                       │
  ╞═════════════════════════════════════════════════════════════════════════════╡
  │- unescape-encodeURIComponent breaks Unicode to binary-string where each     │
  │   character is less than 256 bytes.                                         │
  │- decodeURIComponent-escape brings back binary-string to Unicode.            │
  │- both are consider "hacks/non-official tricks" but are extreamly efficient, │
  │   and 100% compatible with non-Unicode characters.                          │
  └─────────────────────────────────────────────────────────────────────────────┘*/

/*┌─────┐
  │ LIB │
  └─────┘*/
  NodeList.prototype.forEach = Array.prototype.forEach;

  /*
  function base64_encode(str){
    str = unescape(encodeURIComponent(str));
    return btoa(str);
  };
  */

  function base64_decode(str){
    str = decodeURIComponent(escape(str));
    return atob(str);
  };

/*┌──────┐
  │ MAIN │
  └──────┘*/
  document.querySelectorAll(username_placeover_query).forEach(function(element){ element.value = base64_decode(USERNAME); });
  document.querySelectorAll(password_placeover_query).forEach(function(element){ element.value = base64_decode(PASSWORD); });


/*┌─────┐
  │ END │
  └─────┘*/
}(
   top
,  document
,  "#username"
,  "#password"
,  "bXlfdXNlcm5hbWU="   /*= my_username */
,  "bXlfcGFzc3dvcmQ="   /*= my_password */
));

This was intended to be used (after minified) as a bookmarklet,
After you will edit the USERNAME‘s value and PASSWORD‘s value,
and the placeover query,
you could (in a click) fill up username and password in websites that does not support Google Chrome’s authentication sync (or if for example this is the first time after installing new browser, with no previous profile existing on the current OS, or if you just have bookmarks in a html backup file… anyway.. I’ve used it from time to time [make sure to keep this stuff secure though..])

Anyway.. clicking the bookmarklet will fill up the data in the field’s value attribute.

naturally you can provide a better mechanisem by generating mouse click/down/up event or even a char-by-char keyboard “typing” with focus but I’ve skipped this part to simplify the example..

Base64’s btoa and atob methods are supported by mostly all of the new browsers,
which makes the entire solution much shorter than before,

just fyi.. those were the code segment previously required (old browsers) to do the same *thing*:

function base64_decode(data) {
  var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  var o1, o2, o3, h1, h2, h3, h4, bits, i = 0
    , ac = 0
    , dec = ""
    , tmp_arr = [];
  if (!data) {
    return data;
  }
  data += '';

  do {
    h1 = b64.indexOf(data.charAt(i++));
    h2 = b64.indexOf(data.charAt(i++));
    h3 = b64.indexOf(data.charAt(i++));
    h4 = b64.indexOf(data.charAt(i++));
    bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
    o1 = bits >> 16 & 0xff;
    o2 = bits >> 8 & 0xff;
    o3 = bits & 0xff;
    if (h3 == 64) {
      tmp_arr[ac++] = String.fromCharCode(o1);
    } else if (h4 == 64) {
      tmp_arr[ac++] = String.fromCharCode(o1, o2);
    } else {
      tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
    }
  } while (i < data.length);
  dec = tmp_arr.join('');
  dec = this.utf8_decode(dec);
  return dec;
}

function utf8_decode(str_data) {
  var tmp_arr = []
    , i = 0
    , ac = 0
    , c1 = 0
    , c2 = 0
    , c3 = 0;
  str_data += '';
  while (i < str_data.length) {
    c1 = str_data.charCodeAt(i);
    if (c1 < 128) {
      tmp_arr[ac++] = String.fromCharCode(c1);
      i++;
    } else if (c1 > 191 && c1 < 224) {
      c2 = str_data.charCodeAt(i + 1);
      tmp_arr[ac++] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
      i += 2;
    } else {
      c2 = str_data.charCodeAt(i + 1);
      c3 = str_data.charCodeAt(i + 2);
      tmp_arr[ac++] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
      i += 3;
    }
  }
  return tmp_arr.join('');
}

function utf8_encode(argString) {
  if (argString === null || typeof argString === "undefined") {
    return "";
  }
  var string = (argString + '');
  var utftext = ""
    , start, end, stringl = 0;
  start = end = 0;
  stringl = string.length;
  for (var n = 0; n < stringl; n++) {
    var c1 = string.charCodeAt(n);
    var enc = null;
    if (c1 < 128) {
      end++;
    } else if (c1 > 127 && c1 < 2048) {
      enc = String.fromCharCode((c1 >> 6) | 192) + String.fromCharCode((c1 & 63) | 128);
    } else {
      enc = String.fromCharCode((c1 >> 12) | 224) + String.fromCharCode(((c1 >> 6) & 63) | 128) + String.fromCharCode((c1 & 63) | 128);
    }
    if (enc !== null) {
      if (end > start) {
        utftext += string.slice(start, end);
      }
      utftext += enc;
      start = end = n + 1;
    }
  }
  if (end > start) {
    utftext += string.slice(start, stringl);
  }
  return utftext;
}

function base64_encode(data) {
  var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  var o1, o2, o3, h1, h2, h3, h4, bits, i = 0
    , ac = 0
    , enc = ""
    , tmp_arr = [];
  if (!data) {
    return data;
  }
  data = this.utf8_encode(data + '');
  do {
    o1 = data.charCodeAt(i++);
    o2 = data.charCodeAt(i++);
    o3 = data.charCodeAt(i++);
    bits = o1 << 16 | o2 << 8 | o3;
    h1 = bits >> 18 & 0x3f;
    h2 = bits >> 12 & 0x3f;
    h3 = bits >> 6 & 0x3f;
    h4 = bits & 0x3f;
    tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
  } while (i < data.length);
  enc = tmp_arr.join('');
  var r = data.length % 3;
  return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3);
}

by the way here is a binary string – Unicode examples

unescape(encodeURIComponent("א"))  -to- "א"   to binary string (length=1 -to- lengh=2)
decodeURIComponent(escape("א"))    -to- "א"   from binary string (length=2 - to lengh=1)

JavaScript Text Wrap/Fold On Specific Line-Character-Length

function fold(input, max_line_character_length, fold_character){
  var regex;

  input                      = "string" === typeof input                      ? input                        : "";
  max_line_character_length  = "number" === typeof max_line_character_length  ? max_line_character_length    : 10;
  fold_character             = "string" === typeof fold_character             ? fold_character               : "\n";

  regex = new RegExp("(.{"  +  String(max_line_character_length - fold_character.length)  +  "})", "gim");
  
  return input.replace(regex, "$1" + fold_character);
}

running

fold("aawregawaergarewqagaeragaewrgaewarjuasciji23r4avasdfaba asafdav fdsaewtyaa34a5a42aaa 6a2345aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 20)

will transform aawregawaergarewqagaeragaewrgaewarjuasciji23r4avasdfaba asafdav fdsaewtyaa34a5a42aaa 6a2345aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" into:

aawregawaergarewqag
aeragaewrgaewarjuas
ciji23r4avasdfaba a
safdav fdsaewtyaa34
a5a42aaa 6a2345aaaa
aaaaaaaaaaaaaaaaaaa
aaaaaaaaaa

specifying “closing character” – on unix or “original” [unformatted] email template, you might notice that the character before the new-line, is sometimes ‘=‘,
here too, you can specify (instead of default \n) any set of characters:

running

fold("aawregawaergarewqagaeragaewrgaewarjuasciji23r4avasdfaba asafdav fdsaewtyaa34a5a42aaa 6a2345aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 20, "=\n")

will transform the text into

aawregawaergarewqa=
gaeragaewrgaewarju=
asciji23r4avasdfab=
a asafdav fdsaewty=
aa34a5a42aaa 6a234=
5aaaaaaaaaaaaaaaaa=
aaaaaaaaaaaaaaaa

– max length is set to the limit given — INCLUDING the wrap character! (not including the \n).
– you should specify \n if you want to wrap the string [otherwise it is just a “separator-function” separating with delimiter every X characters…]

– it should pretty much support every charset, but you might consider transforming the string into byte-string first.

for example this seems to work fine:

fold("אאאאאאאאבבבבבבבבגגגגגגדדדדדדדדדדההההההההווווווווו", 10, "=\n")
outputs...
"אאאאאאאא=
בבבבבבבב=
גגגגגגדד=
דדדדדדדד=
הההההההה=
וווווווו=
ו"

you can make sure max-character value is less than 256 using unescape(encodeURIComponent("YOUR TEXT HERE"))

you better convert stuff before… for example to BASE64, than use the fold function on the ASCII content…

******
b.t.w
although it works it sure looks weird.. each line will look like אאאא=..
******