Trigger Event on Ajax generated Element - javascript

I can't use any Event (eg. onlick) on any ajax generated element. I read about jQuery's ".on" function, but I need to use something like <div id="myId_1234" onlick="doStuff()">.
The Id of the Element is random, so I can't use
`$('.some-parent-class').on('click', '.element', function() {// DO STUFF!});`
I hope someone can help me! Thanks.

You could attach the event handler to your element in the AJAX response before adding it to the DOM by using
$(responseHtml).find('some selector').on('click', handler);
There is most likely one or more attribute selectors that will work for you.
Ex: id begins with selector
$(responseHtml).find('div[id^=myId]').on('click', handler);
If you cannot differentiate which element in the response you need with a css selector you will have to modify the server script generating the HTML with a unique id or class that matches a pattern you can look for.
EDIT
You CAN use a css class to identify each element. use:
$('.myCloseButtonClass').on('click', function(){ $(this).parent.hide(); });
The key here is the this object. It will reference the specific element that was clicked thereby allowing you to close only the chat window that contains the clicked close button.
JSFiddle using AJAX echo

$('.some-parent-class').on('click', 'this put your id input', function() {// DO STUFF!});
proib with this......

You could do something like:
<div class="myBoxes">
<div id="oneBox" onclick="myFunc(this.parentNode);">
<p>Some content..</p>
</div>
</div>
function myFunc(){
// Code goes here
alert('function fired!');
}

I am simulating the Ajax Generated part by dynamically generating a clickable DIV element.
HTML:
<div id="container">
</div>
JS:
$("#container").append(
$('<div>').attr('id', 'randomId').html('New element')
);
$("#randomId").click( function(){
alert('Clicked!!!');
});
EDIT: Same example using class instead of Id:
$("#container").append(
$('<div>').attr('id', 'randomId').addClass('parent-class').html('New element')
);
$(".parent-class").click( function(){
var clickedElementId = $(this).attr("id");
alert('Element with ID ' + elementId + ' Clicked!!!');
});
Working fiddle

Related

JS delegate unique event (one()) for dynamic declared elements

I'm working on js-project. Some parts of HTML is generating via JS like this:
html += '<div class="button"><a href="' + url1 + '>' + button_text1 + '</a></div>';
html += '<div class="button"><a href="' + url2 + '>' + button_text2 + '</a></div>';
What I want is create listener to the first click for each of the buttons.
Idea 1: Use $(.button a).live('click', doSomething) because of dynamic declaration. Sadly, there's no way to force trigger only on the first click like that. Also deprecated.
Idea 2: Use $(.button a).one('click', doSomething). Not working because of on() might fail to find selector when DOM is ready, but still rendering ($(document).ready(...)). See details here: https://jqueryhouse.com/jquery-on-method-the-issue-of-dynamically-added-elements/
Idea 3: Use $(body).one('click', '.button a', doSomething), i.e. delegate event as noted source suggests.
But it seems like JS is read it not as "Here is an array of elements; for each element add one('click') event", but as "Add one('click') event for click on any element from an array", because an event is triggered only once no matter what button I have clicked.
I was really trying to find any clues to how manage this situation but got no luck. I will be really grateful for help or another idea how to solve this!
«I want is create listener to the first click for each of the buttons.»
The keyword here is each.
Try that:
$(.button a).each(function(){
$(this).one('click', doSomething); // (!)No prenthesis here... Just the function name.
});
Documentation for the .each() method.
Since you append new elements dynamically... After you appended html to a container, run a similar each loop on them like this:
// Assuming you do this
$(".container_selector").append(html);
// Then run the each loop
$(".container_selector").find(".button a").each(function(){
$(this).one('click', doSomething); // (!)No prenthesis here... Just the function name.
});
You are overthinking things. So use event delegation and some flag that says if it has run or not.
$(document).on('click', '.test', function() {
var elem = $(this) // what was clicked
if (elem.data('clicked')) { // see if we clicked it
return false // if yes, ignore the click
}
elem.data('clicked', true) // mark it was clicked
elem.html((new Date).toLocaleString()) // do something
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test">1</div>
<div class="test">2</div>
<div class="test">3</div>
<div class="test">4</div>
Or go off a class that has not run and remove it
$(document).on('click', '.test-run', function() {
var elem = $(this) // what was clicked
elem.removeClass('test-run') // remove class so will not be clickable
elem.html((new Date).toLocaleString()) // do something
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test test-run">1</div>
<div class="test test-run">2</div>
<div class="test test-run">3</div>
<div class="test test-run">4</div>

Get custom css property with a function

This is my code :
<html>
<body>
<button class="myclass" data-card-id="1">Save</button>
</body>
</html>
My question is how whould look like a function that when user click on any of "myclass" buttons submit a variable with data-card-id of the specific card in a php file.
Thank you ! :)
this is using Jquery:
$(".myclass").click(function(){
$(this).attr( "data-card-id" );
});
JSFIDDLE - http://jsfiddle.net/q5j8z/11/
see browser console for data display
// change the selector "ul li a" to your button
$('ul li a').click(function (e) {
e.preventDefault();
var value = $(this).data('value');
$('.button').data('value', value);
console.log($('.button').data('value'));
});
$('.button').click(function (e) {
e.preventDefault();
console.log($(this).data('value'));
});
This can be accomplished through an additional selection feature. I believe "data-card-id" is an attribute of your html tag, so you have two choices.
Bind the click to the element using the selector or delegate it to the body of the document, I think you'll see how either way works here.
Option 1. The advantage here is that when click events bubble up to the body this will check and execut appropriately, even if other buttons are added to the page after this code is executed. This is jquery's click delegation feature
$('body').on('click', 'button[data-card-id="1"]', function(){
//perform your action
});
Option 2. This binds the click event to the object itself. This can be more straight forward and has its advantage in simplicity.
$('button[data-card-id="1"]').click(function(){
// perform some action
});
And of course you have a plethora of other approoaches......
or
$('button').each(function(){
if($(this).attr("data-card-id") == '1'){
$(this).click(function(){
//some action
});
}
});
There are other approaches, too. Let me know if none of these seem to work.
JS FIDDLE DEMO
The most simpler would be to use this code -- >
just change this card-id to this cardid
HTML
<button class="myclass" data-cardid="1">Save</button>
<button class="myclass" data-cardid="2">Save</button>
JS
$(document).ready(function(){
$(".myclass").on('click',function(){
var cid = $(this).data("cardid");
alert(cid);
});
});

get id of first child of class and then trigger onclick event of that

I am dynamicaly creating html as below,
<div id="disc_cat">
<ul class="viewCatList">
<img id="prod1" src="../products/ `Image_url`" class="slide_contain" onclick="getCanvas(1,1,1,1,1,1,1,2,' `Image_url`')">
<img id="prod3" src="../products/ `Image_url`" class="slide_contain" onclick="getCanvas(1,1,1,1,1,1,1,2,' `Image_url`')">
</ul>
</div>
I am trying to trigger click event of first image , but i dont know the id.
I tried ,
$( "ul.viewCatList" ).find("img:first").attr("id"));
and many things , what is the correct way to get id of first child in viewCatList
Why do you want the id, once you have the jQuery wrapper for the element just call the click() on that
$( "ul.viewCatList" ).find("img:first").click()
The below code will get you the first id of image and then you can use along with # for click event..Comment here for further queries
$(document).ready(function(){
var x=$( "ul.viewCatList" ).find("img:first").attr("id");
alert(x);
$("#"+x).click(function(){
// do your stuff here..
});
});
$( "ul.viewCatList" ).find("img:first").attr("id"));
is working fine. It gives your the ID "prod1" of first image element.
But as you know, that click event is bind on jquery element object. So you can directly call click event on $( "ul.viewCatList" ).find("img:first") like below.
$( "ul.viewCatList" ).find("img:first").click(function(){
console.log("Here is your image1")
})

jQuery Nested Plugins Selector Issue

I'd like the ability to nest one plugin within another. However my selectors are too aggressive and keep retrieving the elements for the nested plugin aswell.
For example given the following HTML:
<div class="my-plugin">
...
<div class="my-plugin">
...
<button class="select">Select</button>
</div>
</div>
With the following code to create the plugin:
$(function() {
$('.my-plugin').myPlugin();
});
When I say the following (within my plugin):
// element is the element the plugin is attached to
$('.select', element);
This will retrieve the select element from the nested plugin within the outer plugin but I'd like it not to. Also I'd like to do the same when attaching click events. For example the following code should only attach the click event in the nested plugin and not within the outer plugin.
element.on('click', '.select', function(e) {
...
});
I hope I've explained that clearly. I'd appreciate if someone could show me how my selector can be improved to handle this. Thanks
The problem is, selectors work against the context they're given. If you tell jQuery to search a div, it will search everything in that div for what it's looking for. It's just how jQuery works.
If you want to exclude the inner plug-in, give it an id and exclude it using .not(). Or you could give it a class or data-* attribute as well. We just need something to tag it as "do not include".
So, do this:
$('.select', element).not('#mySecondPlugin');
or:
$('.select', element).not('.mySecondPlugin');
or:
$('.select', element).not('[mySecondPlugin="true"]');
This selector will select everything within your outer element EXCEPT the inner one and its contents.
And finally:
$('.select', element).not('[mySecondPlugin="true"]').on('click', function(e) {
...
});
You can use jQuery .closest() to find the first occurrence of a selector from an element. So you could target the nested div with #('.select').closest('.my-plugin').
Using jQuery .filter():
var myPlugin = this;//or whatever is representing your plugin jQuery object.
var selectsYouWant = $('.my-plugin .select').filter(function(index){
if(this.closest('.my-plugin') === myPlugin) {
return true;
} else {
return false;
}
});
You need to understand events. When you click on the element, event bubbles up the DOM tree. You need to stop propagation, so that it would not reach outer plugin handler. Depending on the logic you may also need to prevent default action:
element.on('click', '.select', function(e) {
e.stopPropagation();
e.preventDefault();
// ...
});
Also, not sure what is the logic inside plugin, but you can filter out inside items:
var button = $('.my-plugin').find('.select').not('.my-plugin .my-plugin *');
button.css('color', 'red');
See: FIDDLE
This is the approach I recommend.
At initialization:
$(element).addClass('my-plugin');
var $selects = $(element).find('select')
.not( $(element).find('.my-plugin select') );
You would have to make sure that the element and $selects variables are accessible to all functions in the plugin.
On the note about on(), here's what I would suggest:
element.on('click', '.select', function(){
// see if the closest .my-plugin is the matching element, and not
// a child plugin
if ( ! $(this).closest('.my-plugin').is( element ) )
return;
...
});
Try to start outside of your first plugin:
for example:
<div class="plugin-wrapper">
<div class="my-plugin">
...
<button class="select">Select</button> //We want this one
<div class="my-plugin">
...
<button class="select">Select</button> //Without this one
</div>
</div>
</div>
You would then be able to use something like $('.plugin-wrapper > .my-plugin > .select') which would get ONLY the first .select without the second. Which I believe is what you are trying to accomplish
For the onclick
$('.plugin-wrapper > .my-plugin > .select').on('click', function () {
//Your code here
});

jQuery delegateing inside div > divs > a also :(

html:
<div id="a">
<a id="a0" href="#"></a>
<div id="b"><a id="b0" href="#"></a><div>
<div>
jQuery:
$('#a').delegate('a', 'click', function(){ //do stuff });
delegates #b0 as well. Is there any clever selector way of ways to ignore #b ?
NB /// links inside divs are added and detached dynamically ///
ty
if you know it's only direct descendants try
$('#a').delegate('#a>a', 'click', function(){ alert('a') });
if you know you want to ignore children of b try
$('#a').delegate('a:not(#b>a)', 'click', function(){ alert('a') });
EDIT: a fiddle
This is working as expected. Your delegate() call will set event handler for all children under #a that match selector a.
If you are trying to set handler for a specific element then do that
$('#a0').click(function(){ ... });
Also your html is pretty broken. Make sure closing tags actually closing.
The first field in the delegate method is the selector. As of now, you are selecting all the anchors. Use id instead.
jQuery1.7 or above
$('#a').on('click', '#a0', function(event) {
alert(event.target.id);
});

Categories

Resources