I'm not sure, how to use .click in the right way.
I looked at the manual (http://api.jquery.com/click/) but could not find the answer for my problem:
I'm generating an div structure with JS like this:
<div>
<img id='img_1' src="click.gif">
</div>
<div id='content_1'> Text</div>
Lots of those blocks are generated with the following function. At the end, each image gets an click event to change the css of the related text: click on img_1 changes css on content_1.
I try this code (simplified version):
$.each(data, function(selector,content) {
id=prepare(selector);
$('#boxDiv').append(' <div>\
<img id="img_'+id+'" src="click.gif">\
</div>\
<div id="content_'+id+'"> Text</div>');
$('#img_'+id).click(function(a) {
$('#content_'+id).css('height','100px');});
});
But this code does not work as I exacted.
Every 'img_'+id Element gets his related click event (so far, so god)
But the function does not change the css of the related 'content_'+id! All the time, the last content element is changed.
It looks like, that the .click call-back function does not get the idat the time of adding click event, but at the time of execution the callback function. At this time, the id is (of course) always the last element.
So the question is, how to bring the current (related) id inside the .click -callback function?
//Update: I'm not sure, if using live() could help in this case: i tried this, without any success.
The problem is not an missing click event. The Problem is, that at every click, the callback-function is fired by using the last id.
Example.
The generated content looks like this:
<div>
<img id='img_1' src="click.gif">
</div>
<div id='content_1'> Text</div>
<div>
<img id='img_2' src="click.gif">
</div>
<div id='content_2'> Text</div>
<div>
<img id='img_3' src="click.gif">
</div>
<div id='content_3'> Text</div>
The JS code binds one click event to img_1, one click event to img_2 and one click event to img_3.
I changed the content of the callback function to:
$('#expand_'+id).live('click',function() {console.info(id);});
SO i see the content of ID: by clicking img_1 or img_2 id is 3. Probably because, 3 is the last value for the each loop. So how can i get the related id inside the call-back?
Thank you for any kind of help.
Found the problem in your fiddle (and your updated code):
You forgot to put varin front of id, which makes it global. All event handlers reference the same id and its value is the one from the last iteration.
Declare it as
var id = ....;
to make it local.
That said, I would use jQuery to create all the elements:
$.each(data, function(selector,content) {
var id = selector;
var $img = $('<span />', {
id: 'img_' + id,
text: 'click'
}).click(function() {
$('#content_'+id).css('height','100px');
});
var $div = $('<div />', {
id: 'content_' + id,
text: 'Text'
});
$('<div />').append($img).append($div).appendTo('#boxDiv');
});
There are also other ways to find the #content_X elements. In your structure, this element is always the next sibling of the parent of the image. So instead searching for the element with this ID, inside the event handler, you could do:
$(this).parent().next().css(...);
Or even bind the event handler to the parent div instead directly to the image.
The click event handler will have access to the id (and content) variable, as it's defined in the parent function. In JavaScript, inner functions have access to all the variables of the function in which they are defined.
The problem is simply that you are missing the # ID selector from a couple of your jQuery selector string:
$('#boxDiv').append('...');
//some code removed
$('#content_' + id).css('height', '100px');
Instead of using the .click call-back function, you should use the .live call-back function. Quoting the jquery docs:
"Description: Attach a handler to the event for all elements which match the current selector, now and in the future."
Try this:
$.each(data, function(id,content) {
$('boxDiv').append(' <div>\
<img id="img_'+id+'" src="click.gif">\
</div>\
<div id="content_'+id+'"> Text</div>');
$('#img_'+id).live('click', function() {
$('content_'+id).css('height','100px');});
});
Don't you mean
$.each(data, function(id,content) {
$('#boxDiv').append(' <div>\
<img id="img_'+id+'" src="click.gif">\
</div>\
<div id="content_'+id+'"> Text</div>');
$('#img_'+id).click, function(a) {
$('#content_'+id).css('height','100px');
});
});
? There were two missing # before ID
Related
How do i even put these, let me try. In the following sets of codes, i want to click 'parentclass' and have an alert value of 'child1' and when i click the class below it which is 'Parent 2' have an alert fire with a value of 'child2'
So this must alert the content of that class only and not the entire class.
Here's some Javascript in Jquery.
var childclass = $('.childclass').html();
$('.parentclass').click(function(e) {
alert (childclass)
});
$('.childclass').click(function(e) {
e.stopPropagation()
e.preventDefault()
});
And HTML
<a href="" onClick="return false">
<div class='parentclass'>
Parent 1
<div style="display:none" class="childclass">child1</div>
</div>
</a>
<a href="" onClick="return false">
<div class='parentclass'>
Parent 2
<div style="display:none" class="childclass">child2</div>
</div>
</a>
This line var childclass = $('.childclass').html(); doesnt make sense as it doesn't know which element in particular you mean. The result of that will just be child1child2 which is just a concatenation of the .html() of all the elements with class childclass. This is obviously not what you want.
Therefore you should dynamically find the child with a class of childclass upon receiving the click event.
$('.parentclass').click(function(e) {
alert($(this).find('.childclass').html())
});
Also, you should know that your child class event handler is useless as we don't care if the event gets propogated downwards. If you DID care, then your e.stopPropagation() and e.preventDefault() should be in the event handler of the parent class.
You need to fetch the html of the clicked parent element within the click handler
$('.parentclass').click(function (e) {
alert($(this).find('.childclass').html())
});
$('.childclass').click(function (e) {
e.stopPropagation()
e.preventDefault()
});
Demo: Fiddle
Several ways you can go about this.
First, if your HTML will not be dynamic (elements already exist when page loads), then you can select elements by the parent class name and assign click event as so:
$('.parentclass').click(function(e) {
// the first variable here is selecting the inner elements having class 'childclass'
// keep in mind, if more than one child having that class is present within this parent, it will select all of them
var child = $(this).find('.childclass');
// here we alert the text of the inner child found
// if it is more than one, you will have undesired results. you may want to specify `.first()`
alert(child.text())
})
For newer jQuery you can also use $('.parentclass').on('click', function(e) {.
If you expect any pieces of parentclass to be dynamic, then you'll want to delegate the event based on either a static parent to the parents or document. This can be like so:
$(document).on('click', '.parentclass', function(e) {
alert($(this).find('.childclass').text())
})
Or, if you have a static (already there when page loads) wrapping element, give it an ID like `parentClassWrapper' and assign the click event dynamically as:
$('#parentClassWrapper').on('click', '.parentclass', function(e) {
alert($(this).find('.childclass').text())
})
Some helpful links:
jQuery API
jQuery Selectors
.click()
.on()
Some info on Event Delegation
jquery on vs click methods
jQuery .on('click') vs. .click() and .delegate('click')
jquery .live('click') vs .click()
I made several adjustments to your html that are worth noting. There's no need for the <a> tag. Don't use inline js - onlick in your html. Note that I wrapped the text inside of the div in the <a> tag instead. This markup is more semantic. Also, move your styles to css rather than in the html.
<div class="parent">
<a>Parent 1</a>
<a class="child">child of parent 1 contents</a>
</div>
<div class="parent">
<a>Parent 2</a>
<a class="child">child of parent 2 contents</a>
</div>
css:
.parent > .child { /* good practice: only select an immediate child of the parent */
display: none;
}
The other answers here are using find() to select the child, but I recommend children() instead. For example, if you had additional nested .childs, find() will select them all, but children() will only select direct .childs of the parent, so it is better in this case. I also recommend using the console for debugging rather than alert.
Live demo here (click).
$('.parent').click(function() {
var $child = $(this).children('.child');
var cls = $child.attr('class');
console.log(cls);
$child.show(); //added so that you can click the child
});
$('.child').click(function() {
var html = $(this).html();
console.log(html);
//if you just want the text, use this instead:
var text = $(this).text();
console.log(text);
});
I am trying to create a click event for an image using jQuery but I fail every time I try.
First I have a div:
<div id="price-holder"></div>
then I am using jQuery to insert this HTML by using the following:
$("#price-menu li:nth-child(2)").click(function() {
var pregHTML = $("#cakesmash-price").html();
$("#price-holder").html(pregHTML);
});
However, using this HTML doesn't work
<div id="cakesmash-price" style="display:none">
<img id="cake" src="images/order.png" height="32px" onclick="pregbasic(this);">
</div>
I tried to use the attribute onclick for the image and also tried using jQuery's selector with the ID like so
$("#cake").click(function(){
})
but both didn't work.
Can anyone help me?
Thanks
This assumes that the element is actually being added to the page.
I am betting you are adding the click event before you add the element to the page meaning the selector did not find anything so it did not add the event.
Either add the event after you add the element or use event delegation.
$("#price-holder").html(pregHTML);
$("#cake").click(function(){
});
or
$("#price-holder").on("click", "#cake", function () {
});
Your error could be due to your choice of selectors "#price-menu li:nth-child(2)". Try using the JS .children and .eq selectors. Also if your code was added dynamically consider using the .on() event handler rather than the .click().
Just start with the DOM you actually want, without using jQuery to do this:
<div id="price-holder">
<div id="cakesmash-price" style="display:none">
<img id="cake" src="images/order.png" height="32px">
</div>
</div>
Then you can just add you click handler on #cake:
$('#cake').on('click', function (event) {
// your logic goes here
});
I have the following html, dynamically created.
<a class="open"></a>
<div class="dialog"></div>
<a class="open"></a>
<div class="dialog"></div>
<a class="open"></a>
<div class="dialog"></div>
<a class="open"></a>
<div class="dialog"></div>
Using the follwing jquery, I'm assigning ID's to each a aswell as each div
$('a.open').prop('id', function(i){
return '' + (i + 1);
});
$('div.dialog').prop('id', function(i){
return 'dialog' + (i + 1);
});
I'm then using the assigned ID's to trigger a jquery ui Dialog pop-up, however, I'm having to rewrite the function below for x number of times. Is there a way to create the below function so I do not have to rewrite it x number of times. (x being the max. number of times the the divs may appear on page).
$("#1").click(function(){
$("#dialog1").dialog("open");
});
Sounds like an ideal use for data attributes. When you dynamically generate the <a> tags, assign them a data attribute like so:
<a class="open" data-openNumber="1"></a>
(You can also do this via jQuery, of course).
Then all you have to do is write a single click handler:
$('body').on( 'click', '.open', function(){
var num = $(this).data('openNumber');
$('#dialog'+num).dialog( 'open' );
});
Note that I don't attach the handler directly to elements with class open; if I did that, I would have to do it every time the elements were dynamically created. Instead, I attach the handler to the body, and filter it by class open; that way I don't have to keep re-declaring that click handler. If you have a more handy enclosing class, you can use that instead of body, but not knowing your page structure, I didn't know what that element would be, so I just used body.
I made a jsFiddle to demonstrate the concept. I hope it's helpful:
http://jsfiddle.net/Jammerwoch/Z9U67/
What about this?
HTML
<a class"open" data-id="1">open</a>
<div class="dialog" data-id="1"></div>
JS
$(document).on("click", ".open", function(e) {
var id = $(this).data("id");
$(".dialog[data-id="+ id +"]").dialog("open");
});
If you are only using the id attribute to listen for clicks later on. It makes more sense to create a single event listener for the group.
$("a.open").on("click", function(){
$(this).find(".dialog").dialog("open")
});
I have the following:
<div class="tab-pane" id="message">
<textarea rows="4" cols="50" id="send_message" placeholder="Enter text ..."> </textarea>
OK
Cancel
I want to bind the click method to the 'div' element , and when one of the child 'a' elements is clicked do separate things. I am trying to distinguish between them using the button text, but the following is not working:
$(function(){
$('#message').click(function(){
if($(this + ">a").is(":contains(OK)")) {
console.log("OK!!");
How can I fix this?
Okay there are two ways of doing this:
.find(selector)
if(this).find("a").is(":contains(OK)")) {
console.log("OK!!");
OR
$(selector,context)
if("a",this).is(":contains(OK)")) {
console.log("OK!!");
In javascript, this is essentially the context of the current function. In jQuery event callbacks, this is set to be the source element of the event - not the selector string, which is what you are treating it as.
Instead, you want to do a test like: if($("a", this).is(":contains(OK)")) {
This works because the second parameter to the jQuery selector is the context to search in, so you are only searching for the a tags under the source element of the click.
Binding the click element to the Div, then checking the text string of the A tags will make both events happen on every click. You want to bind 2 separate click events on each A tag. Add an ID to each A tag, then try this code
$('#okLinkID').click(function(){
console.log("OK!!");
});
$('#cancelLinkID').click(function(){
console.log("Cancel!!");
});
//Attaches only one listener to the #message div and listens for any 'a' element within it to be clicked.
$('a','#message').on('click',function(){
var $this = $(this),
btnText = $this.text();
console.log(btnText);
});
http://jsfiddle.net/YA7Ds/
This question already has answers here:
jquery stop child triggering parent event
(7 answers)
Closed 8 years ago.
I am not sure this is really bubbling, I will explain.
I have this:
<div>
<div>
text here
</div>
</div>
How to bind an on click event so that it will affect only the enclosed div? If I set it like this:
jQuery('div').bind('click', function() {
jQuery(this).css('background','blue');
});
it makes blue all the divs. If I add false as the third argument(prevent bubbling) to the bind function it does nothing.
How can I solved this?
http://api.jquery.com/event.stopPropagation/
Add event.stopPropagation(); inside the hander.
(It might be better, though, to assign an ID or class to the nested DIV so you can be sure it's the only one affected.)
You should really use identifiers like IDs or classes, but for your example, you could do this:
jQuery('div > div').bind('click', function() {
jQuery(this).css('background','blue');
});
...which will bind the handler to any div that is a direct descendant of another div.
So either make your initial selection specific to the element(s) you want to affect, or use event delegation, placing a handler on an ancestor, and testing for the element you want.
Delegation example: http://jsbin.com/ehemac/edit#javascript,live
<div id="container">
<div class="outer">
<div>
text here
</div>
</div>
<div class="outer">
<div>
text here
</div>
</div>
</div>
jQuery('#container').delegate( '.outer > div', 'click', function() {
jQuery(this).css('background','blue');
});
This uses the delegate()[docs] method that places a handler on the ancestor with the ID #container.
The first argument to .delegate() is a selector. Any elements that are clicked inside #container will have that selector compared against the element clicked. If the selector matches, the handler will be invoked.
http://jsfiddle.net/vol7ron/WzSkj/
Targeting the last descendant
Credit to Patrick DW:
jQuery('div:not(:has(div))').bind('click', function() {
jQuery(this).css('background','blue');
});
This should be all you need as it will look at all div and find those that don't have child divs (thus, they will be the last descendant of that element type. You could further filter this to make sure they have a parent that is a div, if you wanted to exclude those divs that are standalone.
Older Answer:
This is not by any means meant to be a complete/robust plugin. It serves as only an example of how to target the last element in a chain. See the revision history for a way to do it w/o the plugin. This should be modified if you wish to use it for production.
Plugin:
(function($){
$.fn.lastDescendant = function(el){
var found = jQuery(el + ':first').siblings(el).andSelf();
var prev, curr;
var stack = this;
for (var i=0,n=found.length; i<n; i++){
curr = found.eq(i).find(el);
while (curr.length){
prev = curr;
curr = curr.find(el);
}
stack = stack.add(prev);
}
return stack;
};
})( jQuery );
Example Call:
jQuery.fn.lastDescendant('div')
.click(function(){
jQuery(this).css("background","#09c");
});
Note:
this will not select the first (ancestor) element. If you want to select that as well, you could wrap the whole thing in a new div, and then do the above.
if I were to make this a production plugin, I would include checking the parameter, and allow you to be able to pass in an object and a starting point (so that siblings are not selected)
To fix this just use a more specific selector
jQuery('div > div').bind('click', function() {
jQuery(this).css('background','blue');
})
The best way to solve it would be to give your inner div an identifiable feature such as a class, e.g., <div class="inner"></div>.
Alternatively, change your selector:
$('div > div').click(function() {
$(this).css('background', 'blue');
}
try giving the inner div an id tag and refer to it...
<div><div id=foo>text goes here</div></div>
...
$('#foo').bind('click', function() {
$(this).css('background','blue');
});
HTH
-- Joe