18

I have a textarea in which the user can enter text in english (or any other left-to-right language) or in a language that is RTL.

When the user writes in RTL, the user must press Right-shift + ctrl in order to make the text be aligned to the right and be rtl. However, in windows (and probably other modern OSes) the user can set any key combination to switch language and text direction.

I know how to display text as RTL, but how will I know which direction to display?

Is there a way to detect that the text typed in a textarea/text-field was typed as RTL?

j0k
  • 22,600
  • 28
  • 79
  • 90
Nick Ginanto
  • 31,090
  • 47
  • 134
  • 244
  • there are specific characters in unicode used to indicate the text direction in so called BiDi mode, but is it applicable in your case I don't know. – didierc Dec 05 '12 at 20:41
  • are those characters included in the actual text saved in the textarea? – Nick Ginanto Dec 05 '12 at 20:43
  • I suppose that in most cases, UI force users to use the english alphabet when necessary, and offer specific fields in form for language specific inputs, so that no detection code is necessary. – didierc Dec 05 '12 at 20:44
  • I don't know if inputs handle that. I suppose they do if the input value contains mixed text, but otherwise I cannot tell. – didierc Dec 05 '12 at 20:46
  • you could probably setup an event handler on text change in your textarea which looks for these characters, and test it out if you have a OS supporting BiDi. – didierc Dec 05 '12 at 20:51
  • this means the textarea should be in unicode and not in utf-8 right? – Nick Ginanto Dec 05 '12 at 20:52
  • utf-8 is an instance of unicode, so it should work. – didierc Dec 05 '12 at 20:56
  • see question: http://stackoverflow.com/q/12006095/104380 – vsync Feb 12 '13 at 02:53

3 Answers3

39

I've come up to a more simple and nice solution. Just add dir="auto" to the elements and the browser will do it's job!

See: http://www.w3schools.com/tags/att_global_dir.asp

s3v3n
  • 8,203
  • 5
  • 42
  • 56
12

Try this:

var rtl_rx = /[\u0591-\u07FF]/;
$('textarea').on('keyup',function(){
    this.style.direction = rtl_rx.test(this.value) ? 'rtl' : 'ltr';
});

I used a simplified RegExp to detect RTL

/[\u0591-\u07FF]/

Though it will not catch each and every RTL character in the Unicode table, it probably covers all real life cases. It includes all normal Hebrew and Arabic characters, including vowelization characters.

oriadam
  • 7,747
  • 2
  • 50
  • 48
1

You can write a quick little JavaScript/jQuery code using regular expressions. Regular expressions are limited in JavaScript though, so you will need to use the XRegExp library which has full Unicode support - if you add the plugins. Then you can check the characters to see what block of Unicodes they belong to with expressions like this \p{Hebrew}. http://www.regular-expressions.info/unicode.html

Faced with the same dilemma I wrote myself a function that loops through the characters in each string and counts the number of occurrences of Hebrew characters (my site is bilingual Yiddish/English). Then the string gets a score, and an 'rtl' class is applied to the elements with a high score. You could easily add all of the RTL languages in Unicode to the for loop to make this more generic.

http://jsfiddle.net/Swyu4/9/

Please note the External Resources linking to the XRegExp libraries in the jsfiddle.

$('p').each(function() {
    if(isRTL($(this).text()))
        $(this).addClass('rtl');
});

function isRTL(str) {
    var isHebrew = XRegExp('[\\p{Hebrew}]');
    var isLatin = XRegExp('[\\p{Latin}]');
    var partLatin = 0;
    var partHebrew = 0;
    var rtlIndex = 0;
    var isRTL = false;

    for(i=0;i<str.length;i++){
        if(isLatin.test(str[i]))
            partLatin++;
        if(isHebrew.test(str[i]))
            partHebrew++;
    }
    rtlIndex = partHebrew/(partLatin + partHebrew);
    if(rtlIndex > .5) {
        isRTL = true;
    }
/*
console.log('Latin score: ' + partLatin);
console.log('Hebrew score: ' + partHebrew);
console.log('trlIndex score: ' + rtlIndex);
console.log('isRTL: ' + isRTL);
*/

    return isRTL;
}
Tristan
  • 1,730
  • 3
  • 20
  • 25