Perfect way to avoid blur event - javascript

There is a div and it contains input type text element inside it, this div gets visible on some button click and input gets focused every time, input inside div contain blur event and in that event it has to perform some calculations.
Now problem I am facing is when I set display none of that div its blur event is called although it is very logical.
<div id="main-container">
<div id="main">
<input type="text" id="name" />
</div>
<input type="button" id="btn" value="click me"/>
I have to avoid those calculations that is performed in blur event when its style property is display none so for this I place a check in blur event i.e.
if(style!='none')
This solves my problem but the purpose of writing this question here is to find a nice and efficient way to handle this problem?

It sounds like you've already solved the problem but are looking for an alternative. Unfortunately, there really isn't much else you can do aside from checking for visibility before doing your calculations.
You might want to just add the check in your blur event, if you haven't already:
var main = document.getElementById( 'main' );
document.getElementById( 'name' ).onblur = function() {
if( main.style.display != 'none' ) {
// do calculations
}
};
If, for whatever reason, you don't want to check the style.display, you could do a check similar to jQuery:
if( main.offsetWidth > 0 && main.offsetHeight > 0 ) {
// do calculations
}

var x = document.getElementById('btn');
if(x.style.display != 'none')
// do calculations

Related

Find Cursor in which input

I have two inputs
<input id="foo" name="foo"/>
<input id="bar" name="bar"/>
How to find cursor present in which input?
I am able to find position of cursor in it, but I need to know in which input cursor exists.
While other answers give you the current active element. I prefer to provide another answer which give you the exact 'which input' you asked.
<input id="foo" name="foo" onfocus="onfocus(this)" onblur="onblur(this)"/>
<input id="bar" name="bar" onfocus="onfocus(this)" onblur="onblur(this)"/>
<script>
var idOfInputFocused = ""; // what you need
function onfocus(input) {
idOfInputFocused = input.id;
}
function onblur(input) {
idOfInputFocused = "";
}
</script>
If you need to find the element that is currently active/on focus, use
document.activeElement
https://www.w3schools.com/jsref/prop_document_activeelement.asp
If the element has the cursor, it has the focus, you can find out using activeElement][1].
var activeElement = document.activeElement;
If you can't modify html, and need to know over which input cursor is positioned you can try such approach
document.addEventListener("mouseover", function(e) {
if(e.target.tagName === "INPUT") {
console.log(e.target.id);
document.getElementById("result").innerHTML = e.target.id;
}
});
Here you can find more information about events delegation - https://javascript.info/event-delegation, so you can wrap your inputs into some block and set event listener to that wrapper, listen any events on it and figure out what happened inside.
And be sure to remove event listener after necessary actions were performed)
Information about removing event listeners you can find here https://www.w3schools.com/jsref/met_element_removeeventlistener.asp.
link to test this solution https://www.w3schools.com/code/tryit.asp?filename=GB7P6V4ACH1O

Logging values from currently focused textarea

