<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>