PDA

View Full Version : My Unicode(Farsi) editor isn't working in Mozilla!


ConfusedOfLife
04-15-2003, 09:20 AM
Hi

It's a while that I'm working on a program to convert all inputs/textareas of my page into a Farsi editor. Farsi is a lnaugage that is supported in unicode and I should only take the event.keyCode of a pressed key and then print out the unicode equivalent . There were lots of scripts doing this, but my code is different. You should add the parser function in the onload part of your document body, and it finds all the inputs/textareas which use "useFarsi='true", a fancy attribute that I defined myself.

Well, the process is so simple then, any textarea/input that uses that attribute, should convert English to Farsi when the user is typing, and if he/she presses the Ctrl key, it should stop and let him/her type English. Pressing Ctrl again, should result in Farsi characters again. Here it's the code:


<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>

<body onload="easyFarsi();">
<form>
<textarea useFarsi="true" style="width: 400px; height: 200px;"></textarea><br />
</form>
<script>
// The Farsi keys in unicode
var farsikeys = [
0x0020, 0x0021, 0x061B, 0x066B, 0x00A4, 0x066A, 0x060C, 0x06AF,
0x0029, 0x0028, 0x002A, 0x002B, 0x0648, 0x002D, 0x002E, 0x002F,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
0x0038, 0x0039, 0x003A, 0x0643, 0x003E, 0x003D, 0x003C, 0x061F,
0x066C, 0x0624, 0x200C, 0x0698, 0x0649, 0x064D, 0x0625, 0x0623,
0x0622, 0x0651, 0x0629, 0x00BB, 0x00AB, 0x0621, 0x004E, 0x005D,
0x005B, 0x0652, 0x064B, 0x0626, 0x064F, 0x064E, 0x0056, 0x064C,
0x0058, 0x0650, 0x0643, 0x062C, 0x005C, 0x0686, 0x00D7, 0x0640,
0x200D, 0x0634, 0x0630, 0x0632, 0x064A, 0x062B, 0x0628, 0x0644,
0x0627, 0x0647, 0x062A, 0x0646, 0x0645, 0x067E, 0x062F, 0x062E,
0x062D, 0x0636, 0x0642, 0x0633, 0x0641, 0x0639, 0x0631, 0x0635,
0x0637, 0x063A, 0x0638, 0x007D, 0x007C, 0x007B, 0x007E ];

// This function returns an array of all the tagNames in the page
// who have the specified type and name.
function retElementsArray( tagName, type, name )
{
var specTag = new Array();
var counter = 0;


var typeMatch = ( type == "" ) ? ( "true" ) : ( "document.getElementsByTagName(tagName)[i].type.toLowerCase() == type.toLowerCase()");
var nameMatch = ( name == "" ) ? ( "true" ) : ( "document.getElementsByTagName(tagName)[i].name == name" );

for(var i=0; i<document.getElementsByTagName(tagName).length; i++)
if ( eval(document.getElementsByTagName(tagName)[i].getAttribute("useFarsi")) && eval(typeMatch) && eval(nameMatch) )
{
specTag[counter] = document.getElementsByTagName(tagName)[i];
++counter;
}

return specTag;
}


function easyFarsi()
{

var textInputArr = retElementsArray( "input", "text", "" );
var txtAreaArr = retElementsArray( "textarea", "", "" );

var totalElements = textInputArr.concat(txtAreaArr);

for( i in totalElements )
{
// Setting the default language, i.e. Farsi
if ( !totalElements[i].getAttribute("language") )
totalElements[i].setAttribute("language", "far");

// Whenever Alt+Ctrl is pressed, this function is excecuted
// to change the language
totalElements[i].changeLanguage = function()
{
var currentLang = this.getAttribute("language");
var newLang = ( currentLang == "far" ) ? ( "eng" ) : ( "far" );
this.setAttribute("language", newLang);
return true;
}
totalElements[i].onkeydown = function(e)
{
if ( (e||event).ctrlKey )
{
alert("Oopse! You were right!");
this.changeLanguage();
}
}

totalElements[i].onkeypress = function(e)
{
var key = ( window.event ) ? ( window.event.keyCode ) : ( e.which );
if ( key == 13 )
return true;

window.status = red;

// Check if the language is farsi
if ( this.getAttribute("language") == "far" )
{
if ( key == 0x0020 && window.event.shiftKey) // Shift-space -> ZWNJ What's this?
(e||window.event).keyCode = 0x200C;
else
(e||window.event).keyCode = farsikeys[key - 0x0020];

// This is for J key in Farsi! Like J in Bijan!!
if (farsikeys[key - 0x0020] == 92)
window.event.keyCode = 0x0698;
// This one is for P in Farsi! Better to say the ~ key under the ESC button!
if (farsikeys[key - 0x0020] == 8205)
{
window.event.keyCode = 0x067E;
}
}

return true;
}
}
}
</script>