Let us assume that I have many textarea elements on my page, and my goal is to log the value of current textarea element that I am typing on.
I have managed to write the code that does just that, but the problem is that when type text in one textarea, and then switch to another and type in that for a while, when I come back to the first one, I get two .keyup() methods attached to that element. So I get two logs of that textarea value.
$( "body" ).click( function( event ) {
let element = event.target
if( element.nodeName === "TEXTAREA" ){
if($(element).focus()){
$(element).keyup(function(){
console.log(element.value)
})
}else {
$(element).unbind( 'keyup' )
}
}
});
What do I need to do to remove that method stacking?
You should never attach event inside another event because when the first fired the one inside will be attached another time and so on.
I suggest attaching the input event directly to the textarea's instead of keyup and nested events, so with the helps of this keyword you will get the current changed textarea element, like :
$("textarea").on('input', function(event) {
console.log($(this).val());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea></textarea>
<br>
<textarea></textarea>
<br>
<textarea></textarea>

jQuery blur-event not fired on hidden element

I'm simply trying to bind the blur event to a set of inputs found on my page.
var $urlTextBoxes = $(`input[type='url'][data-url-prefixer]`);
$urlTextBoxes.on("blur", onUrlTextBoxBlur);
whereas onUrlTextBoxBlur is a simple function checking the current value,
If the <input type="url" data-url-prefixer /> is already visible when prefixing with 'http://' if not already set.$(function () { // ... } is called, the onUrlTextBoxBlur is called on blur.
On the other hand, if the input is hidden on load (inside a div) and shown later, the onUrlTextBoxBlur is never hit and I don't get the point why?
I've tried
$(document).on("blur", $urlTextBoxes, onUrlTextBoxBlur);
which is not working at all.
Putting
if (jQuery._data($("#ExternalRegistrationUrl")[0] !== undefined)) {
console.log($("#ExternalRegistrationUrl")[0]);
console.log(jQuery._data($("#ExternalRegistrationUrl")[0], "events"));
}
shows
input#ExternalRegistrationUrl.form-control
Object {blur: Array[1]}
in master, and
input#ExternalRegistrationUrl.form-control
undefined
in my sub-view. Somehow, the event gots lost. But, how can this be? The Masters onReady is called before the SubViews onReady, or not?
Seems like another plugin is removing the content and re-adding it afterwards. Therefore, all bindings are lost. Now I need a way to re-bind by events after the plugin has done it's magic!
HIDDEN FIELD ALSO WORKING WITH BLUR
FIDDLE
SCRIPT
$(document).ready(function(){
$(":text").hide();
$(":text").blur(function(){
alert("Blurred");
});;
$(":text").show();
});
HTML
<input type="text" />
CSS
input
{
display:none
}

Detect the changes of the controls in a page using Jquery

I have page with around 20 to 30 controls based on the query string values. I need to change a button as disabled based on the value changes in the controls. For examble in the list of Check boxes if something is checked or unchecked, some texts added or removed etc... for all the controls.
The controls are textbox, option buttons, check boxes, select controls and list boxes.
I don't want to add static methods to all controls. I do have an idea of doing the late binding to all the controls and to attach events. And that events will disable the button whenever the event gets fired.
Is there any other way to do this functionality in a simple way(Like Keypress or using event property window object)?
As #ekhaled pointed out you can use the same handler to handle all the click and change events.
Here's a somewhat convoluted example:
<div id="container">
<input id="input1" type="text" value="" />
<select>
<option value="1">ABC</option>
<option value="2">EFG</option>
</select>
<input type="button" value="Submit" />
</div>
and the javascript for it:
$('#container').on("change click", ":input", function (event) {
if (event.target.nodeName == "SELECT") {
if ($(event.target).val() == "2") {
console.log("disable");
$(":button").prop("disabled", true);
} else {
$(":button").prop("disabled", false);
console.log("enable");
}
}
if (event.target.id == "input1" && $(event.target).val() == "") {
$(":button").prop("disabled", true);
}
});
See it working here.
However if you main concern is validation you should have a look at jquery validation
With jQuery validation you can set specific rules for each of the inputs that will make up the validation of the whole form. It is very customizable, you can change where and how the errors are displayed, when is the validation triggered, etc.
You can use event delegation and bind your event to the parent element, and then write all your logic inside that one event handler.
Can't really show you much, because you haven't included any examples or code. But something along the lines of:
$("body").on('change click', 'input, select', function(){
var _this = $(this);
if(_this.is('input[type=checkbox].className')){
//follow one logic
}
if(_this.is('input[type=radio].className')){
//follow another logic
}
//etc, etc
})

Why is my onchange function called twice when using .focus()?

TLDR
Check this example in chrome.
Type someting and press tab. see one new box appear
type something and press enter. see two new boxes appear, where one is expected.
Intro
I noticed that when using enter rather then tab to change fields, my onchange function on an input field was firing twice. This page was rather large, and still in development (read: numerous other bugs), so I've made a minimal example that shows this behaviour, and in this case it even does it on 'tab'. This is only a problem in Chrome as far as I can tell.
What it should do
I want to make a new input after something is entered into the input-field. This field should get focus.
Example:
javascript - needing jquery
function myOnChange(context,curNum){
alert('onchange start');
nextNum = curNum+1;
$(context.parentNode).append('<input type="text" onchange="return myOnChange(this,'+nextNum+')" id="prefix_'+nextNum+'" >');
$('#prefix_'+nextNum).focus();
return false;
}
HTML-part
<div>
<input type="text" onchange="return myOnChange(this,1);" id="prefix_1">
</div>
the complete code is on pastebin. you need to add your path to jquery in the script
A working example is here on jFiddle
The onchange gets called twice: The myOnChange function is called, makes the new input, calls the focus(), the myOnChange gets called again, makes a new input, the 'inner' myOnChange exits and then the 'outer' myOnchange exits.
I'm assuming this is because the focus change fires the onchange()?. I know there is some difference in behaviour between browsers in this.
I would like to stop the .focus() (which seems to be the problem) to NOT call the onchange(), so myOnChange() doesn't get called twice. Anybody know how?
There's a way easier and more reasonable solution. As you expect onchange fire when the input value changes, you can simply explicitly check, if it was actually changed.
function onChangeHandler(e){
if(this.value==this.oldvalue)return; //not changed really
this.oldvalue=this.value;
// .... your stuff
}
A quick fix (untested) should be to defer the call to focus() via
setTimeout(function() { ... }, 0);
until after the event handler has terminated.
However, it is possible to make it work without such a hack; jQuery-free example code:
<head>
<style>
input { display: block; }
</style>
<body>
<div></div>
<script>
var div = document.getElementsByTagName('div')[0];
var field = document.createElement('input');
field.type = 'text';
field.onchange = function() {
// only add a new field on change of last field
if(this.num === div.getElementsByTagName('input').length)
div.appendChild(createField(this.num + 1));
this.nextSibling.focus();
};
function createField(num) {
var clone = field.cloneNode(false);
clone.num = num;
clone.onchange = field.onchange;
return clone;
}
div.appendChild(createField(1));
</script>
I can confirm myOnChange gets called twice on Chrome. But the context argument is the initial input field on both calls.
If you remove the alert call it only fires once. If you are using the alert for testing only then try using console instead (although you need to remove it for testing in IE).
EDIT: It seems that the change event fires twice on the enter key. The following adds a condition to check for the existence of the new field.
function myOnChange(context, curNum) {
nextNum = curNum+1;
if ($('#prefix_'+nextNum).length) return false;// added to avoid duplication
$(context.parentNode).append('<input type="text" onchange="return myOnChange(this,'+nextNum+')" id="prefix_'+nextNum+'" >');
$('#prefix_'+nextNum)[0].focus();
return false;
}
Update:
The $('#prefix_'+nextNum).focus(); does not get called because focus is a method of the dom object, not jQuery. Fixed it with $('#prefix_'+nextNum)[0].focus();.
The problem is indeed that because of the focus(), the onchange is called again. I don't know if this is a good sollution, but this adding this to the function is a quick sollution:
context.onchange = "";
(The onchange is called again, but is now empty. This is also good because this function should never be called twice. There will be some interface changes in the final product that help with problems that would arise from this (mistakes and all), but in the end this is something I probably would have done anyway).
sollution here: http://jsfiddle.net/k4WKH/2/
As #johnhunter says, the focus does not work in the example, but it does in my complete code. I haven't looked into what's going on there, but that seems to be a separate problem.
maybe this some help to anybody, for any reason, in chrome when you attach an event onchage to a input text, when you press the enterkey, the function in the event, do it twice, i solve this problem chaged the event for onkeypress and evaluate the codes, if i have an enter then do the function, cause i only wait for an enterkey user's, that not works for tab key.
input_txt.onkeypress=function(evt){
evt = evt || window.event;
var charCode = evt.which || evt.keyCode;
if(charCode === 13) evaluate( n_rows );
};
Try this example:
var curNum = 1;
function myOnChange( context )
{
curNum++;
$('<input type="text" onchange="return myOnChange( this )" id="prefix_'+ curNum +'" >').insertAfter( context );
$('#prefix_'+ curNum ).focus();
return false;
}
jsFiddle.

Categories