YUI Autocomplete: search after pasting? - javascript

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.

Related

Tabulator - custom editor with blur exceeding active cell

I'm working on a custom editor (dropdown with search & ajax-fetched items based on said search) and I need to keep cell in the edit mode after blur event.
As of Tabulator 5.1 blur must be handled either by calling cancel or success. If that is not satisfied Tabulator cancels the edit.
I've checked how built-in Autocomplete editor works around this but the solution lies around input type search and still adheres to this constraint.
How can this be achieved? For me personally it would make sense if the function implementing a custom editor would take an extra param passtrough changing the signature to (cell, onRendered, success, cancel, editorParams, passthrough). We could call passthrough() inside blur event to indicate we are ok with exceeding the active cell bounds and do not want to cancel the edit.
I've tried
not resolving blur event -> leads to fallback cancel
calling success, cancel -> leads to their respective results
commenting out blur handler -> results in fallback cancel too
Tabulator already has a built in autocomplete editor that allows for text searching and ajax lookup.
Full details can be found in the Editor Documentation
If you want to build a custom editor, i would suggest your starting point should be to look at the code for the existing select and autocomplete editors to see how the do this as they already work correctly, there is no need for an additional passthrough argument.
There has been no change in behaviour to the blur event behavior on editors in any of the recent releases of Tabulator, neither v5.0 or v5.1
You will see that on lines 226 and 405 of the select editor, it uses a mousedown event to track when a user clicks on elements relating to the editor and sets a blurable property to false, and then back to true a few ms later:
listEl.addEventListener("mousedown", function(e){
blurable = false;
setTimeout(function(){
blurable = true;
}, 10);
});
On line 559 it listens to the blur event on the editor, if the blurrable flag is false, ie someone just click on an element of the editor, then it ignores the blur event and dosnt cancel the edit
input.addEventListener("blur", function(e){
if(blurable){
cancelItem();
}
});

Which event is being triggered from a menu paste?

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

jQuery using event.preventDefault() with on('input')

I'm catching paste events with $('selector').on('input', function(event) { ... });
Then I'm trying to test what's been pasted and if it doesn't pass validation, cancel the paste with event.preventDefault(). Unfortunately, by the time the listener function is executed, the text has already been pasted and event.preventDefault() does nothing.
So what's a good way to catch paste events, and if what's been pasted doesn't validate, undo/prevent the paste?
I know I can use .on('paste', function(event) { ... }), but that doesn't give me the text that's been pasted or the contents of the input element after the paste, unless I use setTimeout() with some minute wait time, and I'd like to avoid using setTimeout().
First of all some background on event trigger order for the input element:
keydown -> keypress -> paste -> input -> keyup -> change
Whenever you call preventDefault it stops the chains, like nothing happened.
So my suggestion is to catch the paste event, prevent its default behavior and do your logic there.
I know I can use .on('paste', function(event) { ... }), but that
doesn't give me the text that's been pasted or the contents of the
input element after the paste
Actually you can retrieve the content of the clipboard. See this doc. Support is all major browser (but only IE11+). I do not know if by the time of the writing of the question this functionality was available or not.
Fiddle example
$('#myInput').on('paste', function(e) {
// Cancel the event - this prevents the text from being entered into the input and stops the event chain
e.preventDefault();
// Get the content of the clipboard
let paste = (event.clipboardData || window.clipboardData).getData('text');
// Validate what it is pasted
if (paste == "text to paste") {
// If condition is satisfied manually set the value of the input
$(this)
.val(paste)
// Manually trigger events if you want
.trigger('input')
.trigger('change');
}
});
Notes on the code:
This solution does not include setTimeout. Whenever you make it with setTimeout you see for a very short time the text being pasted, like a blinking effect.
If text meets condition I manually set it in the input. However this does not trigger input and change events. If you need them, just manually trigger them
Similar approach is to first check the text and if it does not meet requirements then call preventDefault, otherwise do nothing. This way you avoid manually setting value in the input and triggering events afterward.
Try using .change event of jquery.
Set value to blank if value doesn't satisfy your condition.
Using
$('selector').on('input', function(event) { ... });
and in case the validation does not pass deleting the pasted text seems to work for me.
Sadly accessing the clipboard has some flaws (browser asking if it is allowed to inspect the clipboard, cross browser compatibility, etc.)
If you are okay with saving the last value of the input, the pasted text can be calculated anyway.
Here is my approach for calculating the pasted text
https://jsfiddle.net/f710o9qd/2/
I hope this helps you :)
(Feel free to refine the calculation of the pasted text if you find any flaws)
My understanding from the question is, we must not allow any data to be pasted inside the text box until and unless it pass a specific validation. Instead of using event.preventDefault(), we can capture the value when user input any content, using on('input') listener and validate it against the specific condition and if the validation gets failed, empty the text box value.
(This is the workaround if we still need to use on('input') event listener)
Sample Code (I am using console.log() for printing the pasted value):
HTML:
<input type='text' id="selector" />
JS:
$(document).ready(function() {
$('#selector').on('input', function (e){
if(e.target.value !== "myValue"){
$('#selector').val('');
}
else{
console.log(e.target.value);
}
});
});

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

How to listen to basic events in CKEditor?

I can't figure out how to listen to focus, click, onKeyUp and other basic dom events in ckeditor. In the events summary there is only a few events regarding the lifecycle of ckeditor. And the "textArea" of ckeditor is an iframe, and it's html itself, so it is not clear on what dom node to listen.
It's not a big deal, just do the following, works for focus, blur, click etc.
var ckeditor = CKEDITOR.instances['textArea_id'];
ckeditor.on('focus', fnHandler, context, data, priority);
or a jQuery example :
$(document).ready(function () {
$('#YOUR_TEXTAREA_ID').ckeditor(ckeditor_config);
CKEDITOR.instances.YOUR_TEXTAREA_ID.on('blur', fnHandler);
});
I don't know when this support appeared, but it definitely works for 3.5.x
CKEditor actually has built-in event handling in the object. See this article for an explanation: http://alfonsoml.blogspot.com/2009/09/ckeditor-events.html
So, to catch a modification in a CKEditor instance you could do this:
CKEDITOR.on('currentInstance', function(){modified = true;});
Also, it appears that version 3 has an event processor built into it that's more straightforward: http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.ui.dialog.file.html#eventProcessors
CK is a bit convoluted and documentation has holes, but based on its ability to gracefully handle Word generated HTML it gets my vote as the best option out there.

Categories

Resources