</body>
<html>


If you test it in IE you see that it doesn't have any problem. You can have as many textareas/inputs as you want, and it'll work for all of them. The only problem is when I test it in Mozilla, I see that by pressing the Ctrl key, nothing happens! It means it doesn't change the language. I narrowed the problem down to this code ( the real program is really more than what I typed in here!) and I hope you can help me. I commented all the necessary function/lines and I hope you can help me find the problem.

Thank you in advance,
bijan

glenngv
04-15-2003, 09:48 AM
maybe this link would help

http://www.webreference.com/js/column11/modifierkeys.html

ConfusedOfLife
04-15-2003, 12:31 PM
Thank you glenn, you're right, it wasn't working. But as I said this is not the whole code I'm posting in here and it's just a sample of what I am doing, so, I just mis-wrote it and now if you look at the code, you see that in the onkeydown function some red lines are added that fixed this. Actually I had this problem and liorean helped me by giving me this address:

http://www.din.or.jp/~hagi3/JavaScript/JSTips/Mozilla/Samples/KeyEvent.htm

It's no thing wrong with the event controlling and you can test it by alerting something in the onkeydown function. I got a very simple script a while ago that could only turn one textarea/text input into a Farsi editor. I only tried to make it OO and now that I'm finished I see that even that first simple script doesn't work in Mozilla. It's not because the pressed key isn't recognized, no, but when you're typing Farsi and then you press Ctrl, you see that it still types Farsi, it seems that it can't use English in the middle of Farsi! If you test it in Moz, you see the same thing! In the other hand, when you go to another line and press Ctrl, you see that it can change the language. Of course this behaviour isn't seen every time and it makes me think that maybe Moz can not handle it.

Do you know of any script that changes an input into a unicode editor and it also works in Moz? Not important what language, just unicode.

liorean
04-23-2003, 04:57 PM
Is the language attribute what you really want? It's only valid on script elements. Isn't lang the attribute you should be changing?

