var conversionTable1 = [ ["a", "ا"], ["A", "َ"], ["e", "ِ"], ["o", "ُ"], ["b", "ب"], ["p", "پ"], ["t", "ت"], ["c", "ث"], ["j", "ج"], ["J", "چ"], ["H", "ح"], ["K", "خ"], ["d", "د"], ["D", "ذ"], ["r", "ر"], ["Z", "ژ"], ["z", "ز"], ["s", "س"], ["w", "ش"], ["S", "ص"], ["x", "ض"], ["T", "ط"], ["X", "ظ"], ["E", "ع"], ["Q", "غ"], ["f", "ف"], ["q", "ق"], ["k", "ک"], ["g", "گ"], ["l", "ل"], ["m", "م"], ["n", "ن"], ["N", "ً"], ["h", "ه"], ["v", "و"], ["u", "و"], ["y", "ی"], ["W", "ّ"], ["~", "آ"], ["`", "ء"], ["i", "ی"], ["I", "ئ"], ["*", "×"], ["%", "٪"], ["/", "÷"], [",", "،"], [";", "؛"], ["?", "؟"], ["0", "۰"], ["1", "۱"], ["2", "۲"], ["3", "۳"], ["4", "۴"], ["5", "۵"], ["6", "۶"], ["7", "۷"], ["8", "۸"], ["9", "۹"], [" ", " "], ["|", "‌"], ["$", "ـ"] ]; var conversionTable = conversionTable1; // for compatibility with bookmarklets function cyr_translit(src) { return to_cyrillic(src); } var conversionHash = undefined; var maxCyrLength = 0; var maxLatLength = 0; function getConversionHash() { if (conversionHash == undefined) { conversionHash = new Array(); for (var i = 0; i < conversionTable.length; i++) { if (!conversionHash[conversionTable[i][0]]) { conversionHash[conversionTable[i][0]] = conversionTable[i].slice(1); maxLatLength = Math.max(maxLatLength, conversionTable[i][0].length); } } } return conversionHash; } function to_cyrillic(src, output, chunks) { if (src == undefined || src == "" || src == null) return src; if (output == undefined) output = new String(); var hash = getConversionHash(); var location = 0; while (location < src.length) { var len = Math.min(maxLatLength, src.length - location); var arr = undefined; var sub; while (len > 0) { sub = src.substr(location, len); arr = hash[sub]; if (arr != undefined) break; else len--; } // need this for translit on the fly if (chunks != undefined) chunks[chunks.length] = [sub, arr == undefined ? 0 : arr[0].length]; if (arr == undefined) { output += sub; location++; } else { // case analysis var newChar = arr[0]; if (sub.toLowerCase() == sub && arr.length > 1 && arr[1] && (newChar != newChar.toLowerCase())) { // need translit hash to determine if previous character (and possibly the one before it) // were converted and are in upper case // set prevDud to true previous is not a translated character or simply a blank // set prevCap to true if previous was translated and was upper case var prevCh = output.length == 0 ? null : output.substr(output.length - 1, 1); var prevDud = !prevCh || !getTranslitString(prevCh); var prevCap = (!prevDud && prevCh == prevCh); // sub is caseless but result isn't. case will depend on lookbehind and lookahead if (prevDud || !prevCap) { output += newChar.toLowerCase(); prevCap = false; } else { var next = " "; if (location + len < src.length) next = src.substr(location + len, 1); if (next != next && next == next.toLowerCase()) { //next is lowercase (and not caseless) output += newChar.toLowerCase(); } else if (next == next && next != next.toLowerCase()) { // next is uppercase (and not caseless) output += newChar; } else { // next is caseless. output case determined by the case of output[length - 2] var pprevCh = output.length == 1 ? null : output.substr(output.length - 2, 1); var pprevDud = !pprevCh || !getTranslitString(pprevCh); if (!pprevDud && (pprevCh == pprevCh)) { //pre-prev is in upper case. output is also uppercase output += newChar; } else { output += newChar.toLowerCase(); } } } } else if ((sub.toLowerCase() == sub) && (arr.length < 2 || !arr[1])) { // literal treatment of newChar output += newChar; } else if (sub != sub.toLowerCase()) { if (newChar.length > 1 && sub != sub) { // capitalize first letter of newChar output += newChar.substr(0, 1) + newChar.substr(1).toLowerCase(); } else { output += newChar; } } else { // sub is lowercase output += newChar.toLowerCase(); } location += len; } } return output; } // split string on HTML tags, return array containing both the matches and the pieces of string between them, matches always in even positions - since IE does not support this in String.split function splitHtmlString(string) { var re = /<[\/]?[!A-Z][^>]*>/ig; var result = new Array(); var lastIndex = 0; var arr = null; while ((arr = re.exec(string)) != null) { result[result.length] = string.substring(lastIndex, arr.index); result[result.length] = string.substring(arr.index, re.lastIndex); lastIndex = re.lastIndex; } result[result.length] = string.substr(lastIndex); return result; } /* convert cyrillic to translit using to_translit-- similar to from_translit.... */ function to_translit_ext(src, skipHtml) { return convertWithSkip(src, skipHtml, to_translit); } /* convert translit to cyrillic (using to_cyrillic above) */ function to_cyrillic_ext(src, skipHtml) { return convertWithSkip(src, skipHtml, to_cyrillic); } function convertWithSkip(src, skipHtml, converter) { if (src == "" || src == null) return src; if (!skipHtml) return converter(src); else { var arr = splitHtmlString(src); for (var i = 0; i < arr.length; i++) { if ((i % 2) == 0) arr[i] = converter(arr[i]); } return arr.join(""); } } var translitHash = undefined; function initTranslit() { if (translitHash == undefined) { translitHash = new Array(); for (var i = 0; i < conversionTable.length; i++) { var ch = conversionTable[i][1]; maxCyrLength = Math.max(maxCyrLength, ch.length); // if the translit string is not caseless, convert cyr string to upper case // otherwise maintain its case if (conversionTable[i][0] != conversionTable[i][0].toLowerCase()) ch = ch; if (translitHash[ch] == undefined) translitHash[ch] = conversionTable[i][0]; } } } /* convert cyrillic to translit */ function getTranslitString(ch) { initTranslit(); var value = translitHash[ch]; if (value == undefined) value = translitHash[ch]; return value; } function to_translit(src) { /* if (src == undefined || src == "" || src == null) return src; var output = new String(); for (var i = 0; i < src.length; i++) { var ch = src.substr(i, 1); var value = getTranslitString(ch); if (value != undefined) { if (ch != ch) { output += value.toLowerCase(); } else { prev = i == 0 ? null : src.substr(i - 1, 1); next = i == src.length - 1 ? null : src.substr(i + 1, 1); if ( value.length == 1 || (prev && prev == prev) || (next && next == next)) { // completely capitalize output += value; } else { // capitalize first letter output += value.substr(0, 1) + value.substr(1).toLowerCase(); } } } else output += ch; } return output; */ if (src == undefined || src == "" || src == null) return src; //force initTranslit to get the value of maxCyrLength getTranslitString(""); var output = new String(); var loc = 0; while (loc < src.length) { //for (var i = 0; i < src.length; i++) { var len = Math.min(maxCyrLength, src.length - loc); var value = undefined; var str = undefined; while (len > 0) { str = src.substr(loc, len); value = getTranslitString(str); if (value == undefined) len--; else break; } //var ch = src.substr(i, 1); //var value = getTranslitString(ch); if (value != undefined) { if (str == str.toLowerCase()) { output += value.toLowerCase(); } else if (str != str && value.length > 1) { // neither upper nor lower - upcase first letter and be done output += value.substr(0, 1) + value.substr(1).toLowerCase(); } else { // str is all upcase var prev = loc == 0 ? null : src.substr(loc - value.length, 1); var next = loc == src.length - str.length ? null : src.substr(loc + str.length, 1); if (value.length == 1 || str.length > 1 || (prev && prev == prev) || (next && next == next)) { // completely capitalize output += value; } else { // capitalize first letter output += value.substr(0, 1) + value.substr(1).toLowerCase(); } } } else output += str; loc += str.length; } return output; } //-- translit on-the-fly -- function replaceValue(node, value, stepback) { if (stepback == undefined) stepback = 0; if (isExplorer()) { var range = document.selection.createRange(); range.moveStart("character", -stepback); range.text = value; range.collapse(false); range.select(); } else { var scrollTop = node.scrollTop; var cursorLoc = node.selectionStart; node.value = node.value.substring(0, node.selectionStart - stepback) + value + node.value.substring(node.selectionEnd, node.value.length); node.scrollTop = scrollTop; node.selectionStart = cursorLoc + value.length - stepback; node.selectionEnd = cursorLoc + value.length - stepback; } } // compare positions function positionIsEqual(other) { if (isExplorer()) return this.position.isEqual(other.position); else return this.position == other.position; } function Position(node) { if (node.selectionStart != undefined) this.position = node.selectionStart; else if (document.selection && document.selection.createRange()) this.position = document.selection.createRange(); this.isEqual = positionIsEqual; } function resetState() { this.position = new Position(this.node); this.transBuffer = ""; this.cyrBuffer = ""; } function StateObject(node) { this.node = node; this.reset = resetState; this.cyrBuffer = ""; this.transBuffer = ""; this.position = new Position(node); } var stateHash = new Array(); function isExplorer() { return (document.selection != undefined && document.selection.createRange().isEqual != undefined); } function pressedKey(event) { if (isExplorer()) return event.keyCode; else return event.which; } function translitonkey(event) { /* if ((event.keyCode == 255 && event.charCode > 0) || event.keyCode == 8) { return; } */ if (event == undefined) event = window.event; var node = null; if (event.target) node = event.target; else if (event.srcElement) node = event.srcElement; // initialize state var state = stateHash[node]; if (state == null) { state = new StateObject(node); stateHash[node] = state; } if ((pressedKey(event) > 20) && !event.ctrlKey && !event.altKey && !event.metaKey) { var c = String.fromCharCode(pressedKey(event)); // process input var result = process_translit(state, c); // finish up if (c != result.out || result.replace != 0) { if (isExplorer()) event.returnValue = false; else event.preventDefault(); replaceValue(node, result.out, result.replace); state.position = new Position(node); } } } function TranslitResult() { this.out = ""; this.replace = 0; } function process_translit(state, c) { // reset state if position changed if (!state.position.isEqual(new Position(state.node))) state.reset(); var result = new TranslitResult(); // initial backbuffer. Add to it as characters are converted var backbuffer = getBackBuffer(state.node, state.cyrBuffer.length, 2 * maxLatLength); var chunks = new Array(); state.transBuffer = state.transBuffer + c var str = to_cyrillic(state.transBuffer, backbuffer, chunks); // remove backbuffer from output str = str.substr(backbuffer.length); result.out = str; /* str is now left alone - it has the output matching contents of chunks and will be used to reinitialize backbuffers, along with chunks and state.transBuffer */ // get the difference between state.cyrBuffer and output for (var i = 0; i < Math.min(state.cyrBuffer.length, result.out.length); i++) { if (state.cyrBuffer.substr(i, 1) != result.out.substr(i, 1)) { result.replace = state.cyrBuffer.length - i; result.out = result.out.substr(i); break; } } if (result.replace == 0) { result.out = result.out.substr(Math.min(state.cyrBuffer.length, result.out.length)); } // update state: backbuffer, bufferArray if (chunks.length > 0 && chunks[chunks.length - 1] == result.out.substr(result.out.length - 1)) { // no convertion took place, reset state state.reset(); } else { while (state.transBuffer.length > maxLatLength) { state.transBuffer = state.transBuffer.substr(chunks[0][0].length); // chunks[i][1] evaluates to false if no conversion took place, otherwise holds the length of cyr string str = str.substr(chunks[0][1] ? chunks[0][1] : chunks[0][0].length); chunks.shift(); //chunks.shift(); //str = str.substr(1); } state.cyrBuffer = str; } return result; } function getBackBuffer(node, offset, count) { if (isExplorer()) { //.tagName == "EDITOR") { var range = document.selection.createRange(); range.moveStart("character", -offset); var result = range.text.substr(-count); if (!result) result = ""; return result; } else { return node.value.substring(0, node.selectionStart - offset).substr(-count); } } // need this for bookmarklets function getSelectedNode() { if (document.activeElement) return document.activeElement; else if (window.getSelection && window.getSelection() && window.getSelection().rangeCount > 0) { var range = window.getSelection().getRangeAt(0); if (range.startContainer && range.startContainer.childNodes && range.startContainer.childNodes.length > range.startOffset) return range.startContainer.childNodes[range.startOffset] } return null; } function toggleCyrMode() { var node = getSelectedNode(); if (node) { if (stateHash[node]) { if (removeKeyEventListener(node)) delete stateHash[node]; } else { if (addKeyEventListener(node)) stateHash[node] = new StateObject(node); } } } function addKeyEventListener(node) { if (node.addEventListener) node.addEventListener("keypress", translitonkey, false); else if (node.attachEvent) node.attachEvent("onkeypress", translitonkey); else return false; return true; } function removeKeyEventListener(node) { if (node.removeEventListener) node.removeEventListener("keypress", translitonkey, false); else if (node.detachEvent) node.detachEvent("onkeypress", translitonkey); else return false; return true; } function getSelectedText() { if (isExplorer()) { return document.selection.createRange().text; } else { var node = getSelectedNode(); if (node && node.value && node.selectionStart != undefined && node.selectionEnd != undefined) return node.value.substring(node.selectionStart, node.selectionEnd); } return ""; } function bmkToCyrillic() { batchConverter(to_cyrillic_ext); } function bmkToTranslit() { batchConverter(to_translit_ext); } function RangeConversionState(range, converter) { this.range = range; this.convert = converter; this.started = false; this.finished = false; this.toString = function() { return "started : " + this.started + ", finished: " + this.finished; }; } function convertRangeNode(node, state) { if (state.started && state.finished) return; if (!state.started && (((state.range.startContainer.nodeType == node.TEXT_NODE || state.range.startContainer.nodeType == node.PROCESSING_INSTRUCTION_NODE || state.range.startContainer.nodeType == node.COMMENT_NODE) && node == state.range.startContainer) || (state.range.startContainer.childNodes && node == state.range.startContainer.childNodes[state.range.startOffset]) )) state.started = true; if (node.nodeType == node.TEXT_NODE || node.nodeType == node.PROCESSING_INSTRUCTION_NODE || node.nodeType == node.COMMENT_NODE) { if (state.started && !state.finished) { // convert text var start = (node == state.range.startContainer) ? state.range.startOffset : 0; var end = (node == state.range.endContainer) ? state.range.endOffset : node.nodeValue.length; var remainder = (node == state.range.endContainer) ? node.nodeValue.length - state.range.endOffset : 0; node.nodeValue = node.nodeValue.substring(0, start) + state.convert(node.nodeValue.substring(start, end)) + node.nodeValue.substr(end); if (node == state.range.endContainer) state.range.setEnd(node, node.nodeValue.length - remainder); if (node == state.range.startContainer) state.range.setStart(node, start); } } else if (node.childNodes) // walk the tree for (var i = 0; i < node.childNodes.length; i++) { convertRangeNode(node.childNodes[i], state); if (state.started && state.finished) break; } if (!state.finished && (((state.range.endContainer.nodeType == node.TEXT_NODE || state.range.endContainer.nodeType == node.PROCESSING_INSTRUCTION_NODE || state.range.endContainer.nodeType == node.COMMENT_NODE) && node == state.range.endContainer) || ((state.range.endContainer.childNodes.length > 0) && node == state.range.endContainer.childNodes[state.range.endOffset - 1]) )) state.finished = true; } function convertSelection(selection, converter) { if (selection == null) return; for (var i = 0; i < selection.rangeCount; i++) { convertRangeNode(selection.getRangeAt(i).commonAncestorContainer, new RangeConversionState(selection.getRangeAt(i), converter)); } selection.collapseToEnd(); } function batchConverter(convert) { if (isExplorer()) { var range = document.selection.createRange(); try { range.pasteHTML(convert(range.htmlText, true)); } catch (err) { range.text = convert(range.text, true); } } else if (window.getSelection) { var node = getSelectedNode(); var sel = window.getSelection(); if (node && node.value && node.selectionStart != undefined && node.selectionEnd != undefined) replaceValue(node, convert(node.value.substring(node.selectionStart, node.selectionEnd), true)); else if (sel && sel.toString() != "") convertSelection(sel, convert); } } function convertAll() { var area = document.getElementById("txt"); area.value = to_cyrillic_ext(area.value, document.getElementById("skipHTML").checked); } function convertSelected() { if (document.selection && document.selection.createRange()) { // ie var range = document.selection.createRange(); range.text = to_cyrillic_ext(range.text, document.getElementById("skipHTML").checked); } else { // mozilla, everything else var txt = document.getElementById("txt"); var str; if (txt.selectionStart != undefined) { var str = txt.value.substr(0, txt.selectionStart) + to_cyrillic_ext(txt.value.substring(txt.selectionStart, txt.selectionEnd), document.getElementById("skipHTML").checked) + txt.value.substr(txt.selectionEnd); } else { //str = do_translit(txt.value, document.getElementById("skipHTML").checked); alert("This feature is not supported by your browser. Please use \"Convert All\""); str = txt.value; } txt.value = str; } } function convertToTranslit() { var area = document.getElementById("txt"); area.value = to_translit(area.value); } function processKeys(event) { if (rtsupported) { if (event.keyCode == 27 && !isExplorer()) { //escape to toggle realTime = !realTime; document.getElementById("realtime").checked = realTime; } else if (realTime) translitonkey(event); } } var realTime = true; function rtClick(event) { realTime = !realTime; } var rtsupported = false; try { /* var nav = navigator.userAgent; rtsupported = (nav.indexOf("GECKO") >= 0 || nav.indexOf("OPERA") >= 0 || nav.indexOf("SAFARI") >= 0); */ rtsupported = (document.selection != undefined) if (!rtsupported) { var element = document.createElement("TEXTAREA"); document.getElementsByTagName("BODY")[0].appendChild(element); if (element.selectionStart != undefined) rtsupported = true; document.getElementsByTagName("BODY")[0].removeChild(element); } } catch (error) { } var maximized = false; function toggle() { var transliterator = document.getElementById("transliterator"); var main = document.getElementById("main"); var button = document.getElementById("btnmaximize"); var txt = document.getElementById("txt"); var transbottom = document.getElementById("transbottom"); var sidebar = document.getElementById("sidebar"); if (!maximized) { //transliterator.className = "max"; main.className = "max"; //body.style.background = "inherit"; button.title = "Restore"; //document.body.style.overflow = "hidden"; document.documentElement.style.overflow = "hidden"; document.documentElement.style.height = "100%"; document.body.style.height = "100%"; //txt.className = "txt-max"; //button.className = "btnmaximize-max"; //transbottom.className = "transbottom-max"; sidebar.style.display = "none"; } else { //document.getElementById("transliterator").className = "transliterator-reg"; //document.body.style.background = "none"; button.title = "Maximize"; //button.className = ""; main.className = ""; //document.body.style.overflow = "auto"; document.documentElement.style.overflow = "auto"; document.documentElement.style.height = "auto"; document.body.style.height = "auto"; //txt.className = ""; //transbottom.className = ""; sidebar.style.display = "block"; } maximized = !maximized; } function convertAll() { var area = document.getElementById("txt"); area.value = to_cyrillic_ext(area.value, document.getElementById("skipHTML").checked); } function convertSelected() { if (document.selection && document.selection.createRange()) { // ie var range = document.selection.createRange(); range.text = to_cyrillic_ext(range.text, document.getElementById("skipHTML").checked); } else { // mozilla, everything else var txt = document.getElementById("txt"); var str; if (txt.selectionStart != undefined) { var str = txt.value.substr(0, txt.selectionStart) + to_cyrillic_ext(txt.value.substring(txt.selectionStart, txt.selectionEnd), document.getElementById("skipHTML").checked) + txt.value.substr(txt.selectionEnd); } else { //str = do_translit(txt.value, document.getElementById("skipHTML").checked); alert("This feature is not supported by your browser. Please use \"Convert All\""); str = txt.value; } txt.value = str; } } function convertToTranslit() { var area = document.getElementById("txt"); area.value = to_translit(area.value); } function processKeys(event) { if (rtsupported) { if (event.keyCode == 27 && !isExplorer()) { //escape to toggle realTime = !realTime; document.getElementById("realtime").checked = realTime; } else if (realTime) translitonkey(event); } } var realTime = true; function rtClick(event) { realTime = !realTime; } var rtsupported = false; try { /* var nav = navigator.userAgent.toUpperCase(); rtsupported = (nav.indexOf("GECKO") >= 0 || nav.indexOf("OPERA") >= 0 || nav.indexOf("SAFARI") >= 0); */ rtsupported = (document.selection != undefined) if (!rtsupported) { var element = document.createElement("TEXTAREA"); document.getElementsByTagName("BODY")[0].appendChild(element); if (element.selectionStart != undefined) rtsupported = true; document.getElementsByTagName("BODY")[0].removeChild(element); } } catch (error) { } var maximized = false; function toggle() { var transliterator = document.getElementById("transliterator"); var main = document.getElementById("main"); var button = document.getElementById("btnmaximize"); var txt = document.getElementById("txt"); var transbottom = document.getElementById("transbottom"); var sidebar = document.getElementById("sidebar"); if (!maximized) { //transliterator.className = "max"; main.className = "max"; //body.style.background = "inherit"; button.title = "Restore"; //document.body.style.overflow = "hidden"; document.documentElement.style.overflow = "hidden"; document.documentElement.style.height = "100%"; document.body.style.height = "100%"; //txt.className = "txt-max"; //button.className = "btnmaximize-max"; //transbottom.className = "transbottom-max"; sidebar.style.display = "none"; } else { //document.getElementById("transliterator").className = "transliterator-reg"; //document.body.style.background = "none"; button.title = "Maximize"; //button.className = ""; main.className = ""; //document.body.style.overflow = "auto"; document.documentElement.style.overflow = "auto"; document.documentElement.style.height = "auto"; document.body.style.height = "auto"; //txt.className = ""; //transbottom.className = ""; sidebar.style.display = "block"; } maximized = !maximized; } function create(htmlStr) { var frag = document.createDocumentFragment(), temp = document.createElement('div'); temp.innerHTML = htmlStr; while (temp.firstChild) { frag.appendChild(temp.firstChild); } return frag; } function ChangeKey(value, i) { conversionTable1[i][0] = value; } function FillTable() { chartabe1 = document.getElementById("chartable1"); for (i = 0; i < conversionTable1.length; i++) { var divContainer = document.createElement('div'); divContainer.setAttribute('class', 'container'); var divTop = document.createElement('div'); divTop.setAttribute('class', 'divTop'); var Toptxt = document.createTextNode(conversionTable1[i][0]); var textBox = document.createElement("input"); textBox.type = "text"; textBox.setAttribute('id', 'txtbx' + i); textBox.value = conversionTable1[i][0]; textBox.setAttribute('onChange', 'ChangeKey(this.value,' + i + ')'); textBox.setAttribute('size', '1'); textBox.setAttribute('maxlength', '1'); divTop.appendChild(textBox); var divBottom = document.createElement('div'); divBottom.setAttribute('class', 'divBottom'); var Bottomtxt = document.createTextNode(conversionTable1[i][1]); divBottom.appendChild(Bottomtxt); // div.setAttribute('onclick', 'alert(' + i + ')'); // div.setAttribute('id', 'divhar' + i); divContainer.appendChild(divTop); divContainer.appendChild(divBottom); chartabe1.appendChild(divContainer); } }