execCommand insertHTML inserting multiple times - contenteditable

I am working on a small RTE in a contentEditable DIV. I have attached a keypress event handler to the DIV that monitors when the ENTER key is struck and where the selection is. If it is inside a text node, I am inserting a new line. However, this code is buggy and often inserts 4 newlines instead of one (I have to press undo 4 times to get back to where the cursor was before - that's why I think execCommand is firing multiple times). On the other hand, it sometimes requires TWO strikes of the ENTER key to get a new line inserted.
here is a code snippet of the keypress event handler, once it's determined that the ENTER key has been pressed:
if(selection.focusNode.nodeType!=3){ return; }
ev.preventDefault();
var HTML='
';
toolbar.target.ownerDocument.execCommand('insertHTML',false,HTML);
I want to use execCommand to preserve the browser's undo behavior. I do NOT want to insert a <br> as this insertion only happens in a text node and for post-processing purposes, I need \n in the text nodes instead of <br>'s or any other block-type tags. I am using the unicode newline character
. I have tried the carriage return character 
 as well with similar results. I can't use \n with insertHTML because that is not proper HTML.
Anyone have ideas about how to make sure that execCommand runs ONLY once?

Related

What're the key codes for "Alt+Q Alt+Q"?

I want to create a script that triggers when pressing Q twice while holding Alt, but couldn't figure out what're the correct key codes for that, could someone please shed some light?
P.S. I want to bind this shortcut to Ctrl+F12, which I assigned Sogou IME to turn on the Chinese input mode.
I didn't test this and there's probably a more concise way to do it, but I think something like this should work.
!Q::
If(keyPressed = 1){
...Do a thing...
}
keyPressed := 1
SetTimer, altQTimer, 50
return
altQTimer:
keyPressed := 0
return
TL;DR
In conclusion, even if I do all kinds of hacks and get the script working as intended, it's likely to break in the future, which is really not worth the trouble.
After hours of experimenting, the current conclusion is Sogou IME which uses Ctrl+F12 won't trigger the bound action i.e. switching to the Chinese input mode if it was sent by Alt+[Any Other Key], it can be triggered if it was sent by other shortcuts such as Ctrl+C, which is really unfortunate.
And the weirdest thing is the following code works:
^c::Send !q
!q::Send ^{F12}
And to rule out the potential extra simulated keystrokes (Ctrl by default) effect, the following code also works:
^!q::Send ^{F12}
But the following doesn't (tested on several machines):
!q::Send ^{F12}
Update
After much effort, I did get Alt+Q to turn on the Chinese input mode with the following code, not sure why:
!q::Send ^{F6}
^F6::Send ^{F7}
^F7::Send ^{F12}
But because I also need to trigger a VSCode command using Alt+Q at the same time, I had to modify the above code to the following:
~!q::Send ^{F6} ; with ~ prefixed
^F6::Send ^{F7}
^F7::Send ^{F12}
Now Alt+Q does trigger the VSCode command, but it won't turn on the Chinese input mode...
At last, if I take a step back and bind the VSCode command to Ctrl+C (which could turn on the Chinese input mode with just ^c::Send ^{F12}), I still have to prefix ^c with ~, otherwise it won't trigger the VSCode command, now I'm repeating the cycle all over again...
After all of these attempts, I have to say Sogou IME's logic for determining whether to enable the Chinese input mode is quite indeterminate, making the script for enabling the Chinese input mode very unreliable.
In conclusion, even if I do all kinds of hacks and get the script working as intended, it's likely to break in the future, which is really not worth the trouble.

What is the best practice to simulate an ENTER or RETURN using Selenium WebDriver

I came across this solution to my initial problem, which was to simulate an ENTER or RETURN key press using Selenium WebDriver.
However, in my code, I strictly want to use only one of the two WebElement.sendKeys(Keys.ENTER); vs WebElement.sendKeys(Keys.RETURN);.
What is the best practice when doing the same, since there seems to be divided opinion about using enter or return, since both work MOST of the time? In what scenarios would one or the other not work, and is there one which would ALWAYS work?
As a performancewise I do not get any change on both of these,
But yes I know one difference on them
Keys.Enter is used to enter key on the number pad
while
Keys.Return is used to one next to the letters
Generally I have preferred Keys.Enteras sometimes in some browser Keys.Return is not worked for me
Let us analyze Keys.ENTER and Keys.RETURN in details.
Keys.ENTER and Keys.RETURN both are from org.openqa.selenium.Keys, which extends java.lang.Enum<Keys> and implements java.lang.CharSequence
Enum Keys :
Enum Keys is the representations of pressable keys that aren't text. These are stored in the Unicode PUA (Private Use Area) code points, 0xE000-0xF8FF.
Key Codes :
The special keys codes for them are as follows :
RETURN = u'\ue006'
ENTER = u'\ue007'
The implementation of all the Enum Keys are handled the same way.
Hence there is No Functional or Operational difference while working with either sendKeys(Keys.ENTER); or WebElement.sendKeys(Keys.RETURN); through Selenium.
Enter Key and Return Key :
On computer keyboards, the Enter (or the Return on Mac OSX) in most cases causes a command line, window form, or dialog box to operate its default function. This is typically to finish an "entry" and begin the desired process, and is usually an alternative to pressing an OK button.
The Return is often also referred as the Enter and they usually perform identical functions; however in some particular applications (mainly page layout) Return operates specifically like the Carriage Return key from which it originates. In contrast, the Enter is commonly labelled with its name in plain text on generic PC keyboards.
Wiki References : Enter Key Carriage Return
As yourself, I failed to find a good explanation to this question online so I tested it myself using this Keyboard Events tester.
driver.get("https://dvcs.w3.org/hg/d4e/raw-file/tip/key-event-test.html");
WebElement textArea = driver.findElement(By.id("input"));
textArea.sendKeys(Keys.ENTER);
textArea.sendKeys(Keys.RETURN);
As a result I've got this output (this is Keys.ENTER followed by Keys.RETURN):
So it seems like there is no difference between these two options.

Autohotkey - AltGr hotkey behaves differently from LAlt hotkey

I'm trying to map LAlt+Space to Delete and AltGr+Space to Backspace, so i made this script :
<!Space::Delete
<^>!Space::Backspace
LAlt+Space gets mapped correctly to Delete, but AltGr+Space doesn't work properly : it removes words like Ctrl+Backspace would do instead of removing one character at a time.
I switched 'Delete' and 'Backspace' and got the same issue : LAlt+Space works properly but AltGr+Space removes words like Ctrl+Delete instead of characters.
I'm guessing this might have to do with the fact that AltGr is actually Ctrl+RAlt, so the Ctrl might be composed with Backspace or Delete at some point ?
Does anybody know what the cause of this could be, and a solution ?
While #user3419297's answer is essentially correct, it's advisable in modern versions of AHK to use SendInput over Send.
<!Space::
SendInput, {Delete}
return
<^>!Space::
SendInput, {Backspace}
return

Android WebDriver not able to enter alphanumeric character

I am trying to automate a mobile website on android device, using Android WebDriver library.
When the script enters some alphanumeric characters , eg Test12345, in a text field the textbox shows "TEST!##$%" as entered text. It is true for any alphanumeric word starting with capital letter.
But, if I make the first character a SMALL character or a number then correct word is inserted.
Here is the code which I am using (same scenario happens on any textbox field)
driver.get("http://www.google.com");
WebElement searchBox = driver.findElement(By.name("q"));
searchBox.sendKeys("Test12345");
Is it a bug or am I missing something?
It seems that this is a bug. As a workaround you can type any (except NULL U+E000 or "\xEE\x80\x80" in UTF-8) character before your string. E.g. you can start typing with sending two SHIFT (U+E008 or "\xEE\x80\x88" in UTF-8) characters, or one CLEAR (U+E005 or "\xEE\x80\x85" in UTF-8) character. Just anything unprintable, and after that type your string.
FYI: I've confirmed the bug still exists. I'm looking at the android webdriver code to see if I can fathom out why it's occurring. I have some ideas, it's likely to be in one or other of:
java/client/src/org/openqa/selenium/android/library/AndroidKeys.java
java/client/src/org/openqa/selenium/android/library/EventSender.java
java/client/src/org/openqa/selenium/Keys.java
and related to mapping keys between Selenium-Webdriver and Android.
I have found another workaround, similar to the one mentioned by Ivan. Mine involves splitting the text into 2 parts, the first capitalized character e.g. the T and use sendKeys to send it; then send the rest of the text e.g. est12345
searchBox.sendKeys("T");
searchBox.sendKeys("est12345");
Ugly, shouldn't be necessary, but a practical option that doesn't involve sending extra (unprintable) characters.

target.frontMostApp().keyboard() failed to locate key 'N'

I'm trying to automate keyboard typing with UI Automation.
target.frontMostApp().keyboard().typeString("INTERCOM")
But i will get this error after first 'I' is typed
target.frontMostApp().keyboard() failed to locate key 'N'
Script threw an uncaught JavaScript error: target.frontMostApp().keyboard() failed to locate key 'N'
I have a localized swedish keyboard.
Anyone know if this a bug or something I've missed?
This might help:
var vKeyboard = target.frontMostApp().keyboard();
vKeyboard.setInterKeyDelay(0.1);
vKeyboard.typeString("INTERCOM");
By default this delay is set with 0.03 seconds. This is not enough for your application to update the keys on your keyboard. Increasing this timeout between determining keys for typeString keyboard method will help you. There is no description for setInterKeyDelay on UIAKeyboard reference page but this method is available for UIAKeyboard.
Also I'm not sure about other languages. I do not know if typeString allows to type on other languages but this 100% works for English keyboard for iOS 5.x.
try{
target.delay(1);
target.frontMostApp().mainWindow().textFields()[0].tap();
target.delay(1);
target.frontMostApp().mainWindow().textFields()[0].setValue("INTERCOM");
}
catch(err){
target.delay(1);
target.frontMostApp().mainWindow().scrollViews()[0].textFields()[0].tap();
target.delay(1);
target.frontMostApp().mainWindow().scrollViews()[0].textFields()[0].setValue("INTERCOM");
}
I've had this problem as well and I believe it's a case of the string being typed too quickly.
It seems that the names of the key,change depending on the status of the shift button.If shift is enabled then the key is called 'N',if shift is not enabled then it's 'n'.You'll notice as a string is being typed,that the shift button is tapped before an uppercase letter is typed.Your test is attempting to press the 'N' key before the 'Shift' button has been pressed.It doesn't affect the first letter of your sentence because the keyboard has shift enabled for the first letter.
This also affects typing a lowercase character after an uppercase character:the lowercase character may be typed whilst the shift button is in the process of being unpressed.
I use a workaround of typing each letter of the string with separate typeString() methods.
for (i = 0; i < title.length; i++)
{
var strChar = title.charAt(i);
target.frontMostApp().keyboard().typeString(strChar);
}
The downside to this is that it takes a lot longer to type the full string.
You may also want to look at the following link which provides a similar solution but uses the app.keyboard().keys().tap() method for each character of the string instead of the typeString() method.
http://jojitsoriano.wordpress.com/2011/06/27/ios-ui-automation-typing-a-string-in-a-uiatextfield/