[HTML4] 8.1 Specifying the language of content: the lang attribute (http://www.w3.org/TR/html4/struct/dirlang.html#adef-lang)

jkd
04-23-2003, 05:26 PM
I'm not going to claim that I've done anything more than glance at the code, but I did notice you're not passing the event object in this line:

totalElements[i].onkeypress = function()

Yet you are referring to e.which inside the function body.

ConfusedOfLife
04-24-2003, 08:54 AM
Hi

Welcome back liorean! As for as using the "lang" attribute, well, it's just a fancy thing and to be honest, coz I didn't know much about it and I thought it might make some conflicts in some computers, I didn't use it. But now that you sent me that address, I figured out that well, it really doesn't make much difference! Of course it's easier to use it and I don't need to use "getAttribute('language')" any more and can directly get the lang attribute, but well, it doesn't solve my current problem!

About putting that e in the onkeypress, I added that and it still doesn't work. I changed the above code and if you look at it now you see that "e" is added in red. Also you see some green lines in the onkeypress which I thought might be the cause of my problem, but nothing happend when I changed them!

Is it really impossible to have the same functionality in Moz too? I have no problem in IE and I'm sure that the language attribute is working fine, because I set the window.status to show the current language when I type, and I saw that it shows the right language, ie. when I press CTRL the language is changed. So, whatever is wrong, it's with the onkeypress that I unfortunately do not have enough experience to correct myself, my knowledge about cross browser compatibility is zero, I confess!

Thanks for your help
bijan

glenngv
04-24-2003, 09:51 AM
modifier keys such as ALT and SHIFT are not captured on onkeypress event only on onkeydown

liorean
04-24-2003, 02:36 PM
Hmm...var key = ( window.event ) ? ( window.event.keyCode ) : ( e.which );
Doesn't the following work? var key=(e||event).keyCode

if ( key == 0x0020 && window.event.shiftKey)
I think the above should be written as if ( key == 0x0020 && window.event && window.event.shiftKey)
It'll be false for Mozilla, so this is the mozilla code that will be executed:window.event.keyCode = farsikeys[key - 0x0020];
But, since window.event won't exist, that should throw an error. Try e.keyCode = farsikeys[key - 0x0020]; instead. I wouldn't be surprised if you found it not working, though: from http://unstable.elemental.com/mozilla/build/latest/mozilla/dom/dox/interfacensIDOMKeyEvent.html#m115:
readonly attribute unsigned long nsIDOMKeyEvent::keyCode
and for which readonly attribute unsigned long nsIDOMNSUIEvent::which

beetle
04-24-2003, 03:00 PM
Shouldn't a page using Farsi be UTF-8 encoded?

Just a thought.

ConfusedOfLife
04-24-2003, 11:55 PM
Originally posted by glenngv
modifier keys such as ALT and SHIFT are not captured on onkeypress event only on onkeydown

I'm not capturing them on onkeypress, I do it in onkeydown and change the language attribute, later on in onkeypress I check the language attribute and make decisions based on that!

ConfusedOfLife
04-24-2003, 11:59 PM
Originally posted by beetle
Shouldn't a page using Farsi be UTF-8 encoded?

Just a thought.

You're right beetle, it should be UTF-8 encoded, but for showing the characters in normal page. Using a input/textarea doesn't require this, even though we normally have it in the page because we're showing Farsi text as well and it might cause some problems if we try to capture it via a server side language. But in here, it doesn't make any difference as you see. Besides if it had any problem, it showed itself in not displaying correct Farsi characters and putting some unread code in there, not putting English characters instead!

ConfusedOfLife
04-25-2003, 12:09 AM
Liorean, the answer to your first question:


Doesn't the following work?

var key=(e||event).keyCode



I added this line to the onkeypress event handler, exactly after the condition that checks if key==13,


window.status = key;


And then I changed that line with your suggestion, it works in IE, but in Mozilla, I wasn't lucky!

For your 2nd suggestion, I changed it in the above code and you can see it in red.

Your 3rd suggestion is better written as:

(e||window.event).keyCode = farsikeys[key - 0x0020];


I tried it, but nothing has changed!

I made the new changes in the code above and it is in red, so, you can easily see it!

Thank you all for your help, you are very kind to me!
bijan

liorean
04-25-2003, 12:44 AM
Have you considered the possibility of determining the language, adding the correct character dependingon that, and returning false on the keypress in Mozilla? Since which, keyCode and charCode are all readonly in Mozilla according to unstable.elemental.com, that is the only way of doing it that I can think of that should work.

jkd
04-25-2003, 01:55 AM
Originally posted by liorean
Have you considered the possibility of determining the language, adding the correct character dependingon that, and returning false on the keypress in Mozilla? Since which, keyCode and charCode are all readonly in Mozilla according to unstable.elemental.com, that is the only way of doing it that I can think of that should work.

You can cancel the event, then dynamically create a new one using createEvent() with whatever keyCode you want, and dispatchEvent() on the textarea.

jkd
04-25-2003, 03:11 AM
Might as well provide an example. Note: KeyEvent is Gecko-proprietary - DOM3 describes a TextEvent, but it isn't implemented anywhere as DOM3 Events is still in working draft (Moz's KeyEvent interface is very similar though).


document.onkeydown = function(event) {
if (someConditionsAboutEvent) {
// cancel the event first
event.preventDefault();
event.stopPropagation();

// create and init a new event
var newEvent = document.createEvent("KeyEvent");
newEvent.initKeyEvent("keydown", true, true, document.defaultView, event.ctrlKey, event.altKey, event.shiftKey, event.metaKey, newKeyCode, newCharCode);

// dispatch new event in old event's place
event.target.dispatchEvent(newEvent);
}
}


Not tested, but I'm pretty sure that would work.

glenngv
04-25-2003, 03:57 AM
Originally posted by ConfusedOfLife
I'm not capturing them on onkeypress, I do it in onkeydown and change the language attribute, later on in onkeypress I check the language attribute and make decisions based on that!

but you have this onkeypress:

if ( key == 0x0020 && window.event.shiftKey) // Shift-space -> ZWNJ What's this?
(e||window.event).keyCode = 0x200C;
else
...

