I am getting a problem when using onblur and onfocus event of textbox in Firefox.
In Opera. it works as expected (e.g. onfocus is called first, then onblur).
In Firefox, onblur is called first, then it calls onfocus. This should not happen.
How can this be fixed?
It's good to know that some browsers are broken in this way. Consider the following code.
<input type="text" id="t1" onfocus="is_editing=true" onblur="is_editing=false" />
<input type="text" id="t2" onfocus="is_editing=true" onblur="is_editing=false" />
In Opera, if you click on either textfield, is_editing will be true. If you then tab to the other textfield... is_editing will be false!
The same happens if you replace the above variable assignments with function calls: enableEditing() and disableEditing(), for example: you tab from one field to another, and editing becomes disabled. That is clearly not what people would want!
To avoid this, most browsers now support document.activeElement, which you need to use to do something really nasty like so:
function enableEdit() { is_editing = true; }
/* Can't just unset is_editing here, since broken browsers may
call onblur /after/ onfocus when tabbing between two text elements.
So, we only unset if we don't have a text element focused */
function disableEdit() {
if (!document.activeElement) {
/* For old & broken browser support, could traverse every DOM elem to set
elem.onfocus = function(){ document.activeElement = elem; }
For the meantime, I just assume they aren't broken. */
is_editing = false;
}
// If not focused on a text input type, then it's OK to unset.
else if ("text" != document.activeElement.type) {
is_editing = false;
}
}
Obviously, replace the is_editing assignments with whatever you wanted to happen onblur/onfocus.
With jQuery, you can also apparently use $("*:focus") in the same way as I used document.activeElement above.
Related
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
I am looking for a method to left align the contents of a text input box when the user fires the onblur event. I have seen mention of solving the issue with onblur="this.value = this.value", but this does not work in IE.
To Clarify: This issue occurs in Internet Explorer when the user types beyond the width of the textbox and then leaves focus. In Chrome and Firefox, the text will automatically left align, but this does not happen in IE.
Due to request, I've attached code (View in IE):
<input type="text" />
http://jsfiddle.net/t3hjonneh/FZJjW/
Text Field:
After Typing:
After Blur:
How it should look:
This is rather a hack than a proper solution, but somehow it works:
function blurred(elem) {
var range;
// IE only, probably not the best check since it will run in other browsers
// if they ever implement this feature
if (elem.createTextRange) {
range = elem.createTextRange();
range.collapse(true);
range.select();
}
}
<input type="text" onchange="blurred(this);" />
Notice the use of onchange instead of onblur. This is since select() causes some troubles when using onblur.
Here is a jQuery version I mocked up that works in all the major browsers:
$(document).ready(function(){
$('input[type=text]').change(function(){
try{//select nothing but side-effect is that text left justifies
if(/webkit/.test(navigator.userAgent.toLowerCase())){
return;//webkit browsers do it automatically
} else if(this.createTextRange) { //ie
var r = this.createTextRange();
r.collapse(true);
r.select();
} else if(typeof this.selectionStart !== "undefined") { //firefox
this.selectionStart = 0;
this.selectionEnd = 0;
}
} catch(err) {
//?? nobody cares ??
}
});
});
I'd just set a class on that field and then fire up a function with the onBlur in your html: e.g. onBlur="left()" Then in your javascript you can then simply change the class with .setAttribute As an added bonus you can also set other properties for that class as well.
Although I do support the notion of posting relevant code
I have an input element and I want to keep checking the length of the contents and whenever the length becomes equal to a particular size, I want to enable the submit button, but I am facing a problem with the onchange event of Javascript as the event fires only when the input element goes out of scope and not when the contents change.
<input type="text" id="name" onchange="checkLength(this.value)" />
----onchange does not fire on changing contents of name, but only fires when name goes out of focus.
Is there something I can do to make this event work on content change? or some other event I can use for this?
I found a workaround by using the onkeyup function, but that does not fire when we select some content from the auto completer of the browser.
I want something which can work when the content of the field change whether by keyboard or by mouse... any ideas?
(function () {
var oldVal;
$('#name').on('change textInput input', function () {
var val = this.value;
if (val !== oldVal) {
oldVal = val;
checkLength(val);
}
});
}());
This will catch change, keystrokes, paste, textInput, input (when available). And not fire more than necessary.
http://jsfiddle.net/katspaugh/xqeDj/
References:
textInput — a W3C DOM Level 3 event type. http://www.w3.org/TR/DOM-Level-3-Events/#events-textevents
A user agent must dispatch this event when one or more characters have
been entered. These characters may originate from a variety of
sources, e.g., characters resulting from a key being pressed or
released on a keyboard device, from the processing of an input method
editor, or resulting from a voice command. Where a “paste” operation
generates a simple sequence of characters, i.e., a text passage
without any structure or style information, this event type should be
generated as well.
input — an HTML5 event type.
Fired at controls when the user changes the value
Firefox, Chrome, IE9 and other modern browsers support it.
This event occurs immediately after modification, unlike the onchange event, which occurs when the element loses focus.
It took me 30 minutes to find it, but this is working in June 2019.
<input type="text" id="myInput" oninput="myFunction()">
and if you want to add an event listener programmatically in js
inputElement.addEventListener("input", event => {})
As an extention to katspaugh's answer, here's a way to do it for multiple elements using a css class.
$('.myclass').each(function(){
$(this).attr('oldval',$(this).val());
});
$('.myclass').on('change keypress paste focus textInput input',function(){
var val = $(this).val();
if(val != $(this).attr('oldval') ){
$(this).attr('oldval',val);
checkLength($(this).val());
}
});
Do it the jQuery way:
<input type="text" id="name" name="name"/>
$('#name').keyup(function() {
alert('Content length has changed to: '+$(this).val().length);
});
You can use onkeyup
<input id="name" onkeyup="checkLength(this.value)" />
You would have to use a combination of onkeyup and onclick (or onmouseup) if you want to catch every possibility.
<input id="name" onkeyup="checkLength(this.value)" onmouseup="checkLength(this.value)" />
Here is another solution I develop for the same problem. However I use many input boxes so I keep old value as an user-defined attribute of the elements itself: "data-value". Using jQuery it is so easy to manage.
$(document).delegate('.filterBox', 'keyup', { self: this }, function (e) {
var self = e.data.self;
if (e.keyCode == 13) {
e.preventDefault();
$(this).attr('data-value', $(this).val());
self.filterBy(this, true)
}
else if (e.keyCode == 27) {
$(this).val('');
$(this).attr('data-value', '');
self.filterBy(this, true)
}
else {
if ($(this).attr('data-value') != $(this).val()) {
$(this).attr('data-value', $(this).val());
self.filterBy(this);
}
}
});
here is, I used 5-6 input boxes have class 'filterBox',
I make filterBy method run only if data-value is different than its own value.
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();
});
}
}
I am looking to do the following
Disallow text selection inside of an input element
Do not show the cursor carrot inside of an input
i cannot simply blur the input on click, focus must remain in the input. There is probably a way to do this in just IE, i would of course rather have a cross browser solution but ill settle for IE (or FF) only solution.
Here is a demo page where you can see why i might need this functionality:
http://programmingdrunk.com/current-projects/dropdownReplacement/
if you click on the dropdowns in the first row on page, you will see the carrot inside the dropdown which looks funny. (this wont happen in chrome, but will in FF or IE)
A bit hacky, but:
onclick="this.selectionStart=this.selectionEnd=-1;"
onselect="this.selectionStart=this.selectionEnd=-1;"
Seems to work in Firefox (3.6.3).
Do us all a favor and hide it from the HTML, though (attachEvent magic).. And don't tell anyone I suggested this :)
I use the following function in my code, it's not JQuery but it should be fairly easy to convert:
function disableSelection(elm) {
// Disable the selection of `elm` - should work for all major browsers except Opera
// which doesn't seem to allow disabling selections unless the mousedown
// events etc are cancelled as far as I know
// Disable the select start event
elm.onselectstart = function() {
return false
}
// Disable in IE - see http://msdn.microsoft.com/en-us/library/ms534706(VS.85).aspx
elm.unselectable = "on"
// Disable in Mozilla - see https://developer.mozilla.org/en/CSS/-moz-user-select
elm.style.MozUserSelect = 'none'
// Disable Safari/Chrome
// See http://help.dottoro.com/lcrlukea.php
elm.style.webkitUserSelect = 'none'
// Disable in other browsers
elm.style.userSelect = 'none'
// Display a normal cursor
elm.style.cursor = "default"
}
You can disable text selection in some non IE browsers with CSS user-select.
-webkit-user-select:none;
-k-user-select:none;
-moz-user-select:moz-none;
user-select:none;
Not sure about IE.
As far as the effect you're trying to achieve, how about making the input invisible and have a div on top of the input that displays the value of the input?
If you need to change the value in the input, a click event on the div would direct focus to the input, and a keypress event would update the div.
Haven't tried it, but seems like it should work.
EDIT:
Use CSS to render the input invisible in order to retain tabbing functionality.
(Example assumes background is #FFF)
#myInput {
border-width:0;
color:#FFF;
background:#FFF;
outline:0;
}