User:Reza1615/fa-transliteration.js

From Meta, a Wikimedia project coordination wiki

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/**
 * Trasliteration Tool
 * @author Junaid P V ([[user:Junaidpv]])
 * @date 2010-05-19
 * License: GPLv3, CC-BY-SA 3.0
 */
/**
 * Define your own regular expression rules here. Or include predefined rules before this file.
 * They should be in associative arrays named 'rules' and 'memrules'
 * 'rules' table is for normal rewriting
 * 'memrules' table is for memorised rules
*/
 
// defining to store state info
var trasliteration_fields = {};
// memory for previus key sequence
var previous_sequence = {};
// temporary disabling of transliteration
var temp_disable = {};
/**
 * from: http://stackoverflow.com/questions/3053542/how-to-get-the-start-and-end-points-of-selection-in-text-area/3053640#3053640
 */
function GetCaretPosition(el) {
    var start = 0, end = 0, normalizedValue, range,
        textInputRange, len, endRange;
 
    if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
        start = el.selectionStart;
        end = el.selectionEnd;
    } else {
        range = document.selection.createRange();
        if (range && range.parentElement() == el) {
            len = el.value.length;
            normalizedValue = el.value.replace(/\r\n/g, "\n");
 
            // Create a working TextRange that lives only in the input
            textInputRange = el.createTextRange();
            textInputRange.moveToBookmark(range.getBookmark());
 
            // Check if the start and end of the selection are at the very end
            // of the input, since moveStart/moveEnd doesn't return what we want
            // in those cases
            endRange = el.createTextRange();
            endRange.collapse(false);
 
            if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
                start = end = len;
            } else {
                start = -textInputRange.moveStart("character", -len);
                start += normalizedValue.slice(0, start).split("\n").length - 1;
 
                if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
                    end = len;
                } else {
                    end = -textInputRange.moveEnd("character", -len);
                    end += normalizedValue.slice(0, end).split("\n").length - 1;
                }
            }
        }
    }
    return {
        start: start,
        end: end
    };
}
 
/**
 * from: http://stackoverflow.com/questions/3274843/get-caret-position-in-textarea-ie
 */
function offsetToRangeCharacterMove(el, offset) {
    return offset - (el.value.slice(0, offset).split("\r\n").length - 1);
}
/**
 * IE part from: http://stackoverflow.com/questions/3274843/get-caret-position-in-textarea-ie
 */
function setCaretPosition (el, iCaretPos)
{
    if (document.selection) // IE
    {
	endOffset = startOffset=iCaretPos;
	var range = el.createTextRange();
	var startCharMove = offsetToRangeCharacterMove(el, startOffset);
	range.collapse(true);
	if (startOffset == endOffset) {
		range.move("character", startCharMove);
	} else {
		range.moveEnd("character", offsetToRangeCharacterMove(el, endOffset));
		range.moveStart("character", startCharMove);
	}
	range.select();
    }
    else if (el.selectionStart || el.selectionStart == '0') // Firefox
    {
        el.setSelectionRange(iCaretPos, iCaretPos)
    }
}
 
function getLastSixChars(str, caretPosition)
{
	if(caretPosition <= 6 ) return str.substring(0,caretPosition);
	else return str.substring(caretPosition-6,caretPosition);
}
 
function replaceTransStringAtCaret(control, oldStringLength, newString, selectionRange)
{
	var text = control.value;
	// firefox always scrolls to topmost position,
	// to scroll manually we keep original scroll postion.
	if(control.scrollTop || control.scrollTop=='0') { var scrollTop = control.scrollTop; }
	if(text.length  >= 1) {
		var firstStr = text.substring(0, selectionRange['start'] - oldStringLength + 1);
		var lastStr = text.substring(selectionRange['end'], text.length);
		control.value = firstStr+newString+ lastStr;
		var newCaretPosition = firstStr.length+newString.length;
		setCaretPosition(control,newCaretPosition);
	}
	else { 
		control.value = newString;
		var newCaretPosition = newString.length;
		setCaretPosition(control,newCaretPosition);
	}
	// Manually scrolling in firefox, few tweeks or re-writing may require
	if (navigator.userAgent.indexOf("Firefox")!=-1) {
		var textLength = control.value.length;
		var cols = control.cols;
		if(newCaretPosition > (textLength-cols)) {
			//var height = parseInt(window.getComputedStyle(control,null).getPropertyValue('height'));
			var fontsize = parseInt(window.getComputedStyle(control,null).getPropertyValue('font-size'));
			//var lineheight = height/fontsize;
			control.scrollTop = scrollTop+fontsize;
		} else control.scrollTop = scrollTop;
	}
}
 
