Which event is being triggered from a menu paste? - javascript

I have a search box that users can type in. When the user keys up, the search is performed. There are checks to see the length of text in the search box.
// THE SEARCH STRING IS BEING POPULATED
$SEARCH.SearchString.keyup($SEARCH.utilities.doSearch);
When someone uses ctrl+v to paste text, this works perfect. When someone uses the menu to paste, like in the image below, the search is not performed.
I am not sure of what to call this menu so it's difficult to search for an answer. What event should I have JavaScript listen for when this menu is present and the user selects "Paste"?

The input event triggers for both paste and typing, thus could be used in lieu of keyup or keydown and cover both scenarios for user entry in modern browsers.
The caveat is that IE shows support starting in IE9 as well as IE9 has some different behavior issues .
IE 9 does not fire an input event when the user removes characters
from input filled by keyboard, cut, or drag operations.
$('input').on('input', function(e){
$('body').append('<br>Input event triggered, value = ' + this.value);
});
Reference: MDN input event docs
DEMO

There is onpaste but it doesn't seem to be part of any standard so your milage may vary
$(selector).on('paste', function() {
doSomething();
});

Related

how does google redirect a keypress event (no matter where) to its search text box?

make any search in google and you end up with the search text box and various other HTML elements (for the various matches).
I noticed that, no matter which HTML element has the focus, if you type a letter/number it gets picked up by the search text box.
Can somebody explain to me how google achieves that ?
I'd like to do something similar on my site.
p.s.
I was thinking to listen to key events from document but I am not sure if that is a good idea...
You can try something like this.
The main ideea is to capture keyboard events closer to the root, window would be fine. Once you catched up one, you should focus your search input by adding the correct character typed before focusing. On input focus, don't forget to unbind the window keyup handler and bind it again on input blur. Some startup code to help you:
$(document).ready(function() {
var windowKeyupHandler = function(e) {
var code = e.which || e.keycode;
$('#typer').focus().val( $('#typer').val() + ' ' + String.fromCharCode(code).toLowerCase());
$(window).off('keyup.window');
};
$(window).on('keyup.window', windowKeyupHandler);
$('#typer').on('blur', function(e) {
$(window).on('keyup.window', windowKeyupHandler);
});
});
One way is listening to key down on window and channeling it to the input.
Other way would be to capture each key down (that its target is not the input, you can see it in the event object), and set focus to the input, then appending the key. This way only the first key down would need to be "caught", the other will be automatically typed in the input.

Key event doesnt trigger in Firefox on Android when word suggestion is on

I have a search field that triggers an autocomplete search while typing. I have it trigger on keyup. This works perfectly in most browsers, but in Firefox on Android, this does not work. It seems like the keyup event is not triggered while typing. This only happens if word suggestions is turned on in the Android keyboard settings.
I see on Google search that the autocomplete search works there for the same setup, so it is obviously possible to do. I wonder how? Is it a special event I need to listen to for this to work?
Additionally I have tried to listen to the events change, keydown and keypress, but none is triggered.
HTML:
<input type="text" id="searchField"
autocomplete="off" spellcheck="false" autocorrect="off" />
jQuery event binding:
$('#searchField').keyup(function (e) {
var searchValue = $(this).val();
searchApi._executeAutocomplete(searchValue);
});
Note:
Sometimes, the key event is triggered, which is typically hitting a key that is not resulting in the process of forming a word. The most obvious here is Enter, which always triggers. Another is Space, which triggers because no word contain a space since space is the definition of a word completed. Backspace triggers if the the last character deleted was not within a word. This means it triggers if you just deleted the last remaining letter of a word (so it is the start of the field, or cursor following a space), but not if you deleted some characters at the end of a word where the cursor is still immediately following a letter. Basically, the key event is not triggered if the key press results in some kind of word suggestion from the keyboard app.
As a side note, I can say that everything works fine in Chrome on the same device.
You can use the input event instead, that worked for me in Firefox on Android.
You could bind event handlers to both input and keyup events for backwards compatibility, but in most modern browsers this will fire both:
$('#searchField').bind('input keyup', function(e){
var searchValue = $(this).val();
searchApi._executeAutocomplete(searchValue);
});
Example here:
http://jsfiddle.net/JQ928/3/
I found a solution in this answer to another question. The question was a basically "duplicate the text I write dynamically into another part of the page". The answer was including support for catching changes by non-keyboard actions, like pasting text using mouse. It was solved by starting a sniffer on focus in the text field that checks if the value has changed using setInterval(...). It clears the timer on blur.
This solved my problem which was basically that the key events didn't trigger, as well as the "paste by mouse" issue that I didn't realize was a problem until I found this answer...!
This works, but I'm not sure I am totally happy with this solution, because it uses a sniffer. I would be more happy with using some sort of event that is triggered on value change no matter what the cause of the change is. Using the change event would not work, as that is not triggered until focus leaves the field.
Trough the fact that Firefox on Android doesn't trigger key-events, but also triggers the input-event some kind of weird, (like if you press one key two events get triggerd, and it also triggers the input-event if you leave the input) I had to write my own event:
(function($){
var $event = $.event,
$special = $event.special.fennecInput = {
setup: function(){
$(this).on('input',$special.handler);
},
teardown: function(){
$(this).off('input',$spceial.handler);
},
handler: function(event) {
var context = this,
args = arguments,
dispatch = function() {
event.type='fennecInput';
$event.dispatch.apply(context,args);
};
if($(context).val() != $(context).attr('data-fennecInput-oldval')){
dispatch();
$(context).attr('data-fennecInput-oldval',$(context).val());
}
}
};
})(jQuery);
this event gets only triggered if an input-event happens that changes the value, so it doesn't execute events unnecessary.