which wouldn't be executed on IE at all.

ConfusedOfLife
04-26-2003, 07:57 AM
Wait a minute! I'm not sure if I coult get ya. You mean I can't change the keyCode because it's read only and I have to make a new event instead? And of course kill the default one, huh?

Well, it means that I have to forget about the onkeypresss totally and do what I wana do in onkeydown, right?

I updated my onkeydown and deleted the onkeypress, but it still doesn't work! It's the new onkeydown that I wrote(Everything is the same as the code posted in the first post, only the onkeydown has changed and onkeypress is purged!)


totalElements[i].onkeydown = function(e)
{
if ( (e||event).ctrlKey )
{
//alert("Oopse! You were right!");
this.changeLanguage();
}

if ( this.getAttribute("language") == "far" )
{
var key = ( window.event ) ? ( window.event.keyCode ) : ( e.which );
window.status = key;

// cancel the event first
(e||event).preventDefault();
(e||event).stopPropagation();

// create and init a new event
var newEvent = document.createEvent("KeyEvent");
newEvent.initKeyEvent("keydown", true, true, document.defaultView, event.ctrlKey, event.altKey, event.shiftKey, event.metaKey, farsikeys[key - 0x0020], farsikeys[key - 0x0020]);

// dispatch new event in old event's place
(e||event).this.dispatchEvent(newEvent);
}

}


I couldn't understand what I should write for the newKeyCode and newCharCode. I only need a newKeyCode, what's that newCharCode in here?! Because I didn't know, I put the same thing for both of them. :o

Dear glen, you're right. Actually this code that you're seeing was only 10 or 15 lines and it was written to change one input/textarea to a Farsi editor. So, when I got the code, I decided to write it OO that we can initiate it for all the elements of the page. And also what I posted here is not my complete code, my real program does LOTS of other things too! So, the onkeypress isn't originally written by me and I didn't notice that line, you're right. It'll never get excecuted and I delete it from my script.

Thank you all,
bijan

liorean
04-26-2003, 02:47 PM
No, I don't think that's your best way of doing it.

First of all, one keydown or keyup can correspond to multiple keypress due to the fact that we have an OS feature of keypress repetition when a key is held down. Second, the keypress is the action that actually enters a letter.

So, keydown (or keyup) testing for character 0x0011 to toggle Farsi/English because keypress doesn't handle some nonprintable keys.

On the other hand, use keypress for overriding the user input. Return true if language is Farsi or the pressed key is any special key not in the set (shift, ctrl, alt, meta) such as delete, insert, home, end, esc, etc..

Now, this here is what get's tricky:
IE uses only shiftKey and keyCode (which contains the character to insert in the document - not the actual key code - for printable characters) for all keys - you will have to filter the keys (or easiest, fork off to use the code you had from the beginning). Mozilla on the other hand is quite helpful - it uses keyCode only for nonprintables and charCode for what character to insert into the document modified and all. That means mozilla makes it easy to determine whether to cancel the keypress or not: if charCode is 0, return true. If keyCode is 0, add the correct character to e.target.value and return false.

Well, that's the theory, at least...

liorean
04-26-2003, 02:52 PM
The difference between keyCode and charCode is that charCode is the modified key code (a and A have different character codes) while keyCode is the original key code (capital letter for alpha printables)

jkd
04-26-2003, 06:37 PM
Originally posted by ConfusedOfLife
Wait a minute! I'm not sure if I coult get ya. You mean I can't change the keyCode because it's read only and I have to make a new event instead? And of course kill the default one, huh?