/**
 * This function will take a string to check against regular expression rules in the rules array.
 * It will return a two memeber array, having given string as first member and replacement string as
 * second memeber. If corresponding replacement could not be found then second string will be too given string
*/
function trans(lastpart,e)
{
	var len = lastpart.length;
	var i=0;
	var part1 = lastpart;
	var part2 = lastpart;
	var found = false;
outerloop1:
	for(i=0; i< len; i++)
	{
		var toTrans = lastpart.substring(i, len);
		for(var key in memrules)
		{
			if((new RegExp(key)).test(toTrans) && (new RegExp(memrules[key][0])).test(previous_sequence[(e.currentTarget || e.srcElement).id ]))
			{
				part1 = toTrans;
				part2 = toTrans.replace(RegExp(key), memrules[key][1]);
				found = true;
				break outerloop1;
			}
		}
	}
	if(!found)
	{
	outerloop2:
		for(i=0; i< len; i++)
		{
			var toTrans = lastpart.substring(i, len);
			for(var key in rules)
			{
				if((new RegExp(key)).test(toTrans))
				{
					part1 = toTrans;
					part2 = toTrans.replace(RegExp(key), rules[key]);
					break outerloop2;
				}
			}
		}
	}
	var pair = new Array(part1, part2);
	return pair;
}
/**
 * from: http://www.javascripter.net/faq/settinga.htm
 */
function setCookie(cookieName,cookieValue,nDays) {
	var today = new Date();
	var expire = new Date();
	if (nDays==null || nDays==0) nDays=1;
	expire.setTime(today.getTime() + 3600000*24*nDays);
	document.cookie = cookieName+"="+escape(cookieValue)+ ";expires="+expire.toGMTString();
}
/**
 * from: http://www.javascripter.net/faq/readinga.htm
 */
function readCookie(cookieName) {
	var theCookie=""+document.cookie;
	var ind=theCookie.indexOf(cookieName);
	if (ind==-1 || cookieName=="") return ""; 
	var ind1=theCookie.indexOf(';',ind);
	if (ind1==-1) ind1=theCookie.length; 
	return unescape(theCookie.substring(ind+cookieName.length+1,ind1));
}
 
function enableTrasliteration(controlID, enable) {
	if(enable==undefined) { enable = true; }
	var cookieValue;
	if(enable) {
		trasliteration_fields[controlID] = true;
		temp_disable[controlID] = false;
		cookieValue = 1;
	}
	else {
		trasliteration_fields[controlID] = false;
		cookieValue = 0;
	}
	var checkbox = document.getElementById(controlID+'cb');
	if(checkbox) { checkbox.checked = enable; }
	setCookie("tr"+controlID, cookieValue);
}
 
// event listener for trasliterattion textfield
// also listen for Ctrl+M combination to disable and enable trasliteration
function tiKeyPressed(event) {
	var e = event || window.event;
	var code = e.charCode || e.keyCode;
	var targetElement = (e.currentTarget || e.srcElement);
	if (code == 8 ) { previous_sequence[targetElement.id] = ''; return true; } // Backspace
    // If this keystroke is a function key of any kind, do not filter it
    if (e.charCode == 0 || e.which ==0 ) return true;       // Function key (Firefox and Opera), e.charCode for Firefox and e.which for Opera
    if (e.ctrlKey || e.altKey) // Ctrl or Alt held down
	{
		if (e.ctrlKey && (e.keyCode == 13 || e.which == 109)) // pressed Ctrl+M
		{
			enableTrasliteration(targetElement.id, !trasliteration_fields[targetElement.id]);
			return false;
		}
		return true;
	}
	if (code < 32) return true;             // ASCII control character
	if(trasliteration_fields[targetElement.id])
	{
 
		var c = String.fromCharCode(code);
		var selectionRange = GetCaretPosition(targetElement);
		var lastSevenChars = getLastSixChars(targetElement.value, selectionRange['start']);
 
		if(code ==62 && previous_sequence[targetElement.id ].substring(previous_sequence[targetElement.id ].length-1)=="<") 
		{
			var oldString = "<>";
			var newString = "";
			temp_disable[targetElement.id] = !temp_disable[targetElement.id];
		}
		else {
			if(!temp_disable[targetElement.id])
			{
				var transPair = trans(lastSevenChars+c, e);
				var oldString = transPair[0];
				var newString = transPair[1];
			}
			else 
			{
				var oldString = c;
				var newString = c;
			}
		}
		replaceTransStringAtCaret(targetElement, oldString.length, newString , selectionRange);
		previous_sequence[targetElement.id ] += c;
		if(previous_sequence[targetElement.id ].length > 6 ) previous_sequence[targetElement.id ] = previous_sequence[targetElement.id ].substring(previous_sequence[targetElement.id ].length-6);
		if(event.preventDefault) event.preventDefault();
		else if(event.cancelBubble) { event.cancelBubble = true; }
		return false;
	}
	return true;
}
/**
 * This is the function to which call during window load event for trasliterating textfields.
 * The funtion will accept any number of HTML tag IDs of textfields.
*/
function transliterate(id) {
	var len = arguments.length;
	for(var i=0;i<len; i++)
	{
		var element = document.getElementById(arguments[i]);
		if(element)
		{
			trasliteration_fields[arguments[i]] = true;
			previous_sequence[arguments[i]] = '';
			//element.onkeypress = tiKeyPressed;
			if (element.addEventListener){
				element.addEventListener('keypress', tiKeyPressed, false);
			} else if (element.attachEvent){  
				element.attachEvent("onkeypress", tiKeyPressed);  
			}  
		}
	}
}
 
