Prototype.jsでAjax.Requestするときに、UTF-8以外でPOST (Shift_JIS)

とある既存プロジェクトがSJISで作られていたために、Ajax.RequestでPOSTしたときに文字化けで悩まされました。

prototype.jsの対応バージョンは1.5.0です。

以下のコードをprototype.jsを読み込んだ後に読み込みます。

 
EscapeSJIS=function(str){
	return str.replace(/[^*+.-9A-Z_a-z-]/g,function(s){
		var c=s.charCodeAt(0),m;
		return c<128?(c<16?"%0":"%")+c.toString(16).toUpperCase():65376<c&&c<65440?"%"+(c-65216).toString(16).toUpperCase():(c=JCT11280.indexOf(s))<0?"%81E":"%"+((m=((c<8272?c:(c=JCT11280.lastIndexOf(s)))-(c%=188))/188)<31?m+129:m+193).toString(16).toUpperCase()+(64<(c+=c<63?64:65)&&c<91||95==c||96<c&&c<123?String.fromCharCode(c):"%"+c.toString(16).toUpperCase())
	})
};
 
UnescapeSJIS=function(str){
	return str.replace(/%(8[1-9A-F]|[9E][0-9A-F]|F[0-9A-C])(%[4-689A-F][0-9A-F]|%7[0-9A-E]|[@-~])|%([0-7][0-9A-F]|A[1-9A-F]|[B-D][0-9A-F])/ig,function(s){
		var c=parseInt(s.substring(1,3),16),l=s.length;
		return 3==l?String.fromCharCode(c<160?c:c+65216):JCT11280.charAt((c<160?c-129:c-193)*188+(4==l?s.charCodeAt(3)-64:(c=parseInt(s.substring(4),16))<127?c-64:c-65))
	})
};
 
Object.extend(Hash, {
  toQueryString: function(obj) {
    var parts = [];
 
	  this.prototype._each.call(obj, function(pair) {
      if (!pair.key) return;
 
      if (pair.value && pair.value.constructor == Array) {
        var values = pair.value.compact();
        if (values.length < 2) pair.value = values.reduce();
        else {
        	key = EscapeSJIS(pair.key);
          values.each(function(value) {
            value = value != undefined ? EscapeSJIS(value) : '';
            parts.push(key + '=' + EscapeSJIS(value));
          });
          return;
        }
      }
      if (pair.value == undefined) pair[1] = '';
      parts.push(pair.map(EscapeSJIS).join('='));
	  });
 
    return parts.join('&');
  }
});
 
Object.extend(Hash.prototype, {
 
  toQueryString: function() {
    return Hash.toQueryString(this);
  }
});
 
 
Object.extend(String.prototype,{
  toQueryParams: function(separator) {
    var match = this.strip().match(/([^?#]*)(#.*)?$/);
    if (!match) return {};
 
    return match[1].split(separator || '&').inject({}, function(hash, pair) {
      if ((pair = pair.split('='))[0]) {
        var name = UnescapeSJIS(pair[0]);
        var value = pair[1] ? UnescapeSJIS(pair[1]) : undefined;
 
        if (hash[name] !== undefined) {
          if (hash[name].constructor != Array)
            hash[name] = [hash[name]];
          if (value) hash[name].push(value);
        }
        else hash[name] = value;
      }
      return hash;
    });
  }
 
});