So (just to start with "so") I want to create a greasemonkey script for a qwebirc platform. I need to send replies automatically based on some events that happen. For those who don't know, once logged in the qwebirc, there is an input text field at the bottom of the screen where you can write your reply and then, by pressing enter, the reply is sent to the server. The input field is contained in a form element, but the form has no submit button.
I can populate the input field (no problem) by writing to its "value" attribute, but I found no way to "submit" the reply to the server. I tried calling the .submit() method on the container form element, but that simply reloads the page (so it's sending to itself - and that makes sense, 'cause there's no "action" attribute on the form element). It seems to me that the only explanation is that once the enter key is pressed in the input field there's a method that's called somewhere on the qwebirc.js.
I can't find the code responsible for this action (though I worked that in Chrome, I set an Event Listener Breakpoint on the Keyboard - Input, and that stopped me when I pressed the enter key and pointed me to the beginning of some function) because the script is minified and there's no way for me to know what those "m", "n", "p", "t" etc mean. If I had the uncompressed version, I could scan it and, maybe, find it out. I also tried downloading the qwebirc project, but there are loads of files there - whereas on the server I'm trying to write the greasemonkey script there's a single script.
The main idea here is that I guess the enter key press simulation should trigger the sending function - wherever and whichever that may be.
In order to do this I found on stackoverflow some questions with the same subject - the simulation of enter key press. I tried that code:
function simulate() {
var evt = document.createEvent('KeyboardEvent'),
input = document.querySelector('.keyboard-input');
evt.initKeyboardEvent(
'keydown',
true,
true,
window,
false,
false,
false,
false,
13,
0
);
input.dispatchEvent(evt);
}
The event is created (I can see it in my DOM panel in FireBug), but no action whatsoever is taken. I mean why doesn't the .dispatchEvent() behave just like a real enter key press ?
Thanks in advance.
For the purposes of this answer, I'm going to assume that the message input pseudo-form is like others - i.e. the message can be sent by either pressing Enter or clicking a Send button.
You've tried the former; it didn't work. It's possible that the page is waiting for the Send button to be clicked (which may be triggered by an Enter keypress (though no, I don't know why your event isn't working - I'm unfamiliar with event intricacies)). Instead, then, try that.
Also, take note: IE uses fireEvent not dispatchEvent - so if you're in IE, this may be the problem.
To fire a click on the Send button:
var e = document.createEvent("MouseEvents");
e.initEvent("click", true, true);
e.target = "button#send";
if(document.fireEvent) {
document.fireEvent(e);
}
else {
document.dispatchEvent(e);
}
Change the string assigned to e.target to the CSS selector that uniquely identifies the Send button.
Related
Scenario:
I have a RadCombobox and I have attached functions to most of the events.
One event of the combobox is OnClientBlur and I am using this to check whether value in Combo is "Unassigned" or not. If it is "Unassigned" I need to cancel the onblur event and keep the focus on to the same combo.
This is the javascript which I has been used to cancel the event.
if (sender.get_text() === "Unassigned") {
eventArgs.get_domEvent().preventDefault();
return false;
}
Problem:
When the user tabs out first time of the ComboBox the event gets cancelled and the focus stays on the same combo box (in this case it is the 3rd Combo).
But when the user hits the tab button again the focus moves to the next control.
When I debugged the code I found that when the user first hits the tab button, following line works
eventArgs.get_domEvent().preventDefault();
I can see the preventDefault function, see following snapshot.
but when the user hits the tab button again I get an error and cannot see preventDefault function, see following snapshot
I am not able to understand what is going wrong here. Anyhelp would be appreciated.
Your problem, revolves around the difference between MouseEvents and KeyEvents. And also the way Telerik implement the OnClientBlur event. As far as it doesn't point to a specific type of browser event, each time it gets triggered
As you see in the first snapshot you got clientX and clientY, which means your OnClientBlur derived from a MouseEvent.
Whereas in the second one you got altKey, altLeft, and also there is no button property, which means that this one is a KeyEvent.
The other point here is as you have these fields in the output:
e.bookmarks
e.behaviorPart
e.behaviorCookie
Means you are using one of the old versions of IE4+ to IE7 or IE8, which they have cancelBubble instead of preventDefault.
Sometimes events are not cancelable, and using event.cancelable you can make sure if the current event is cancelable or not.
At the end to fix you code you can simply do this:
if (sender.get_text() === "Unassigned") {
var domEvent = eventArgs.get_domEvent();
if(domEvent.cancelable){
if(typeof(domEvent.preventDefault)==="function")
domEvent.preventDefault();
else
domEvent.cancelBubble = true;
return false;
}
else{
//you can not cancel the event, do something else to make it manageable
}
}
I have a text field which will accepts only numbers. When the user types any characters and moves out of the textfield,
using onchange I am checking whether user have entered Number or characters. So when user press tab , using onchange the value is checked.
When the user press Enter button, it is set as window.event.keycode =9; as IE supports this. To make it work in other browsers,
I have written logic to move the focus whenever the user presses the enter button.
The problem which I am facing is in Firefox, when the user presses enter button in the text field, now onchange is called as well as onsubmit is also called, which makes my page to refresh again.
The logic which I have written to move the focus to next item , is also working. But I don't know why, onchange and onsubmit is called.
This project composes of huge amount of code, thats why I am not able to post a piece of code.
Any idea why it is working like this?
Some browsers have a global event object, other send the event object to the event handler as a parameter. Chrome and Internet Exlporer uses the former, Firefox uses the latter.
Some browsers use keyCode, others use charCode.
Enter key code is 13
function Numberonly() {
var reg = /^((\d{1,8}(\.\d{0,5})?%)|(\d{1,8}(\.\d{0,5})?))$/;
if (!reg.test(($("#txtunitId").val()))) {
$("#txtunitId").val('');
return false;
}
}
<input type="text" id="txtunitId" style="float: left;" onkeyup="Numberonly();" />
jsfiddle.net/hQ86t/20
How can I go about detecting if the file input dialog is currently open?
I'm trying to integrate some file upload functionality into a popup (bootstrap style) model on a web app I'm building. As part of the model's behaviour, if escape is pressed, the model is closed.
This is all good till I open a file input dialog from the open model, if I hit escape to close the input dialog, it'll also close the model.
A super simplified version of what I'm trying to achieve
http://jsfiddle.net/ckevy/1/
Try solving it like this:
When a user clicks on the file selection input, give it focus: $(el).focus().
Then, anytime a user hits ESC, look if the $(':focus') element is the file selection input. In that case, blur() that input and do not close the modal. Worst case – the user wants to close the modal, presses ESC and nothing happens [1]. Thinks "wtf", presses ESC again and modal closes as it should. Just make sure that the file selection input does get focus in all possible cases – tabbing through inputs, etc. If you use a third party uploader and what I've said doesn't work – look into how that uploader wraps the file selection in a custom link or button, and what actually receives the click event in different cases (e.g. when you tab, the input might receive the event, when you click, it could be the link). Overall, it's manageable to have this working with the caveat I've described.
This works with expanded -s too similarly (just check that a select is not focused when ESC is hit).
You won't be able to detect all the cases when you need to blur() the file selection input. It's not a cross-browser solution. Even FF needs adjustments to work. I've been testing on webkit with positive results, in other browsers it might not work.
In my case works this code on jQuery:
// esc must close popup
$("body").keyup(function(e) {
if (27 == e.keyCode) {
hidepopup();
}
});
// input in popup
var $file = $("input:file");
// keyup will be catched for input, not for body
$file.bind("click", function(e) {
$(this).focus();
});
// keyup catching will be changed back to body after selecting file
$file.bind("change", function(e) {
$(this).blur();
});
// we catched esc keyup, so change esc catching back to the body
$file.keyup(function(e) {
if (27 == e.keyCode) {
$(this).blur();
// i don't know, why it works with return false, because i am not js programmer ), but cancelBubble or e.preventDefault is not working
return false;
}
});
I do not believe you actually have direct control over the dialog itself. In some browsers such as FF people have been able to manipulate the dialog to an extent but this does not apply to all browsers and all browser versions.
The easiest way to do this is to disable the shortcut key on the model dialog before opening the file window.
Based on Nikita's answer. If you check for focus on the input field before firing your code it solves the issue:
$('input[type="file"]').on('keydown',function(e){
//Prevents code from firing if file browser is open
if($(this).is(':focus')){
//run code here that should only be applied when the dialog box is closed
}
});
Ok, so we all know that onChange is used to execute javascript code on a select statement when the option changes. However, if you change a select statement using the arrow keys, the onChange event is not called. Is there a way around this? Please help! I'm OCD I know.
--EDIT 1--
Just tested this in IE and arrow keys do work. Apparently it's just Chrome. ** Goes to check firefox
-- Edit 2 --
Tested in Firefox and realized just before an answer below talked about the onBlur action being required for the change. So the answer here is:
Internet Explorer recognizes onChange events from the keyboard as well as clicking on them.
Firefox and Chrome both require key events to be followed by blur event in order to call onChange.
Now normally, I don't like Internet Explorer, because it's a piece of garbage... But I think I... unfortunately, have to say they got that one right.
My understanding as to the reasoning for the blur event on chrome and firefox is to save resources, but I disagree with that. I feel it should follow the literal interpretation of the command onChange... Sigh... I suppose I'm probably wrong somehow, though.
I would suggest you to write the required code in Key Up event to capture the Key press and and also check for Key Code. Hope this helps
Scrolling through a select box is not considered a change. The change happens when you blur() the select and the new option value is applied to the select element.
Coming back to this, it appears that since the asking of this question, Chrome now fires onChange after key events. Firefox appears to still wait for onblur. http://jsfiddle.net/2aQBN/
$(document).ready(function() {
$("#test").on("change", function() {
console.log("Changed.");
});
});
W3C Specification appears to suggest using an input event instead.
When the input event applies, any time the user causes the element's
value to change, the user agent must queue a task to fire a simple
event that bubbles named input at the input element.
However, no input event appears to fire in Chrome or Firefox for the select element. (Just input elements.)
Test demonstrating the current value vs the last onchange value.
http://jsfiddle.net/teynon/MpyHK/5/
Firefox will change the value onmouseover. The key change will change the value as well. However, the onchange hasn't fired. If the form submits while the user has the select menu open, the currently highlighted option is submitted.
From W3C:
If the multiple attribute is absent, and the element is not disabled,
then the user agent should allow the user to pick an option element in
its list of options that is itself not disabled. Upon this option
element being picked (either through a click, or through unfocusing
the element after changing its value, or through a menu command, or
through any other mechanism), and before the relevant user interaction
event is queued (e.g. before the click event), the user agent must set
the selectedness of the picked option element to true and then queue a
task to fire a simple event that bubbles named change at the select
element, using the user interaction task source as the task source.
There is a LONG discussion at https://bugzilla.mozilla.org/show_bug.cgi?id=126379 about this with many people asking for the arrow keys to work. (And some defending the onchange approach.)
Some users have suggested that the W3C is flat out wrong in the specification for the select element's change event. Instead suggesting we propose changes to the specification for how we expect the select's onchange functionality to work.
The current functionality is clearly not intuitive to a large number of people based solely on the number of bug reports. (Mozilla has 40 marked as duplicates.)
This is a pretty dirty hack, but you can force the the change event to fire by doing this:
element.addEventListener('keyup', function(evt){
evt.target.blur();
evt.target.focus();
}, false);
So you'd register an event listener for change as well, and that function would get called when the user presses a key on the <select> via the code above.
You may want to scope this only to Firefox, but AFAIK you'd have to use UA sniffing for that so it's up to you if that's acceptable.
Source
I'm thinking about something like this (to not trigger event if value wasn't changed):
select.keydown(function(){
var _this = $(this);
var _val = $(this).val();
setTimeout(function(){
if(_this.val() !== _val){
_this.trigger("change");
}
}, 1);
});
Here's a realization of this request. For brevity only showing the code. See https://github.com/ida/skriptz/blob/master/js/fields/select/selection_changed.js for long explanations in comments.
function addSelectionChangedListener(selectionEle, onChangeDoWithEle) {
var selectedIndex = null
function onChangeEvent(eve) {
// If selection-change was caused of an option's click-event:
if(eve.explicitOriginalTarget.tagName.toLowerCase() == 'option') {
// We want to trigger passed event-handler:
onChangeDoWithEle(eve.target)
}
}
function onKeyEvent(eve) {
// Key-event is keydown, remember current selectedIndex:
if(eve.type == 'keydown') {
selectedIndex = eve.target.selectedIndex
}
// Key-event is keyup, if selection changed, trigger passed handler:
else if(selectedIndex != eve.target.selectedIndex) {
onChangeDoWithEle(eve.target)
}
}
selectionEle.onchange = function(eve) onChangeEvent(eve)
selectionEle.onkeydown = function(eve) onKeyEvent(eve)
selectionEle.onkeyup = function(eve) onKeyEvent(eve)
}
This is driving me nuts. Its a tough one to explain but I'll have a go.
I have one input text field on the front page of my site. I have coded a keydown event observer which checks the keyCode and if its ENTER (or equiv), itll check the input value (email). If the email is valid and unique in the DB itll submit the form. Basic stuff, or so you would think.
If I type my email address in the field and hit enter, it works fine in all browsers. However, if I type the first couple of letters, and then use the arrow keys to select the email from the history dropdown box (hope you know what I mean here), and then press enter the result is different. The value of the form field is being captured as just the couple of letters I typed, and therefore the validation is failing. It seems that when I press the enter key to "select" the email from the history dropdown, the browser is interrupting that as if I was typing.
In Chrome and Safari it works as it should. As it should means that when you press enter to "select" the email from the history dropdown, all it does is puts that email address into the text box. Only on the second ENTER key press does it then trigger the event observer, and the email is validated.
Hope somebody can shed some light on why this is happening... My gut feeling is its a browser thing and will be something I cant fix.
Thanks
Lee
EDIT:
To add clarification to my question let me add that Im using the "keydown" event to capture the moment when the enter key is pressed. I have tried the "keyup" event and this solved my problem above, but then I cant seem to stop the form submitting by itself. The "keyup" event triggers AFTER the default behaviour, therefore its not the right choice for this.
FURTHER EDIT:
Thank you again, and btw, your English is excellent (in response to your comment about bad English).
I have changed my event handler from this:
$("emailInputBox").observe("keydown", function(event) {
return submitViaEnter(event, submitSignupFormOne);
});
to this:
$("emailInputBox").observe("keydown", function(event) {
setTimeout(submitViaEnter.curry(event, submitSignupFormOne),0);
});
submitViaEnter:
function submitViaEnter(event, callback) {
var code = event.keyCode;
if (code == Event.KEY_RETURN) {
event.stop();
return callback(event);
}
return true;
}
Seems to work but the problem now is that the browser is permitted to carry out the default action before running the submitViaEnter function which means the form is being submitted when I hit ENTER.
Answer to the original question
Yeah, it's a Gecko bug (not Mac-specific though).
The last part of this comment contains the description of the work-around: use the time-out.
[edit] since you asked for the clarification of the bug
When you press Enter and the auto-complete is active, Firefox (erroneously) first fires the page's key handler, then the browser's internal key handler that closes the autocomplete popup and updates the text area value, while it arguably should just fire it at the autocomplete popup and only let the page know the textbox value changed.
This means that when your key handler is called, the autocomplete's handler hasn't run yet -- the autocomplete popup is still open and the textbox value is like it was just before the auto-completion happened.
When you add a setTimeout call to your key handler you're saying to the browser "hey, run this function right after you finished doing stuff already in your P1 to-do list". So the autocomplete's handler runs, since it's already in the to-do list, then the code you put on a time-out runs -- when the autocomplete popup is already closed and the textbox's value updated.
[edit] answering the question in "Further edit"
Right. You need to cancel the default action in the event handler, not in the timeout, if you want it to work:
function onKeyPress(ev) {
if (... enter pressed ...) {
setTimeout(function() {
... check the new textbox value after letting autocomplete work ...
}, 0);
// but cancel the default behavior (submitting the form) directly in the event listener
ev.preventDefault();
return false;
}
}
If you still wanted to submit the form on Enter, it would be a more interesting exercise, but it doesn't seem you do.
ok sorted it. Thanks so much for your help. It was the curry function that I was missing before. I was trying to work on the event inside the scope of the setTimeout function.
This works below. The submitViaEnter is called from the eventobserver and responds to the keyDown event:
function submitViaEnter(event, callback) {
var code = event.keyCode;
if (code == Event.KEY_RETURN) {
event.stop();
setTimeout(callback.curry(event),0);
// return callback(event);
// return false;
}
return true;
}
Stopping the default action inside the eventObserver meant that no characters could be typed. So I stuck inside the if ENTER key clause.