How to handle events on dynamically added elements in jQuery - javascript

A fairly straightforward question - Why doesn't mouseover trigger for (text) inputs which are dynamically generated after the page has loaded?
I can get it to work for checkbox, select, textarea...
Below code doesn't give an event
$(document).ready(function () {
$(`input[type=text]`).on(`mouseover`, function (e) {
console.log(e);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text">
Below code gives an event for everything but text input:
$(document).ready(function () {
$(`input, textarea, [type=checkbox], select`).on(`mouseover`, function (e) {
console.log(e);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input>
<textarea></textarea>
<input type="checkbox">
<select>
<option>test</option>
</select>
How can I trigger mouseover event for a text input?
EDIT: The text inputs are dynamically generated after the document has loaded.
Thank you

You need to pass a second parameter to .on that allows for event delegation:
$(document).ready(function () {
// Set the handler up on something you know will be there from the start
// that the event(s) that get triggered later can "bubble" up to. That's
// document in this case.
// The second argument becomes what you want the event to be handled on
$(document).on(`mouseover`, "input[type='text']", function (e) {
console.log(e);
});
// Create a new element after the handler has been set up
$(document.body).append('<input type="text">');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Related

I have two input elements with class "inputWithLimit". Why would both be firing simultaneously and logging '0' as val().length?

$(document).ready(function() {
$(".inputWithLimit").each(() => {
var inp = this;
inp.addEventListener("input",
function (event){
console.log($(inp).val().length);
});
});
})
I've also tried "keyup" and "change" as event handlers, and in both other cases, jquery is doing a strange thing with assigning these listeners. Thanks.
If you are using jQuery then there is no need to loop through each element and add an event listener. An example which logs the value of each input when you input something.
$(document).ready(function() {
$(".inputWithLimit").on('input',function() {
console.log(this.value);
});
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input class="inputWithLimit">
<input class="inputWithLimit">
The problem is your arrow function. When using arrow function, then you can't use `this'
$(".inputWithLimit").on("input", function() {
console.log($(this).val().length);
});
I've also made your code shorter.
Demo
$(document).ready(function() {
$(".inputWithLimit").on("input", function() {
console.log($(this).val().length);
});
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input class="inputWithLimit" />

JQuery Trigger Event on Dynamically added elements programmatically

I can successfully bind an event to dynamically added elements, but I have a problem triggering it on its first load programmatically.
$('body').on('change', '#elem', function () {
console.log('bind event success');
});
I tried these codes below but do not work.
Not working
$('body').trigger('change');
Not working
$('body').on('change', '#elem', function () {
console.log('hello world');
}).change();
You can trigger an event on the DOM element #elem directly, as you can see here:
$('body').on('change', '#elem', function () {
console.log('new value is: '+this.value);
});
$("button").click(function(){$("#elem").val("3").change()})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="elem"><option>1</option><option>2</option><option>3</option></select>
<button>trigger change to 3</button>

What event does jQuery fire when using append on a textarea?

I'm trying to monitor for any changes in a textarea:
<textarea id="log-box__data"></textarea>
Changes are made to the textarea exclusively via jQuery append:
$(document).on('click', '#myBtn', function(e) {
$('#log-box__data').append('someText' + '\n');
});
What event is fired whenever something is append[ed] to the textarea?
And, if there isn't one, how can I monitor for this change?
Things I've Tried:
$(document).on('input change keyup paste', '#log-box__data', function() {
alert( "foobar" );
});
None of those events fire when #myBtn is clicked.
Using trigger function after append will help
$(document).on('click', '#myBtn', function(e) {
$('#log-box__data').append('someText' + '\n');
$('#log-box__data').trigger("change");
});
$('#log-box__data').on('change', function(e) {
alert( "foobar" );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="log-box__data"></textarea><br />
<button id="myBtn">add text</button>
append is not a good idea and also set a value will never call the onchange event so try below code to trigger manually
$("#myBtn").bind("click",function(){
$("#log-box__data").val("yourtexthere").trigger('change');
});

Add an onchange event listener to an html input field

I would like to add an onchange event to those input fields without jquery:
<input type="text" id="cbid.wizard.1._latitude">
<input type="text" id="cbid.wizard.1._longitude">
I can already call the object with
<script type="text/javascript">
alert(document.getElementById('cbid.wizard.1._latitude').id);
</script>
In the end, I want to add this behaviour, that if you enter a pair of coordinates into the first input, I will spread the pair over the two input fields?
How do I add an onchange event with javascript?
Ummm, attach an event handler for the 'change' event?
pure JS
document.getElementById('element_id').onchange = function() {
// your logic
};
// or
document.getElementById('element_id').addEventListener(
'change',
callbackFunction,
false
);
jQuery
$('#element_id').change(function() {
// your logic
});
Note
Note, that change event on the text field will be fired after the blur event. It's possible that your looking for keypress event's or something like that.
document.getElementById('cbid.wizard.1._latitude').onchange = function(){
//do something
}
GlobalEventHandlers.onchange docs
or
document.getElementById('cbid.wizard.1._latitude').addEventListener("change", function(){
//do something
});
EventTarget.addEventListener docs
use addEventListener in your window.onload
window.onload=function(){
document.getElementById('cbid.wizard.1._latitude').addEventListener("change", function(){
//do something
});
};
addEventListener
Please try with the below code snippet.
<body>
<input type="text" id="cbid.wizard.1._latitude">
<input type="text" id="cbid.wizard.1._longitude">
<script type="text/javascript">
var txt1 = document.getElementById('cbid.wizard.1._latitude');
txt1.addEventListener('change', function () { alert('a'); }, false);
</script>
</body>

adding click event to body when input is focussed on, then removing it on blur

I have a text input that I would like to, when it has focus, register a click event anywhere on the body. But when focus is removed from it, that click event is removed from the body. Sadly, I seem not to be able to suss it.
$(document).ready(function () {
$("html").on("focus", "#asdf", function () {
$("body").on("click", "*:not(#asdf)", wasItClicked);
});
$("html").on("blur", "#asdf", function () {
$("body").off("click", "*", wasItClicked);
});
});
function wasItClicked() {
alert("yeah");
}
BIN
Thanks for any help.
When #asdf is focused, and some other element is clicked, The events fire in order mousedown, blur, mouseup, click. So the handler has been removed before click fires.
The mousedown event fires before blur. If you are OK with mousedown instead of click, you could use this:
$(document).ready(function () {
$("#asdf").on("focus", function () {
$("body").on("mousedown", wasItClicked);
});
$("#asdf").on("blur", function () {
$("body").off("mousedown", wasItClicked);
});
});
(bin)
Edit:
You could use the mousedown event to help determine if you are losing focus because of a click, and remove the handler in the click handler if have lost focus.
$(document).ready(function () {
$("#asdf").on("focus",function() {
$("body").on("mousedown", setDown);
$("body").on("click", wasItClicked);
});
$("#asdf").on("blur", function() {
if ($(this).attr("mouse") != "down") {
$("body").off("mousedown", setDown);
$("body").off("click", wasItClicked);
}
});
});
function setDown() {
$("#asdf").attr("mouse","down");
}
function wasItClicked() {
if ($("#asdf") != $(document.activeElement)) {
$("body").off("mousedown", setDown);
$("body").off("click", wasItClicked);
}
$("#asdf").attr("mouse","up");
alert("yeah");
}
new bin
You could use setTimeout to remove the click and use namespaces when adding and removing events because you may accidentally remove another click handler but the simplest way would be to remove the click event in the handler:
...
$("body").on("click.fromasf", "*:not(#asdf)", wasItClicked);
...
function wasItClicked() {
$("body").off("click.fromasf");
console.log("yeah");
}
Here is an example using timeout:
<!DOCTYPE html>
<html>
<head>
<script src="jquery-1.9.0.js"></script>
<style>
</style>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<title>Example</title>
</head>
<body>
<input type="text" id="asdf" />
<input type="text" id="Text1" />
<script>
$(document).ready(function () {
$("html").on("focus", "#asdf", function () {
console.log("adding click handler");
$("body").on("click.fromasf", "*:not(#asdf)", wasItClicked);
});
$("html").on("blur", "#asdf", function () {
setTimeout(function () {
console.log("remove click");
$("body").off("click.fromasf");
}, 500);
});
});
function wasItClicked() {
console.log("yeah");
}
</script>
</body>
</html>
Ok, I see a couple of issues...
You're delegating a focus event to the HTML element for an event on
a single element... That's a bit of overkill, so I would put the
focus and blur events directly on the input
When you call off, you need to pass it the exact same selector in the second parameter
Your click event is delegated to the body, and firing on any child element that is clicked and matches the selector - this does not include the body itself... not sure if you wanted it that way, but I moved it up to the html element, to include the body
As soon as the input loses focus, the event will be removed, so the clicks won't register (You can use a timeout as #HMR suggested in their answer)
I had some problems with the delegation on the html element that was still returning the input (despite the :not(#asdf) selector) so I just put the filter into the function.
Here is the revised code (testing version):
var click_selector = ":not(#asdf)";
var click_target = 'html';
$(document).ready(function () {
$("#asdf").on("focus", function () {
$(click_target).on("click", click_selector, wasItClicked);
});
$("#asdf").on("blur", function () {
// Use timeout to be able to register the click before function is removed
// NOTE that since 'click' fires when the mouse is released, if they
// hold the mouse down for a while, the event will be gone and won't
// register. Maybe better to use 'mousedown' instead of 'click'
// in which case the timeout could probably be reduced to 10ms or something
// Also, using timeouts creates the possibility of multiple click handlers
// present at the same time (new one added before the previous is removed)
setTimeout( function(){
$(click_target).off("click", click_selector, wasItClicked);
}, 100);
});
});
function wasItClicked(e) {
e.stopPropagation();
e.preventDefault();
if( e.target.id !== 'asdf' ){
console.log('yeah', click_target, click_selector);
}
}

Categories

Resources