Responsive Rich Editor Preview

Consider this Example.
The essential bit is the JavaScript:
function encodeInput(editor) {
theText = editor.val();
theText = theText.replace(/\*\*\*(.*?)\*\*\*/, '<strong><i>$1</i></strong>', 'g');
theText = theText.replace(/\*\*(.*?)\*\*/, '<strong>$1</strong>', 'g');
theText = theText.replace(/\*(.*?)\*/, '<i>$1</i>', 'g');
console.log(theText);
$('#preview').html(theText);
}
$(function() {
$editor = $('#editor');
$editor.keyup(function() {
encodeInput($(this));
});
});
Tested and works great (I do need the \*\*\* part or it doesn't work).
Anyways, on to the main course
The Problem
Because I'm using keyup, the script is not very responsive (eg. it only "runs" once the user had let go of the key). I want it to behave more like the editor here on StackOverflow, where the key is pressed and response occurs immidiately.
I tried using keydown and keypress but it seems as if the val() attribute is not updated when it runs, so I can't really know the updated value.
In Short
How can I make it more responsive, so that when the user pressed a key, the preview is automatically updated??
You can use the HTML5 input event in most browsers and the propertychange event in IE < 9. These events fire immediately after the textarea's value is updated.
Here's an updated demo using these events:
http://jsfiddle.net/muWm2/1/
I've written about this in a few places on SO. Here are two of them:
Catch only keypresses that change input?
jQuery keyboard events
I would recommend against updating the preview on every single change to the textarea's value because it could quickly get unresponsive, which is a big no-no for user experience. I'd suggest "debouncing" the event, in this case waiting for a period of user inactivity (say half a second) before updating the preview. Here's an answer and a link that may help:
How to trigger an onkeyup event that's delayed until a user pauses their typing?
Debouncing Javascript Methods by John Hann
You can bind() both the keyup and keydown events:
$editor.bind('keyup keydown', function() {
encodeInput($(this));
});
I noticed that only the first occurrence was working, adding the g flag to the regex seemed to help, and for the purpose of the jsfiddle demo only, unchecking "normalize css" made the bold text appear.
http://jsfiddle.net/tuUym/3/
Keypress fires when the key is pressed continously, so you have to bind it to keypress in order to see the result. And thats it.
http://jsfiddle.net/tuUym/4/
UPDATE: I see what you mean. Maybe you need an input poller? Check out the de obfuscated wmd code. That will help you achieve the lagless editor you aim for:
WMD Download

Javascript onChange arrow keys

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)
}

YUI Autocomplete: search after pasting?

I'm using an auto-complete widget from YUI to implement live search as in the examples. However, it works fine when search text is typed in, but fails to work when the text is pasted into the field. Which would be the proper way to initiate an autocompletion on paste? Haven't found anything for that in the documentation...
EDIT: Pasting is not Ctrl-V, it's usually "Paste" from the context-menu. YUI does react to a keypress, but doesn't if anything is pasted by the mouse.
We have extended YUI's autocomplete widget and handle paste from the context menu in this way:
YAHOO.util.Event.on(input, 'paste', function(e, autocomplete) {
// We're interested in the value of the input field after text is pasted into
// it instead of the pasted text because the autocomplete proposals are based
// upon the field's whole value. The paste event happens before the input
// field has been updated so we need to wait until after this event has been
// handled to check the value of the input field.
window.setTimeout(function() {
if (autocomplete._sInitInputValue !== autocomplete.getInputEl().value) {
autocomplete.sendQuery(autocomplete.getInputEl().value);
}
}, 1);
}, this);
Where this is the autocomplete widget.
Perhaps on key event, you could detect if they pressed v while holding ctrl. If they have, then do a sendQuery('query=' + textInput.value);
Edit
Here's a compatibility table showing which browsers let you subscribe to the paste events.
http://www.quirksmode.org/dom/events/cutcopypaste.html
Here's his testing page where you can see how to subscribe to the events.
http://www.quirksmode.org/dom/events/tests/cutcopypaste.html
I imagine you could subscribe to that using YUI & then just have your callback be this:
function() {
autoCompleteObject.sendQuery(autoCompleteElement.value);
}
Watch out for browser incompatibilities, looks like some have a weird implementation of the events.

Categories

Resources