Is there an alternative to JQuery`s event delegation? - javascript

I want to be able to assign a function to keypress of elements that don't exist when the DOM loads. In jQuery the code I had is like this
$(document).on('keypress', '.sc-chat-window .sc-user-input--text, #waste-form input,#address,.waste-wise-container .form-control,.widget-box .form-control,#aria-main-search-form-field,#footer-search-field,#aria-feedback-form-field', function(e) {
updateLastTypedTime();
});
It worked fine, but the problem is I can't use jQuery anymore and I would like to use Pure JavaScript this is what I have. The issue is that some elements don't exist yet so when this runs, it doesn't add the eventListener to the selectors.
JS:
var keyPressElements = document.querySelectorAll('form[id="4840400"],#waste-form input,#address,#aria-main-search-form-field,#footer-search-field,#aria-feedback-form-field');
keyPressElements.forEach(function(elem) {
elem.addEventListener('keypress', function() {
updateLastTypedTime();
});
});
How can I fix this issue?

Related

JQuery select elements in <span> that doesn't exist initially

I've been looking for so long and found several answers that suggest using .on() as in $('.idOfMyElemenet').on() works even for elements that don't exist yet. But this doesn't seem to be finding the element. Am I doing something wrong?
The highest level <span> (in screenshot) does not exist until I click on a drop-down. Ultimately I'm trying to trigger an event when the user clicks on any of the <li> (aka selects an option from the drop-down).
$(document).ready(function () {
var test = "#select2-id_customer-results";
$(test).on("click", function() {
console.log('hello')
})
})
EDIT:
Thanks to Drew Baker - I think his second solution is the way to go. But not quite there yet...
From the select2 documentation
All public events are relayed using the jQuery event system, and they
are triggered on the <select> element that Select2 is attached to.
So I tried listening to it via the id (which doesn't seem to exist but would probably be id_customer) and the class. The class I added below did not work. Is there a way to listen to this using Jquery?
$(document).ready(function () {
// console.log($('#id_customer'));
$('.modelselect2 form-control select2-hidden-accessible').on('select2:select', function (e) {
var data = e.params.data;
console.log(data);
});
});
I'll answer your question, but then give you a better solution.
First, you need to make sure the thing you are attaching .on() to actually exists. I typically use a containing DIV or failing that body or html will work.
Secondly you are missing a parameter that tells jQuery the thing you are looking to watch to be clicked on. In this case, I'm assuming it is the UL tag with the ID you provided.
This should do what you want:
$(document).ready(function () {
$('body').on("click", "#select2-id_customer-results", function() {
console.log('hello')
})
})
But a better solution would be to use the Select2 API to have it tell you when something is selected. This will be way more reliable and should make your code work after upgrades to Select2.
Something like this:
$('select[name="customer"]').on('select2:select', function (e) {
var data = e.params.data;
console.log(data);
});
NOTE: #mySelect2 is probably not what you have. Use whatever ID you used to initialize Select2 in jQuery.
You can read more about that API here: https://select2.org/programmatic-control/events
if your element is dynamically generated and you want to target that specific element. You need to specify a static container/parent element to indicate where it belongs.
Try this:
$( '#dynamicallyAddedElement' ).on( 'click', '#wrapper', function () { ... });
//where #wrapper is a static parent element in which you add the dynamic links.
So, you have a wrapper which is hard-coded into the HTML source code:
PS. Hope I helped in some way.
If you need to trigger an event when click on <li> elements, you have to use that elements id or class as the selector. Check the below code:
$(document).ready(function () {
var test = ".select2-results__option";
$(test).on("click", function() {
console.log('hello')
})
})
It turns out this is an old bug in django-auto-complete.
The code below works. I have no idea why but now I can move on.
Note: the 'name' is the value of the select2 select element (see screenshot at bottom)
document.querySelector('select[name="customer"]').onchange=function() {
console.log("myselect2name changed");
};

How to reattach event bindings after DOM is completely changed [duplicate]

This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 4 years ago.
I am working on a C# Razor site and I am POSTing from a boostrap modal which then returns a new view and model. To reload the entire page with the response, I am using the following line within this code block.
$("html").html(response);
function addDevice(e) {
e.preventDefault();
var ID = $("#txtNewDeviceID").val();
var Name = $("#txtNewDeviceName").val();
$.post('#Url.Action("AddDevice", "Devices")', { 'DeviceID': ID, 'DeviceName': Name }, function (response) {
$('#newDeviceModal').modal('hide');
$("html").html(response);
AttachBindings();
});
}
Here is the code behind AttachBindings():
function AttachBindings() {
$(document).on('click', 'table tr', {}, tableClick);
$(document).on('keyup', '#search', {}, search);
$(document).on('click', '#btnAdd', {}, function (e) {
addDevice(e);
});
$(document).on('click', '#btnRemove', {}, function (e) {
removeDevice(e);
});
$(document).on('click', '#btnUpdate', {}, function (e) {
updateDevice(e);
});
}
Unfortunately AttachBindings() is never hit and I can't seem to find a way to reattach these events. The only event that seems to work is keyup which is attached to #search. Any ideas on how to fix this?
Try using live function and call it on document.ready
As per the details provided in the documentation for LIVE:
Description: Attach an event handler for all elements which match the
current selector, now and in the future.
Hence, even if an element is added later in the DOM, the event will be triggered by that element
Whereas, in the case of ON, it will be added to the present elements only:
Description: Attach an event handler function for one or more events
to the selected elements.
So, calling it once, after document is ready and bind the events using bind or live will do the magic for you.
I doubled checked this morning and the events are being hit the way I have it. The real issue is the bootstrap modal that I have on the page does not work if the DOM has been updated. It looks like I will need to reconnect the data-toggle and data-dismiss events. I'm guessing bootstrap does this in the background when the page first loads.
Also the .Live method is deprecated according to the JQuery documentation.
As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event >handlers. Users of older versions of jQuery should use .delegate() in preference >to .live().
Also AttachBindings does not need to be called more than once. My code updated looks like this now:
function addDevice(e) {
e.preventDefault();
var ID = $("#txtNewDeviceID").val();
var Name = $("#txtNewDeviceName").val();
$.post('#Url.Action("AddDevice", "Devices")', { 'DeviceID': ID, 'DeviceName': Name }, function (response) {
$('#newDeviceModal').modal('hide');
$("html").html(response);
});
}

event listner not working for appended items

hey all i am appending a form to a page on click the form has some text boxes and i need to add event listner like on keypress but the function dosent works dont know where is the problem the function works well everywhere but not for this form here is the code.
appending the form
function activityCHART(thisobj){
var theidis=$(thisobj).attr("id");
$("#FULL_FADE").fadeIn();
$.ajax({
type: 'post',
url: 'newpage.php',
data:{'actde':theidis},
success: function(dataa){
$("#the_APPEDEDr5").empty().append(dataa);
}});}
newpage this textbox is present and some more text areas
<input type="text" name="deptname" placeholder="department name" id="detp_names09o" class="TEXTNAME_o909ioi"/>
add this event listner
$('#detp_names09o').keypress(function (e) {
alert('ok');});
these are some script links
src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
i think there are some script link problem
alert comes when i does it like this onkeyup="thisisfun();" function thisisfun(){ alert('ok'); }
You should use live(), delegate() or on() to attach event listeners to dynamically added DOM elements. bind() and keypress() doesn't work for elements that are dynamically added to DOM[see this]
$('#detp_names09o').live("keypress",function (e) {
//do some stuff
});
.on() is mostly syntax sugar that can mimic .live(), or .delegate() depending on how you call it.
$('#detp_names09o').on("keypress",function (e) {
//do some stuff
});
Also, you have specified two different versions of jQuery. Though CDN's do have some advantages over locally referenced libraries, they might break your code at-times.
If thats the reason you've referenced to local jQuery file(along with CDN version), you might consider looking at CDN fallbacks. In either case, you should be careful about the version you are using.
Cheers!
To attach event to dynamically added elements,
Try binding the event using 'bind'
$('#detp_names09o').bind("keypress",function (e) {
alert('ok');
});
or use 'on'
$('#detp_names09o').on("keypress",function (e) {
alert('ok');
});
Also you dont require two versions of jquery in your page, also make sure this id is not duplicated
use onkeyup,.. attribute inside the element and call the function like this
<input type="text" name="deptname" placeholder="department name" id="detp_names09o" class="TEXTNAME_o909ioi" onkeyup="functionName()"/>
in javascript
function functionName(){
//your code
}
First of all you should decide what do u want to use, keyup or keypress ? For example if you want to use keyup and you are using jquery version greater than 1.7 then use
$(document).ready(function () {
$('#element').on("keyup",function () {
alert('result ok');
});
});
else u can use
$(document).ready(function () {
$('#element').live('keyup', function() {
alert('result ok');
});
});
Make sure that you are calling working script (check your script link), try not to make duplicate ids of elements instead use class and avoid using inline use of javascript. Happy Coding !

jQuery on(click) doesn't work but on(hover) does

After initialize js I create new <div> element with close class and on("click") function doesn't work.
$(document).on('click', '.post-close', function () {
alert("hello");
});
but on('hover') work perfectly.
$(document).on('hover', '.post-close', function () {
alert("hello");
});
but I need to make it work on click.
It's because you're not preventing the default behaviour of the browser. Pass e into your handler and then use e.preventDefault()
$(document).on('click', '.post-close', function (e) {
e.preventDefault();
alert("hello");
});
Edit
Also, bind the handler before creating the new <div>
why not use something like
$('.post-close').click(function(){
//do something
});
If the element was added dynamically use:
$(document).on('click', '.post-close', function(){
//do something
});
edit:
like danWellman said, you can add the preventDefault IF you want to make sure no other code is executed. otherwise use the code above.
edit2:
changed the .live to .on
It's an old post but I've had a exactly same problem (element created dynamically, hover works, but click doesn't) and found solution.
I hope this post helps someone.
In my case, I found ui-selectable is used for parent element and that was preventing from click event propagate to the document.
So I added a selector of the button element to ui-selectable's 'cancel' option and problem solved.
If you have a similar probrem, check this
Try turn of libraries for parent element
You're not using stopPropagation() in parent element ?

Add click event to Div and go to first link found

I think I've been too much time looking at this function and just got stuck trying to figure out the nice clean way to do it.
It's a jQuery function that adds a click event to any div that has a click CSS class. When that div.click is clicked it redirects the user to the first link found in it.
function clickabledivs() {
$('.click').each(
function (intIndex) {
$(this).bind("click", function(){
window.location = $( "#"+$(this).attr('id')+" a:first-child" ).attr('href');
});
}
);
}
The code simply works although I'm pretty sure there is a fairly better way to accomplish it, specially the selector I am using: $( "#"+$(this).attr('id')+" a:first-child" ). Everything looks long and slow. Any ideas?
Please let me know if you need more details.
PS: I've found some really nice jQuery benchmarking reference from Project2k.de here:
http://blog.projekt2k.de/2010/01/benchmarking-jquery-1-4/
Depending on how many of these div.click elements you have, you may want to use event delegation to handle these clicks. This means using a single event handler for all divs that have the click class. Then, inside that event handler, your callback acts based on which div.click the event originated from. Like this:
$('#div-click-parent').click(function (event)
{
var $target = $(event.target); // the element that fired the original click event
if ($target.is('div.click'))
{
window.location.href = $target.find('a').attr('href');
}
});
Fewer event handlers means better scaling - more div.click elements won't slow down your event handling.
optimized delegation with jQuery 1.7+
$('#div-click-parent').on('click', 'div.click', function () {
window.location.href = $(this).find('a').attr('href');
});
Instead of binding all the clicks on load, why not bind them on click? Should be much more optimal.
$(document).ready(function() {
$('.click').click(function() {
window.location = $(this).children('a:first').attr('href');
return false;
});
});
I would probably do something like;
$('.click').click(function(e){
window.location.href = $(this).find('a').attr('href');
});

Categories