Consider the following HTML:
<select>
<option>Aardvark</option>
<option>Buffalo</option>
<option>Camel</option>
<option>X-ray Fish</option>
<option>Yak</option>
<option>Zebra</option>
</select>
In most browsers, when the select element has focus, pressing a key will change the selected value to the next option that begins with the character typed. For instance, pressing 'B' on the keyboard while the <select> element above has focus changes the selected value to "Buffalo". Pressing 'Z' after that will change the value to "Zebra".
But I just discovered that, at least in Firefox 6 and Safari 5 on my PC, there is a delay before I can press-to-select the next value. In the specific example above, if I press "B" and then press "Z" less than a second later, nothing appears to happen.
However, in further testing (with jQuery) I discovered that the Javascript events 'keydown', 'keyup', and 'keypress' ARE all fired as you'd expect, no matter how rapidly you press the keys. The browsers themselves just don't switch the selected option until a certain period of time has passed.
Is there any way to get around this?
It seems to be possible with cloning. It's a really dirty hack but works just fine in Chrome: http://jsfiddle.net/pimvdb/v6qy8/2/.
$('select').keyup(function() {
var newSelect = $(this).clone(true).val($(this).val());
$(this).replaceWith(newSelect);
newSelect.focus();
});
I did it by interrupting the keyevent and placing a preventDefault() at the top of the function. I use the Enter key to break the delay and submit what I've typed already.
if (eventinfo.keyCode == 13) {
eventinfo.preventDefault();
var search = document.getElementById("searchtag");
var value = search.value;
mainPage.searchAdd(value).done(
function () {
search.value = "";
search.focus();
}
);
}
Related
I'm making a custom input field which should support subscript. When the user presses the down arrow + a number, then the number should be in subscript. I appended a onKeyDown and onKeyUp event listener to a content editable paragraph. Unfortunately the onKeyUp gets called when the user presses the number, which results in adding the number twice (once in subscript and once normal). How can I solve this problem?
function keyDown(event) {
var code = event.keyCode;
if (code === 40) {
option = 0;
}
}
function keyUp(event) {
var code = event.keyCode;
if (code === 40 || code === 38) {
option = -1;
}
console.log("release");
}
The onKeyPressed is not an option since this does not recognize the arrow keys in all browsers. Is there a native solution (without jQuery)?
What I usually do is to push the keyCodes into an Array on keyDown and .splice() it on keyUp.
All you have to do now is to check (probably against a pre-defined map) if the key states you desire are available in that Array.
As long as your text field has focus, any numeral key you press will be added to it in addition to whatever your keyup or keydown listeners add to it. Maybe you should take away focus from the text field on keydown if the key you are pressing is the down key and add focus back again after the keyup event has fired.
/* Keep track of the down key. */
var down=false;
/* Get the input text field. */
var input=document.getElementById("input");
input.addEventListener("keydown",keyDown);
input.addEventListener("keyup",keyUp);
/* Give focus to input. I'm not sure if this is the right way to do it, I haven't tested this code, but I know there's a way to give focus to elements and it sort of looks like this. */
input.focus();
function keyDown(event_){
switch(event_.keyCode){
case 40:
/* Once again, not sure how to unfocus, but I know you can. */
input.unfocus();
down=true;
break;
}
}
function keyUp(event_){
switch(event_.keyCode){
case 40:
/* Give focus back to input after the keyup event has fired. */
input.focus();
down=false;
break;
}
if (down){
input.value+=//The subscript version of whatever key you pressed.
}
}
Once again, I would just like to say that this code hasn't been tested and I'm not sure if focus() and unfocus() are real methods, but you get the idea. You want to momentarily stop the text field from accepting input while the down key is pressed so you can add your own special value to it without updating it's contents with the default response and then give focus back to the text field once the down key is no longer in use.
I have following jquery code, where on click of a check box I will show a popup value.
Except in IE,in all other browser it works as expected. That is, on change the check box will be checked and the popup will be opened.
However in IE8 its not getting checked, however popup is displayed properly.
Code :
$('#TAndC').change(function(){
if( $('input[name="TAndC"]').is(':checked'))
{
$('#TandCBox').show();
var termsandcondition = GetEnum().TermsandConditionsPageId;
var actionURL = '#Url.Action("ShowTAndC", "Account", new { isFromCheckBox = true })';
$('.popUpForm').load(actionURL);
var msgBox = $('#terms').attr('href');
MaskMsgPopUp(msgBox);
return false;
}
});
If your element is a checkbox and not a dropdown then use click anyway.
If your selector is referring to a dropdown use click if you need to support IE8 and older.
See why that is below.
According to the MSDN for change/onchange, the event is not triggered until the change is committed.
In addition the event is also not triggered when the value is changed programmatically.
To quote:
This event is fired when the contents are committed and not while the
value is changing. For example, on a text box, this event is not fired
while the user is typing, but rather when the user commits the change
by leaving the text box that has focus. In addition, this event is
executed before the code specified by onblur when the control is also
losing the focus. The onchange event does not fire when the selected
option of the select object is changed programmatically. Changed text
selection is committed.
To invoke this event, do one of the following:
Choose a different option in a select object using mouse or keyboard navigation.
Alter text in the text area and then navigate out of the object.
If you must support IE8 and older, you are probably better of to use the click event instead which get's triggered when you release the mouse and your new choice is selected.
instead of .change use below code and try
$(document).ready(function(){
$(document).on('click','#TAndC',click_function){
if( $('input[name="TAndC"]').is(':checked'))
{
$('#TandCBox').show();
var termsandcondition = GetEnum().TermsandConditionsPageId;
var actionURL = '#Url.Action("ShowTAndC", "Account", new { isFromCheckBox = true })';
$('.popUpForm').load(actionURL);
var msgBox = $('#terms').attr('href');
MaskMsgPopUp(msgBox);
return false;
}
});
});
I have the following input element on my page:
<input class="input" name="custom_fields[new]" placeholder="Enter placeholder" type="text">
I have a Twitter Flight event listener on this element that looks like this:
this.on('keyup', {
inputsSelector: this.updateViewInputs
});
Which triggers this method:
this.updateViewInputs = function(ev) {
var isDeletionKeycode = (ev.keyCode == 8 || ev.keyCode == 46);
// Remove field is user is trying to delete it
if (isDeletionKeycode && this.shouldDeleteInput(ev.target.value, this.select('inputsSelector').length)) {
$(ev.target.parentNode).remove();
}
// Add another field dynamically
if (this.select('lastInputsSelector')[0] && (ev.target == this.select('lastInputSelector')[0]) && !isDeletionKeycode) {
this.select('inputsContainer').append(InputTemplate());
}
// Render fields
that.trigger('uiUpdateInputs', {
inputs: that.collectInputs()
});
}
And finally triggers uiUpdateInputs:
this.after('initialize', function() {
this.on(document, 'uiUpdateInputs', this.updateInputs)
});
this.updateInputs = function(ev, data) {
// Render all inputs provided by user
this.select('inputListSelector').html(InputsTemplate({ inputs: data.inputs }));
}
All of this functionality works as expected on Chrome and Firefox. Users can type into the input and see the page change in 'real time'. Users also get additional fields that they can enter text into and see the page change.
The issue in question arises when using Safari, as a user enters text into the described input field the text in the input field becomes highlighted (selected) and when they enter the next character all the content is replaced with that single character. This results in the user not being able to enter more than 1 or 2 characters before having them all replaced by the next entered character.
I have tried several approaches to fix this problem but none have worked, they include:
Using a setTimeout to delay the code run on the keyup event
Using Selection to try to disable the selection of the text using collapseToEnd.
Using click,focus,blur events to try to remove the selection from the entered text
Triggering a right arrow key event to try to simply move the cursor forward so they user does not delete the selected text
Using setInterval to routinely remove selections made by the window
I am very confused why this is happening and I am wondering if this is a bug in webkit with Flight. I see no issue with the Firefox or Chrome versions of this page. Thanks for any help!
This seems to be an issue with certain versions of Safari. When listening for the keyup function in javascript it will automatically select all of the text in the box and subsequently delete it all when the next key is typed. To prevent this from happening call preventDefault on the event object that is passed to the keyup function.
this.on('keyup', function(e) {
e.preventDefault()
});
What I want is to simulate typing in <input> field using javascript.
I have the following code:
var press = jQuery.Event("keydown");
press.ctrlKey = false;
press.which = 65;
$("#test").trigger(press);
But when I load the page, the #test input field has no typed characters, the keycode of '65' represents 'A', but there is no 'A' input.
Basically what I want is to automatically typing in the website using Greasemonkey.
Please give me some ideas or some library with which I can use to do this.
Thanks a lot!
You can send key events, and anything listening for them will get them, but they will not change the input, so you will not see the letter A appear, for example. This is mostly a security thing; see "Manually firing events" for a discussion about that.
So, if you want the letter to appear, you must alter the input's value as you send the key event. There is a jQuery plugin for that, see "The $.fn.sendkeys Plugin".
You can see how an <input> reacts with user-applied keys, key events, and that plugin at this jsFiddle.
For reference, this is the key piece of code from that jsFiddle:
$("button").click ( function (zEvent) {
if (zEvent.target.id == "simA_plain") {
console.log ("Send Plain key event");
var keyVal = 65;
$("#eventTarg").trigger ( {
type: 'keypress', keyCode: keyVal, which: keyVal, charCode: keyVal
} );
}
else {
console.log ("Use the Plugin to simulate a keystroke");
$("#eventTarg").sendkeys ("B") ;
}
} );
That plugin should be sufficient if you are just trying to "simulate typing on an <input>". However, depending on what you are really trying to do, you may need to do one or more of the following:
Just set the text to what you want it to be.
Send a keydown event, if the page's javascript triggers off of that.
Likewise, send a change event, etc., if the page's javascript triggers off of that.
Just find and call the page's javascript directly. Use script injection, the location hack, unsafeWindow, and/or #grant none mode to do that.
Something else? State your true objective and link to the target page.
I have a pretty simple form. When the user types in an input field, I want to update what they've typed somewhere else on the page. This all works fine. I've bound the update to the keyup, change and click events.
The only problem is if you select an input from the browser's autocomplete box, it does not update. Is there any event that triggers when you select from autocomplete (it's apparently neither change nor click). Note that if you select from the autocomplete box and the blur the input field, the update will be triggered. I would like for it to be triggered as soon as the autocomplete .
See: http://jsfiddle.net/pYKKp/ (hopefully you have filled out a lot of forms in the past with an input named "email").
HTML:
<input name="email" />
<div id="whatever"><whatever></div>
CSS:
div {
float: right;
}
Script:
$("input").on('keyup change click', function () {
var v = $(this).val();
if (v) {
$("#whatever").text(v);
}
else {
$("#whatever").text('<whatever>');
}
});
I recommending using monitorEvents. It's a function provide by the javascript console in both web inspector and firebug that prints out all events that are generated by an element. Here's an example of how you'd use it:
monitorEvents($("input")[0]);
In your case, both Firefox and Opera generate an input event when the user selects an item from the autocomplete drop down. In IE7-8 a change event is produced after the user changes focus. The latest Chrome does generate a similar event.
A detailed browser compatibility chart can be found here:
https://developer.mozilla.org/en-US/docs/Web/Events/input
Here is an awesome solution.
$('html').bind('input', function() {
alert('test');
});
I tested with Chrome and Firefox and it will also work for other browsers.
I have tried a lot of events with many elements but only this is triggered when you select from autocomplete.
Hope it will save some one's time.
Add "blur". works in all browsers!
$("input").on('blur keyup change click', function () {
As Xavi explained, there's no a solution 100% cross-browser for that, so I created a trick on my own for that (5 steps to go on):
1. I need a couple of new arrays:
window.timeouts = new Array();
window.memo_values = new Array();
2. on focus on the input text I want to trigger (in your case "email", in my example "name") I set an Interval, for example using jQuery (not needed thought):
jQuery('#name').focus(function ()
{
var id = jQuery(this).attr('id');
window.timeouts[id] = setInterval('onChangeValue.call(document.getElementById("'+ id +'"), doSomething)', 500);
});
3. on blur I remove the interval: (always using jQuery not needed thought), and I verify if the value changed
jQuery('#name').blur(function ()
{
var id = jQuery(this).attr('id');
onChangeValue.call(document.getElementById(id), doSomething);
clearInterval(window.timeouts[id]);
delete window.timeouts[id];
});
4. Now, the main function which check changes is the following
function onChangeValue(callback)
{
if (window.memo_values[this.id] != this.value)
{
window.memo_values[this.id] = this.value;
if (callback instanceof Function)
{
callback.call(this);
}
else
{
eval( callback );
}
}
}
Important note: you can use "this" inside the above function, referring to your triggered input HTML element. An id must be specified in order to that function to work, and you can pass a function, or a function name or a string of command as a callback.
5. Finally you can do something when the input value is changed, even when a value is selected from a autocomplete dropdown list
function doSomething()
{
alert('got you! '+this.value);
}
Important note: again you use "this" inside the above function referring to the your triggered input HTML element.
WORKING FIDDLE!!!
I know it sounds complicated, but it isn't.
I prepared a working fiddle for you, the input to change is named "name" so if you ever entered your name in an online form you might have an autocomplete dropdown list of your browser to test.
Detecting autocomplete on form input with jQuery OR JAVASCRIPT
Using: Event input. To select (input or textarea) value suggestions
FOR EXAMPLE FOR JQUERY:
$(input).on('input', function() {
alert("Number selected ");
});
FOR EXAMPLE FOR JAVASCRIPT:
<input type="text" onInput="affiche(document.getElementById('something').text)" name="Somthing" />
This start ajax query ...
The only sure way is to use an interval.
Luca's answer is too complicated for me, so I created my own short version which hopefully will help someone (maybe even me from the future):
$input.on( 'focus', function(){
var intervalDuration = 1000, // ms
interval = setInterval( function(){
// do your tests here
// ..................
// when element loses focus, we stop checking:
if( ! $input.is( ':focus' ) ) clearInterval( interval );
}, intervalDuration );
} );
Tested on Chrome, Mozilla and even IE.
I've realised via monitorEvents that at least in Chrome the keyup event is fired before the autocomplete input event. On a normal keyboard input the sequence is keydown input keyup, so after the input.
What i did is then:
let myFun = ()=>{ ..do Something };
input.addEventListener('change', myFun );
//fallback in case change is not fired on autocomplete
let _k = null;
input.addEventListener( 'keydown', (e)=>_k=e.type );
input.addEventListener( 'keyup', (e)=>_k=e.type );
input.addEventListener( 'input', (e)=>{ if(_k === 'keyup') myFun();})
Needs to be checked with other browser, but that might be a way without intervals.
I don't think you need an event for this: this happens only once, and there is no good browser-wide support for this, as shown by #xavi 's answer.
Just add a function after loading the body that checks the fields once for any changes in the default value, or if it's just a matter of copying a certain value to another place, just copy it to make sure it is initialized properly.