<html>
<head>
<title>Translation 2.0</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<style type="text/css">
textarea {
width : 100%;
}
div#tagGroup a {
padding-left : 5px;
padding-right : 5px;
border : 1px outset;
cursor : pointer;
font-weight : bolder;
}
#spendTime {
font-size : 8pt;
}
</style>
<script type="text/javascript" language="javascript">
var Translation = {};
// Copy result to Clipboard
Translation.Copy = function(){
if (window.clipboardData){
window.clipboardData.setData("Text", document.tform.outputData.value);
}else if (window.netscape){
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var clip = Components.classes['@mozilla.org/widget/clipboard;1'].createInstance(Components.interfaces.nsIClipboard);
if (!clip) return;
var trans = Components.classes['@mozilla.org/widget/transferable;1'].createInstance(Components.interfaces.nsITransferable);
if (!trans) return;
trans.addDataFlavor('text/unicode');
var str = new Object();
var len = new Object();
var str = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString);
var copytext = document.tform.outputData.value;
str.data = copytext;
trans.setTransferData("text/unicode",str,copytext.length*2);
var clipid=Components.interfaces.nsIClipboard;
if (!clip) return false;
clip.setData(trans,null,clipid.kGlobalClipboard);
}else{
return false;
}
return false;
};
// Clear all text
Translation.Clear = function(){
document.tform.inputData.value = "";
document.tform.outputData.value = "";
};
// Change function module
Translation.ChangeTab = function(tabObj, fuc){
// #region change tab color
var tabs = document.getElementById("tagGroup").childNodes;
for(var index in tabs){
if("A" == tabs[index].tagName){
tabs[index].style.backgroundColor = "white";
}
}
tabObj.style.backgroundColor = "lightblue";
// #endregion change tab color
// change description
document.getElementById("funcDes").innerHTML = fuc.Description;
// #region repaint controls
var controlPanel = document.getElementById("controlPanel");
// remvoe all component
while(controlPanel.firstChild){
controlPanel.removeChild(controlPanel.firstChild);
}
// add control component
var component;
for(index in fuc.Controls){
// create component
if(component = Translation.CreateElement(fuc.Controls[index])){
if("function" == typeof(fuc[component.value])){
// assign event delegate
component.setAttribute("action", fuc[component.value]);
component.onclick = function(){
// start caculate time
Stopwatch.Start();
// execute
this.action();
// stop caculate time
Stopwatch.Stop();
document.getElementById("spendTime").innerHTML = Stopwatch.SpendTime();
}
}
controlPanel.appendChild(component);
// clear stopwatch
controlPanel.appendChild(document.createTextNode(" "));
}
}
// #endregion repaint controls
document.getElementById("spendTime").innerHTML = "";
};
// Create action controls
Translation.CreateElement = function(json){
// check obect and tag name
if(json && json.tagName){
var e = document.createElement(json.tagName);
var child;
for(var i in json){
if("tagName" == i){
// skip tag name
}else if("innerHTML" == i){
// assgin content
e.innerHTML = json[i];
}else if("children" == i){
// process child nodes
if(json[i].constructor == Array){
for(var j in json[i]){
if((child = Translation.CreateElement(json[i][j]))) e.appendChild(child);
}
}else{
if((child = Translation.CreateElement(json[i]))) e.appendChild(child);
}
}else{
// assgin attribute
e.setAttribute(i, json[i]);
}
}
return e;
}else{
return false;
}
};
// Page resized
Translation.Resize = function(){
var docHeight = document.body.offsetHeight;
var tabHeight = document.getElementById("tagGroup").offsetHeight;
var headerHeight = document.getElementById("header").offsetHeight;
var actionsHeight = document.getElementById("actions").offsetHeight;
var txtHeight = (docHeight - tabHeight - headerHeight - actionsHeight - 80) / 2;
document.tform.inputData.style.height = txtHeight;
document.tform.outputData.style.height = txtHeight;
}
// Page load
Translation.Load = function(){
Translation.ChangeTab(document.getElementById("InitComponent"), Blogger);
Translation.Resize();
window.onresize = Translation.Resize;
};
// Caculate executing time
var Stopwatch = {
Tick : 0,
Start : function(){
this.Tick = new Date().getTime();
},
Stop : function(){
this.Tick = new Date().getTime() - this.Tick;
},
SpendTime : function(){
var time = this.Tick;
var output = time % 1000 + " milisecond";
time = Math.floor(time / 1000);
if(time > 0){
output = time % 60 + " second " + output;
time = Math.floor(time / 60);
}
if(time > 0){
output = time % 60 + " minutes " + output;
time = Math.floor(time / 60);
}
return "(" + output + ")";
}
}
// Blogger module
var Blogger = {
Description : "Html encode for Blogger posting.",
Controls : [
{tagName : "input", type : "button", value : "Translate"},
{tagName : "input", type : "button", value : "Resotre"}
],
Translate : function(){
var input = document.tform.inputData.value.split("");
var chars = [{s:"&",r:"&"},{s:" ",r:" "},{s:"\t",r:" "},{s:"<",r:"<"},{s:">",r:">"}];
for(var i = 0; i < input.length; i++){
for(var j in chars) input[i] = input[i].replace(chars[j].s, chars[j].r);
}
document.tform.outputData.value = input.join("");
},
Resotre : function(){
var input = document.tform.inputData.value;
var chars = [{s:"\t",r:" "},{s:" ",r:" "},{s:"<",r:"<"},{s:">",r:">"},{s:"&",r:"&"}];
var temp = input;
for(var i in chars){
while((input = input.replace(chars[i].r, chars[i].s)) != temp) temp = input;
}
document.tform.outputData.value = input;
}
};
// Url encode/decode
var UrlEncoder = {
Description : "URL encode/decode.",
Controls : [
{tagName : "input", type : "button", value : "Translate"},
{tagName : "input", type : "button", value : "Resotre"}
],
Translate : function(){
document.tform.outputData.value = encodeURI(document.tform.inputData.value);
},
Resotre : function(){
document.tform.outputData.value = decodeURI(document.tform.inputData.value);
}
};
// BASE64 encode/decode
var Base64Encoder = {
KeyCode : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
Description : "Base64 encode/decode.",
Controls : [
{tagName : "input", type : "button", value : "Translate"},
{tagName : "input", type : "button", value : "Resotre"}
],
Translate : function(){
var input = Base64Encoder.UTF8_encode(document.tform.inputData.value);
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
do {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output + Base64Encoder.KeyCode.charAt(enc1) + Base64Encoder.KeyCode.charAt(enc2) +
Base64Encoder.KeyCode.charAt(enc3) + Base64Encoder.KeyCode.charAt(enc4);
} while (i < input.length);
document.tform.outputData.value = output;
},
Resotre : function(){
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
var input = document.tform.inputData.value.replace(/[^A-Za-z0-9\+\/\=]/g, "");
do {
enc1 = Base64Encoder.KeyCode.indexOf(input.charAt(i++));
enc2 = Base64Encoder.KeyCode.indexOf(input.charAt(i++));
enc3 = Base64Encoder.KeyCode.indexOf(input.charAt(i++));
enc4 = Base64Encoder.KeyCode.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
} while (i < input.length);
document.tform.outputData.value = Base64Encoder.UTF8_decode(output);
},
UTF8_encode : function (string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
} else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
} else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
},
UTF8_decode : function (utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while ( i < utftext.length ) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
} else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
} else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
};
// Format json object (modify required)
var JSONFormater = {
Description : "Format json object",
Controls : [
{
tagName : "select",
id : "indentType",
children : [
{tagName : "option", value : "\t", selected : "selected", innerHTML : "indent with a tab character"},
{tagName : "option", value : " ", innerHTML : "indent with 2 spaces"},
{tagName : "option", value : " ", innerHTML : "indent with 3 spaces"},
{tagName : "option", value : " ", innerHTML : "indent with 4 spaces"},
{tagName : "option", value : " ", innerHTML : "indent with 8 spaces"}
]
},
{tagName : "input", type : "button", value : "Translate"}
],
Output : "",
Translate : function() {
var input = document.tform.inputData.value;
if (input.length == 0) {
alert("Empty source.");
return;
}
try {
eval("var temp = " + input + ";");
} catch (e) {
alert("Invalid JSON data.");
return;
}
JSONFormater.FormatNode(temp, true, 0)
JSONFormater.ClearComma();
document.tform.outputData.value = JSONFormater.Output;
JSONFormater.Output = "";
},
HasMembers : function(node) {
for (var m in node) return true;
return false;
},
Append : function(str, lineSeparator, hasIndent, indentLevel){
var indent = "";
if(hasIndent && indentLevel > 0){
var indentType = document.getElementById("indentType").value;
while(indentLevel-- > 0) indent += indentType;
}
this.Output += indent + str + (lineSeparator ? "\r\n" : "");
},
ClearComma : function(){
// clear unexcepted comma
if(this.Output.lastIndexOf(",\r\n") == this.Output.length - 3)
this.Output = this.Output.substring(0, this.Output.length -3) + "\r\n";
},
FormatNode : function(node, isValue, indentLevel){
var i;
if(node.constructor == Array){
this.Append("[", true, !isValue, indentLevel);
for(i in node){
this.FormatNode(node[i], false, indentLevel + 1);
}
this.ClearComma();
this.Append("]", true, true, indentLevel);
}else if(this.HasMembers(node)){
this.Append("{", true, !isValue, indentLevel);
for(i in node){
this.Append("\"" + i + "\" : ", false, true, indentLevel + 1);
this.FormatNode(node[i], true, indentLevel + 1);
}
this.ClearComma();
this.Append("},", true, true, indentLevel);
}else if(node.constructor == String){
this.Append("\"" + node + "\",", true, !isValue, indentLevel);
}else{
this.Append(node + ",", true, !isValue, indentLevel);
}
}
};
// Srt file modifier
var SRTModifier = {
Description : "Modify time line of *.srt files.",
Controls : [
{tagName : "input", type : "text", value : "0", id : "srtAdjustment"},
{tagName : "input", type : "button", value : "Modify"}
],
Modify : function(){
var tick = parseInt(document.getElementById("srtAdjustment").value);
if(isNaN(tick)){
alert("Invalid parameter!");
return;
}
var lines = document.tform.inputData.value.split(/\r?\n/);
var output = "";
var session = [];
var index = 1;
for(var i in lines){
// trim
lines[i] = lines[i].replace(/^\s+|\s+$/g, "");
// start of subtitles
if(lines[i].match(/^\d+$/)){
if(session.length > 0){
output += session.join("\r\n") + "\r\n\r\n";
session = [];
}
// reindexing for appending or deleting
session.push((index++).toString());
}else if(lines[i].match(/\d+:\d+:\d+,\d+ --> \d+:\d+:\d+,\d+/)){
var times = lines[i].split(/\s-->\s/);
session.push(SRTModifier.AppendTick(times[0], tick) + " --" + "> " + SRTModifier.AppendTick(times[1], tick));
}else{
session.push(lines[i]);
}
}
document.tform.outputData.value = output + session.join("\r\n");
},
AppendTick : function(time, tick){
if(time.match(/\d+:\d+:\d+,\d+/)){
var indicator = time.split(/[:,]/);
indicator = this.ParseInt(indicator[0]) * 3600000 + this.ParseInt(indicator[1]) * 60000 + this.ParseInt(indicator[2]) * 1000 + this.ParseInt(indicator[3]);
indicator += tick;
// milisecond
var output = "," + this.Format(indicator % 1000, 3);
indicator = Math.floor(indicator / 1000);
// second
output = ":" + this.Format(indicator % 60, 2) + output;
indicator = Math.floor(indicator / 60);
// minute
output = ":" + this.Format(indicator % 60, 2) + output;
indicator = Math.floor(indicator / 60);
// hour
output = this.Format(indicator, 2) + output;
return output;
}else{
return "";
}
},
Format : function(num, size){
var str = num.toString();
while(str.length < size){
str = "0" + str;
}
return str;
},
ParseInt : function(num){
num = num.replace(/^0*([1-9]?\d?)$/,"$1");
return num.length == 0 ? 0 : parseInt(num);
}
};
// NCR
var NCR = {
Description : "Numeric Character Reference",
Controls : [
{tagName : "input", type : "button", value : "Translate"},
{tagName : "input", type : "button", value : "Resotre"}
],
Translate : function(){
var input = document.tform.inputData.value.split("");
for(var i = 0 ; i < input.length; i ++){
input[i] = "&#x" + input[i].charCodeAt(0).toString(16) + ";";
}
document.tform.outputData.value = input.join("");
},
Resotre : function(){
var input = document.tform.inputData.value;
var output = [];
var ncr = input.match(/&#x([\da-fA-F]+);/g);
var code = false;
for(var i = 0; i < ncr.length; i++){
code = ncr[i].toString().replace(/&#x([\da-fA-F]+);/, "$1");
output.push(String.fromCharCode(parseInt(code, 16)));
}
document.tform.outputData.value = output.join("");
}
};
// Convert Java Properties files
var JavaProperties = {
Description : "Translate Java properties file.",
Controls : [
{tagName : "input", type : "button", value : "Translate"},
{tagName : "input", type : "button", value : "Resotre"}
],
Translate : function(){
var lines = document.tform.inputData.value.split(/\r?\n/);
var separator = -1, key = "", value = "";
for(var i = 0 ; i < lines.length; i++){
// comment
if(lines[i].indexOf("#") == 0 || lines[i].indexOf("!") == 0){
continue;
}else{
separator = lines[i].indexOf("=");
if(separator == -1){
// condition of no separator
lines[i] = JavaProperties.Encode(lines[i]);
}else{
name = lines[i].substring(0, separator).replace(/^\s+|\s+$/g, "");
value = lines[i].substring(separator + 1, lines[i].length);
value = JavaProperties.Encode(value);
lines[i] = name + "=" + value;
}
}
}
document.tform.outputData.value = lines.join("\r\n");
},
Resotre : function(){
var input = document.tform.inputData.value;
var codes = input.match(/[\\]u([\da-fA-F]{4})/g);
var code = "";
for(var i = 0; i < codes.length; i++){
code = codes[i].toString().replace(/[\\]u([\da-fA-F]{4})/, "$1");
input = input.replace(codes[i].toString(), String.fromCharCode(parseInt(code, 16)));
}
document.tform.outputData.value = input;
},
Encode : function(s){
var buffer = [];
for(var i = 0 ; i < s.length; i++){
buffer.push(s.charCodeAt(i) < 128 ? s.charAt(i) : ("\\u" + s.charCodeAt(i).toString(16)));
}
return buffer.join("");
}
};
</script>
</head>
<body onload="Translation.Load();">
<form name="tform" action="*">
<!-- Tabs -->
<div id="tagGroup">
<a onclick="Translation.ChangeTab(this,Blogger)" id="InitComponent">Blogger</a>
<a onclick="Translation.ChangeTab(this,JSONFormater)">Json Formater</a>
<a onclick="Translation.ChangeTab(this,UrlEncoder)">URL</a>
<a onclick="Translation.ChangeTab(this,Base64Encoder)">BASE64</a>
<a onclick="Translation.ChangeTab(this,NCR)">NCR</a>
<a onclick="Translation.ChangeTab(this,JavaProperties)">Java properties</a>
<a onclick="Translation.ChangeTab(this,SRTModifier)">SRT</a>
</div>
<!-- Input & output -->
<div><textarea name="inputData"></textarea></div>
<div><textarea name="outputData" style="background-color:lightgray;" readonly="true"></textarea></div>
<!-- Description & control action -->
<h4 id="header"><span id="funcDes">Description</span> <span id="spendTime"></span></h4>
<div id="actions">
<span id="controlPanel">
<input type="button" value="control button" />
</span>
<input type="button" value="Copy" onclick="Translation.Copy();" />
<input type="button" value="Clear" onclick="Translation.Clear();" />
</div>
</form>
</body>
</html>