After clicking on selected text, window selection is not giving updated range - javascript

After double click, selection range can be obtained correctly on onclick event but when I again click on the selected text then updated selection range should be returned by window selection but this is not happening. Can anybody tell me if this is a bug in javascript selection or they have made it this way. And what could be the solution to get the updated range apart from timer.
<div id="xyz" contenteditable="true">Hello world</div>
<span class="status">Selected text : </span>
javascript code :
function yourFunction() {
if (window.getSelection) {
var selectionRange = window.getSelection();
$('.status').text(selectionRange.toString());
}
}
$('#xyz').click(function () {
$('.status').text('Mouse click');
yourFunction();
})
Example here

You fiddle is working just fine. But, yes sometimes when you do selections in quick succession, then it fails to register the click.
The problem really lies in the way you have implemented it on click on the text input itself. A click event is generated when a mouseup follows a mousedown. A selection happens when you mousedown then drag and then mouseup.
If you separate out the selection retrieval then this problem won't occur.
See this updated fiddle: http://jsfiddle.net/zRr4s/21/
Here, the selection retrieval is donw on a button click, instead of the input itself.
i.e., instead of:
$('#xyz').click(function (e) { ...
using this:
$('#btn').click(function () { ...
where, btn is:
<input id="btn" type="button" value="get selection" />
Hope that helps.
Update:
If you insist on handling event only on the input, then listening mouseup would be better option:
See this fiddle: http://jsfiddle.net/zRr4s/22/
$('#xyz').on("mouseup", function (e) { ...
Update 2:
To handle your requirement of in-context click, you will have to first clear the selection. For this to happen you will have to handle mousedown. So, that will defeat your purpose of having only one handler. Anyway,
You updated fiddle: http://jsfiddle.net/zRr4s/29/
And, this is how you do it:
$('#xyz').on("mousedown", function () {
clearTheSelection();
});
Where clearTheSelection is another function:
function clearTheSelection() {
if (window.getSelection) {
if (window.getSelection().empty) { // Chrome
window.getSelection().empty();
} else if (window.getSelection().removeAllRanges) { // Firefox
window.getSelection().removeAllRanges();
}
} else if (document.selection) { // IE?
document.selection.empty();
}
}
The complete code for the above function taken from this answer: https://stackoverflow.com/a/3169849/1355315
Hope that completes all your problems.

The fiddle provided in the question works fine in Edge and IE11 but doesn't work in Chrome. I found a trick to make it work everywhere. Add the following event handler in addition to the click handler you already have:
$(document).on("selectionchange", function () {
yourFunction();
});
Some notes:
selectionchange is a document level event, you cannot bind it to specific element (but you can find out whether you need to handle it within the event handler)
Handling selectionchange without also handling click doesn't work well in Edge and IE11
According to MDN, browser support is good enough: https://developer.mozilla.org/en-US/docs/Web/API/Document/selectionchange_event

Related

How to call a function when default browser autocomplete list item selected [duplicate]

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.

Fire event with right mouse click and Paste

I want to fire an event in a textarea immediately after paste some text inside the textarea. I can do that when Shift+Ins is used; however, I cannot do it when right mouse button and then paste (from the drop down menu) is chosen. Keyup fires after Shift+Ins. None of the rest fires when Paste is chosen after right mouse button clicking... What do I have to do?
<textarea name="message" id="message"></textarea>
$("#message").on('keyup contextmenu', function(event) {
alert("ok");
});
http://jsfiddle.net/f29vuwoL/7/
Thank you
Most browsers support the input event, which is fired when something is pasted or otherwise added, regardless of how:
$("#message").on('keyup contextmenu input', function(event) {
alert("ok");
});
Updated Fiddle
Note that using input is the most general method, firing when the control gets input regardless of how, and so if you hook multiple events (as above), you'll get multiple calls for the same input. For instance, if you hook both keyup and input, on browsers that support input, you'll get two calls. Similarly for paste and input when the user pastes, on browsers that support both.
If you need to support browsers that don't have either input or paste, I'm afraid the unfortunate answer is that you need to poll. Still, polling every (say) 250ms isn't asking the browser to do that much work, and you can feature-detect whether it's necessary:
var message = $("#message");
var events = null;
var previous;
if ('oninput' in message[0]) {
// Browser supports input event
events = "input";
} else if ('onpaste' in message[0]) {
// Browser supports paste event
events = "paste keyup contextmenu";
}
if (!events) {
// Ugh, poll and fire our own
events = "pseudoinput";
previous = message.val();
setInterval(function() {
var current = message.val();
if (current != previous) {
previous = current;
message.trigger(events);
}
}, 250);
}
console.log("Using: " + events);
message.on(events, function(e) {
console.log("Got event: " + e.type);
});
Updated Fiddle
You should use input event callback. See the demo here
You can use the dedicated paste event:
$("#message").on('paste', function(event) {
alert("ok");
});
Updated jsFiddle
However you might want to check browser support - I don't think jQuery normalizes this event.
If you need IE support, it might be a little more difficult, but it depends on your requirements - does it absolutely need to be a paste action? If not, TJ Crowder's answer is the way to go.
The on input is useful if you want to detect when the contents of a textarea, input:text, input:password or input:search element have changed, because the onchange event on these elements fires when the element loses focus, not immediately after the modification.The oninput event is supported in Internet Explorer from version 9.
$("#message").on('input propertychange', function() {
console.log($(this).val());
});
Fiddle

JS function applies checkbox value not immediately for IE

Another one cross-browser issue.
JS logic:
if one specific check-box is checked,that dependent ones are checked automatically
and vice versa,if this check-box is unchecked ,that dependent unchecked also:
function changeStatusCheckBox(statusCheckbox) {
if (statusCheckbox.id == "id1") {
if (statusCheckbox.checked == true) {
document.getElementById("id2").checked = true;
document.getElementById("id3").checked = true;
}
else {
document.getElementById("id2").checked = false;
document.getElementById("id3").checked = false;
}
}
}
FF is OK - check/uncheck performed immediately.
IE7 check/uncheck works after clicked on some other browser area.
It looks like IE expects for additional blur behaviour.
JS called from this .jsf:
<h:selectBooleanCheckbox id="id1"
value="#{payment.searchByPaymentCriteria}" onchange="javascript:changeStatusCheckBox(this);"/>
What is your opinion?
Thank you for assistance.
Internet Explorer and some other browsers also works like this. The onchange event is called only when the blur occours and something changed. Text inputs and select combos are also like this.
The better way to do that with checkboxes, crossbrowser, is to bind it to the onclick event.
The onclick is called right after the mouseup event, so the checkbox status(checked or not) would be changed when the function is called.
Just do like
<h:selectBooleanCheckbox id="id1" value="#{payment.searchByPaymentCriteria}" onclick="javascript:changeStatusCheckBox(this);"/>
The way I like to this is to trap the click event only in IE, and blur/focus the checkbox. That will fire the change event in IE, and you can continue to use the change event for other browsers that support it. Click is not the same, and could introduce other issues. (Example utilizes $.browser from jQuery and assumes jQuery is included on the page.) Same example would work for radio buttons (substitute :radio for :checkbox).
function fixIEChangeEvent (){
if ($.browser.msie && $.browser.version < 9) {
$("input:checkbox").bind("click", function () {
this.blur();
this.focus();
});
}
}

Jquery : how to trigger an event when the user clear a textbox

i have a function that currently working on .keypress event when the user right something in the textbox it do some code, but i want the same event to be triggered also when the user clear the textbox .change doesn't help since it fires after the user change the focus to something else
Thanks
The keyup event will detect if the user has cleared the box as well (i.e. backspace raises the event but backspace does not raise the keypress event in IE)
$("#inputname").keyup(function() {
if (!this.value) {
alert('The box is empty');
}
});
jsFiddle
As Josh says, this gets fired for every character code that is pressed in the input. This is mostly just showing that you need to use the keyup event to trigger backspace, rather than the keypress event you are currently using.
The solution by Jonathon Bolster does not cover all cases. I adapted it to also cover modifications by cutting and pasting:
$("#inputname").on('change keyup copy paste cut', function() {
//!this.value ...
});
see http://jsfiddle.net/gonfidentschal/XxLq2/
Unfortunately it's not possible to catch the cases where the field's value is set using javascript. If you set the value yourself it's not an issue because you know when you do it... but when you're using a library such as AngularJS that updates the view when the state changes then it can be a bit more work. Or you have to use a timer to check the value.
Also see the answer for Detecting input change in jQuery? which suggests the 'input' event understood by modern browsers. So just:
$("#inputname").on('input', function() {
//!this.value ...
});
Another way that does this in a concise manner is listening for "input" event on textarea/input-type:text fields
/**
* Listens on textarea input.
* Considers: undo, cut, paste, backspc, keyboard input, etc
*/
$("#myContainer").on("input", "textarea", function() {
if (!this.value) {
}
});
You can check the value of the input field inside the on input' function() and combine it with an if/else statement and it will work very well as in the code below :
$( "#myinputid" ).on('input', function() {
if($(this).val() != "") {
//Do action here like in this example am hiding the previous table row
$(this).closest("tr").prev("tr").hide(); //hides previous row
}else{
$(this).closest("tr").prev("tr").show(); //shows previous row
}
});
Inside your .keypress or .keyup function, check to see if the value of the input is empty. For example:
$("#some-input").keyup(function(){
if($(this).val() == "") {
// input is cleared
}
});
<input type="text" id="some-input" />

What's the event fired when user selects some text on the page?

Either by double click or move the mouse.
Anyone knows about this?
Maybe you can bind a function to document.onmouseup to call document.getSelection()? This is assuming your users use mouse to select the text ;)
document.onmouseup = function() {
var sel = document.getSelection();
if (sel.length > 0) {
alert(sel);
}
}
I think that you refer to the selectevent. See here: http://www.comptechdoc.org/independent/web/cgi/javamanual/javaevents.html
Could it be document.getSelection()?
Here's a web page on that subject.
It's possible to use "onselect", but it works just for form elements (inputs, selects...).
function on_select() {
alert( "selected" );
}
...
<input name="input" onselect="on_select()">
In IE only the select event applies to body text as well as form inputs, so would do what you want. IE and WebKit have selectstart which fires when the users starts selecting, which probably won't help you. To detect when the user has made a selection in a cross-browser way you will need to handle both keyup and mouseup events. Even then you won't be detecting selection events such as the user using the "Select all" menu option (usually found in the Edit and right click context menus). The situation is not ideal in current browsers.

Categories

Resources