function transOptionOnClick(event)
{
	var e = event || window.event;
	var checkbox =  (e.currentTarget || e.srcElement);
	if(checkbox.checked)
	{
		enableTrasliteration(checkbox.value,true);
	}
	else
	{
		enableTrasliteration(checkbox.value,false);
	}
}
// change this value to "after" or "before" to position transliteration option check box
var TO_POSITION = "after";
// check box message
var CHECKBOX_TEXT = "To Write Hindi (Ctrl+M)";
// call this function to add checkbox to enable/disable transliteration
function addTransliterationOption()
{
	var len = arguments.length;
	for(var i=0;i<len; i++)
	{
		var element = document.getElementById(arguments[i]);
		if(element)
		{
			var checkbox = document.createElement('input');
			checkbox.id = arguments[i]+'cb';
			checkbox.type = 'checkbox';
			checkbox.value = arguments[i];
			checkbox.onclick = transOptionOnClick;
			checkbox.checked = true;
			var para = document.createElement('p');
			para.appendChild(checkbox);
			var text = document.createTextNode(CHECKBOX_TEXT);
			para.appendChild(text);
			if(TO_POSITION=="after") element.parentNode.insertBefore(para, element.nextSibling);
			else if(TO_POSITION=="before") element.parentNode.insertBefore(para, element);
		}
	}
}
 
/**
 * This functions is to synchronize state transliteration state to fields from cookies
 */
function translitStateSynWithCookie() {
	var len = arguments.length;
	for(var i=0;i<len; i++)
	{
		var element = document.getElementById(arguments[i]);
		if(element)
		{
			var state = readCookie("tr"+arguments[i]);
			var enable = true;
			if(parseInt(state) == 0) { enable=false; }
			enableTrasliteration(arguments[i],enable);
		}
	}
}

/**
 * Trasliteration regular expression rules table for Devanagari
 * @authors: Junaid P V ([[user:Junaidpv]]), Mayur Kumar ([[user:mayur]])
 * @Maintainer: Mayur ([[user:mayur]]) 
 * @Maintainer for fawiki: Reza1615 ([[user:Reza1615]]) 
 * @date 2010-09-29
 * License: GPLv3, CC-BY-SA 3.0
 */
 // Normal rules
 var rules = {
'^\\;$':'ک',
'^\\[$':'ج',
'^\\]$':'چ',
'\\u0027$':'گ',
'^a$':'ش',
'^b$':'ذ',
'^c$':'ز',
'^d$':'ی',
'^e$':'ث',
'^f$':'ب',
'^g$':'ل',
'^h$':'ا',
'^i$':'ه',
'^j$':'ت',
'^k$':'ن',
'^l$':'م',
'^m$':'پ',
'^\\,$':'و',
'^n$':'د',
'^o$':'خ',
'^p$':'ح',
'^q$':'ض',
'^r$':'ق',
'^s$':'س',
'^t$':'ف',
'^u$':'ع',
'^v$':'ر',
'^w$':'ص',
'^x$':'ط',
'^y$':'غ',
'^z$':'ظ',
'^A$':'ؤ',
'^B$':'ذ',
'^C$':'ژ',
'^D$':'ی',
'^E$':'ث',
'^F$':'ب',
'^G$':'ل',
'^H$':'آ',
'^I$':'ّ',
'^J$':'ة',
'^K$':'»',
'^L$':'«',
'^M$':'ء',
'^N$':'ٔ',
'^O$':'خ',
'^P$':'ح',
'^Q$':'ض',
'^R$':'ً',
'^S$':'ئ',
'^T$':'ف',
'^U$':'ع',
'^V$':'ر',
'^W$':'ص',
'^Y$':'غ',
'^Z$':'ظ',
'^¯$':'\u200C',
'^0$':'۰',
'^1$':'۱',
'^2$':'۲',
'^3$':'۳',
'^4$':'۴',
'^5$':'۵',
'^6$':'۶',
'^7$':'۷',
'^8$':'۸',
'^9$':'۹'
};
// Memorised rules
var memrules = {
 
};