It appears you do get me. Alternatively, you could just += the textarea value with the correct letter instead of firing a new event... but I think firing the new event is more robust (don't have to worry about selections, caret positioning, etc).

As for it not working, look at your arguments:

event.ctrlKey, event.shiftKey, etc.

In my function snippet, I passed the event argument around as "event" - in yours you passed it around as "e". You're calling properties on an undefined object, that be bad. Change "event" to "e" in those arguments and you should be in business.

jkd
04-26-2003, 06:41 PM
You also seem to think IE has DOM2 Events support (as well as support for Gecko's KeyEvent).

Ha, yeah, I wish. IE does not have preventDefault(), stopPropagation(), createEvent(), initKeyEvent(), dispatchEvent(), etc.

Do a browser check, and modify event.keyCode for IE, and fire the new event for Mozilla. No need for the short circuit evaluation on the event object, as if the browser is IE, it'll get all confused when it sees standard DOM scripting.

Also, what's this?
(e||event).this.dispatchEvent(newEvent);

There is no "this" property on the event object. use "e.target.dispatchEvent()", like I did in the example.

ConfusedOfLife
04-27-2003, 05:41 AM
Thanks! You're cool!

I'll have a closer look at it when I come back from the damn University. Now I have to go, but I'll let you know what happend in my long journey!

Thanks for staying with me in these terrible hours!
bijan

ConfusedOfLife
04-28-2003, 12:07 PM
Originally posted by liorean:

if charCode is 0, return true. If keyCode is 0, add the correct character to e.target.value and return false.





Originally posted by jkd:


In my function snippet, I passed the event argument around as "event" - in yours you passed it around as "e". You're calling properties on an undefined object, that be bad. Change "event" to "e" in those arguments and you should be in business...

There is no "this" property on the event object. use "e.target.dispatchEvent()", like I did in the example.



I know that you think I'm stupid or something (in that case you're right!), but I made the changes that you said, and I came up with this:

totalElements[i].onkeydown = function(e)
{
if ( e.ctrlKey )
{
alert("Oopse! You were right!");
this.changeLanguage();
}


// cancel the event first
e.preventDefault();
e.stopPropagation();

// create and init a new event
var newEvent = document.createEvent("KeyEvent");
newEvent.initKeyEvent("keydown", true, true, document.defaultView, event.ctrlKey, event.altKey, event.shiftKey, event.metaKey, farsikeys[key - 0x0020], 0);

// dispatch new event in old event's place
e.target.dispatchEvent(newEvent);
}


As you see I removed those short circutes, I'm only using "e" and not "event", and I removed "this", and I put 0 for newCharCode ( I also tried the reverse case, putting 0 for newKeyCode), but it still doesn't work! Lemme be honest with you, I don't like ppl who only ask and don't try anything themselves, i.e. they don't study. But I really do not have time to work on these new Mozilla things (new to me of course) and I don't wana lie to anyone. I just do what you tell me, not going for it myself, coz I really don't have time. If you think that it's quite impossible for me to correct the code, then I simply accept it. I really apperciate all the time that you put for answering me and I wish I can pay off one day!

Regards,
bijan

liorean
04-28-2003, 01:40 PM
Hmm, let's see how well this works.

// Make life easier for you...
// Note that if these breaks something else,
// replace uses of them with their expansions.
Object.prototype.hasProperty=function(sProperty){
return (typeof this[sProperty]!='undefined'?true:false);
}

Object.prototype.getProperty=function(sProperty){
return (this.hasProperty(sProperty)&&this[sProperty]);
}

Object.prototype.getMethod=function(sMethod){
return (this.getProperty(sMethod) instanceof Function?
this[sMethod]:
function(){});
}

// Your code, modified. I hope this works now.
totalElements[i].onkeydown=function(e){
if (e.ctrlKey&&(e.keyCode==0x11||e.keyCode==57390))
this.changeLanguage();
}

// I decided to split it and use keypress anyway.
// This way you should be able to catch each time
// a character is entered, not only when a key is
// pressed.
totalElements[i].onkeypress=function(e){
if(this.getAttribute('language')!='en')
return true;
var
key=e.keyCode||e.charCode;
if(typeof window.event!='undefined'){
e.keyCode=farsikeys[key-0x0020];
return true;
}
if(e.charCode>0){
// Cancel the event first
e.getMethod('preventDefault')();
e.getMethod('stopPropagation')();
// Create and init a new event
var
newEvent=document.createEvent('KeyEvent');
newEvent.initKeyEvent('keypress', true, true,
this.ownerDocument.defaultView, e.getProperty('ctrlKey'),
e.getProperty('altKey'), e.getProperty('shiftKey'),
e.getProperty('metaKey'), 0, farsikeys[key-0x0020]);
// Dispatch new event in old event's place
this.dispatchEvent(newEvent);
return false;
}
return true;
}

ConfusedOfLife
04-30-2003, 03:09 PM
Thank you liorean, I'll test your code. I'm upgrading my PC and it's about some days that I don't have my comp at home. I'll let you know what happend as soon as I get my puter back. Thanks for your help anyway.