/**
 * Beginning of Transliteration Tool
 * @Maintainer for fawiki: Reza1615 ([[user:Reza1615]])
 * License: GPLv3, CC-BY-SA 3.0
 */
function addCheckBoxToSimpleSearch() {
	//To add "farsi" transliteration tool
	//********************* farsi **********************************
	var firstone =document.getElementById('p-search');
	if(firstone!= null) {
	try
	{
	var nextone=document.getElementById('h5');
 
	var chkboxelement = document.createElement("input");
	chkboxelement.setAttribute("type","checkbox");
	chkboxelement.setAttribute("id","searchInputcb");
	chkboxelement.style.position ="relative";
	chkboxelement.style.left=".2em";
	chkboxelement.style.top="-3.8em";
	chkboxelement.value = 'searchInput'; // specifying curresponding input filed.
	chkboxelement.checked =true;
 
	if (chkboxelement.addEventListener) 
	chkboxelement.addEventListener("click", transOptionOnClick, false);
	else if (chkboxelement.attachEvent) 
	chkboxelement.attachEvent("onclick", transOptionOnClick);
 
	var chkboxlabel = document.createElement('chkboxlabel');
	chkboxlabel.style.fontSize = '.75em';
	chkboxlabel.style.fontWeight = 'bold';
	chkboxlabel.style.position ="relative";
	chkboxlabel.style.left=".1em";
	chkboxlabel.style.top="-4em"
 
	var linktohelp = document.createElement ('a')
        linktohelp.href= "http://fa.wikipedia.org/wiki/ویکی‌پدیا:فارسی‌نویسی";
        linktohelp.title= "Phonetic Roman-to-farsi: Ctrl + M تایپ با کیبرد لاتین";
        linktohelp.appendChild( document.createTextNode('تایپ فارسی با کیبرد لاتین') );
	chkboxlabel.appendChild(linktohelp);
	chkboxlabel.appendChild(document.createElement('fa'));
	firstone.insertBefore(chkboxelement,nextone);
	firstone.insertBefore(chkboxlabel,nextone);
	firstone.style.position ="relative";
	//firstone.style.top="-1.6em";
	}
	catch(ex)
	{
	}
 
	}
	//************************* end of script ****************************
}
$(document).ready( function() {
	transliterate('searchInput', 'wpTextbox1', 'hotcat_text', 'wpSummary', 'mw-wikilove-message', 'wpFilterDescription', 'wpFilterTags', 'wpFilterRules', 'wpFilterNotes', 'wikieditor-toolbar-reference-text', 'mw-upload-form', 'wpDestFile', 'wpUploadDescription', 'emailuser', 'wpSubject', 'searchText', 'powerSearchText', 'wpNewTitle', 'wpReason', 'nsfrom', 'username', 'mwProtect-reason', 'nsto','wpText');
	CHECKBOX_TEXT = "تایپ فارسی با کیبرد لاتین (Ctrl+M)";
	addTransliterationOption( 'wpSummary', 'hotcat_text', 'searchText', 'mw-wikilove-message', 'powerSearchText', 'wpFilterDescription', 'wpFilterTags', 'wpFilterRules', 'wpFilterNotes', 'wikieditor-toolbar-reference-text', 'mw-upload-form', 'wpDestFile', 'wpUploadDescription', 'emailuser', 'wpSubject', 'wpNewTitle', 'wpReason', 'nsfrom', 'username', 'mwProtect-reason', 'nsto','wpText');
	TO_POSITION = "before";
	addTransliterationOption( 'wpTextbox1');
	addCheckBoxToSimpleSearch();
	translitStateSynWithCookie('wpTextbox1','searchInput','hotcat_text', 'mw-wikilove-message', 'wpSummary', 'wpFilterDescription', 'wpFilterTags', 'wpFilterRules', 'wpFilterNotes', 'wikieditor-toolbar-reference-text', 'mw-upload-form', 'wpDestFile', 'wpUploadDescription', 'emailuser', 'wpSubject', 'searchText', 'powerSearchText', 'wpNewTitle', 'wpReason', 'nsfrom', 'username', 'mwProtect-reason', 'nsto','wpText');
});
/* End of Transliteration Tool */