how to check parent in jquery - javascript

I bind a click event over the document. I have a div with id parent. Now whenever the click event occur over the document than i am trying to check the target element is the child of div ( id = parent ) or not.
<div id="parent">
<div id="c1">
<div id="gc1">
</div>
<div id="gc2">
</div>
...
</div>
...
</div>
For this purpose i wrote the following jquery code :
$(document).click( function(e) {
if($(e.target).parents("#parent").length > 0) //this condition is not
working as expected
{ }
});
What i am doing wrong here?

If the code you posted is verbatim, you forgot to declare e as a parameter to the callback function.
Apart from that, your code looks like it should work fine. However, for efficiency you could use .closest() rather than .parents() since that'll only return 0 or 1 elements, and not the entire chain of elements.

You could use jQuery.contains()
if( $.contains( document.getElementById('parent'), e.target) ) {
}
This will check if the target is contained within the parent container.
From the docs:
Note: The first argument must be a DOM element, not a jQuery object or plain JavaScript object.
This is the reason for the getElementById..

EDIT Use closest... Working FIDDLE
First...this may not completely answer your question but you need the (e) in the click function.
$(document).click( function(e) {
if($(e.target).closest("#parent").length > 0)
{ }
});

Related

Jquery click event on selector returns child as target

I'm starting to lose my mind with Jquery today, I lookep up the other questions but nothing worked so far. I have the simple html structure (added dynamically in a for loop).
<div id="cell'+i+'" class="cell emptyCell">
<div class="handle"></div>
<div class="content"></div>
</div>
I'm using the "on" method to bind the "click event" of elements of class ".emptyCell" with a custom function.
$(document).on('click','.emptyCell', function(e){
console.log(e.target.id);
});
But when the user clicks on the .content div (child of emptyCell), it catches the event, and the console prints "undefined" since .content elements don't have ids here.
How is that even possible ? Isn't the .on function supposed to bind elements of class .emptyCell only ?
Thanks for your help
e.target refers to the actual element where the click happened(it can be handle or content elements), if you want to refer emptyCell then you can use this or e.currentTarget
$(document).on('click','.emptyCell', function(e){
console.log(this.id);
console.log(e.currentTarget.id);
});
Demo: Fiddle

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
});

Disabling element in jQuery

Okay so I want to click an item, then have that item become unclickable, and not execute the jQuery attached to it. I am currently using this
$(clicked_id).prop('disabled', true);
However that is not working.
Any help is much appreciated!
EDIT:
This is the HTML:
<img src="imgs/card.jpg" id="card0" name="card0" onclick="getCard(this.id); ">
disabled is only for disabling input elements (and it doesn't change the clickability of the object -- just that the default animation isn't executed).
To make it so that the click event is removed from an object, use .off()
$(clicked_id).off('click')
But this only works if the onclick was added via jquery
Instead, you may do this:
$(clicked_id)[0].onclick=false
Since your handler is assigned as an attribute, you can just nullify the property for that event handler.
document.getElementById(clicked_id).onclick = null;
just make sure you don't have a leading # on the ID.
Or us jQuery like this:
$(clicked_id).prop("onclick", null);
Or you can pass the element itself instead of passing the ID.
<img src="imgs/card.jpg" id="card0" name="card0" onclick="getCard(this); ">
And then change your function so that it receives the element instead of the ID of the element. Once you do that, you can access the element directly.
elem.onclick = null;
There is another solution:
function getCard(objId){
if( !($('#'+objId).attr('used') == '1') )
{
alert('Click is working for '+objId);
// do something
$('#'+objId).attr('used', '1');
}
}
Here is a working example:
http://jsfiddle.net/HqHut/

How to get top most parent Id when I click on any one of its child element?

I have the following HTML code:
<div id='parentDiv'>
<div class='firstDiv'>
<div class='firstDivChild1'></div>
<div class='firstDivChild2'>
<div class='firstDivChild2_Child1'></div>
<div class='firstDivChild2_Child2'></div>
</div>
</div>
<div class='secondDiv'>
<div class='secondDivChild1'>
<div class='secondDivChild1_child'>
<div class='secondDivChild1_child_child'></div>
</div>
</div>
</div>
</div>
Now my requirement is when I click on any div I want to get an top most parent Id (i.e. parentDiv). Presently I'm using the below script to get parent Id:
<script type='text/javascript'>
$('div').click(function(e){
var parentDivId = (e.target).parentNode.id;
alert(parentDivId );
});
</script>
but it doesn't work. Can anyone correct this code to reach my requirement?
If that parent DIV is unique across document, then you just can refer to it by ID, i.e. $('#parentDiv'), but if it's not, then you should change your HTML and add to parentDiv some class (i.e. parentDiv), and you'll be able to refer to it by this expression $(this).parents('.parentDiv:first');
$('div').click(function() {
alert($(this).parents('div').last().attr('id'));
return false;
});​
Live DEMO
then use the natural power of event bubbling. any descendant clicked will bubble up the event upwards (hence bubble) and will act as if the parent is clicked. so adding a click handler to the parent also does the same thing.
$('#parentDiv').on('click',function(){
var id = this.id
});
Try this little function :
$.fn.root = function() {
var $all = $( this[0] ).parents();
// omit "html", "body" and one index to the last item;
return $all.slice( $all.length - 3, $all.length - 2 );
};
Sample Usage :
$('input').click(function() {
alert($(this).root().prop('id'));
});​
Simple working example using your HTML here
It is still not completely obvious what you're asking for, but based on a few of your comments, here's my best guess.
Using event bubbling, you can examine all clicks in your document and you then determine where the click originated with e.target and you can then figure out whether that click originated in your div tree or elsewhere:
$(document).click(function(e) {
// determine if click was in our div tree or not
if ($(event.target).closest("#parentDiv").length) {
// click was in our parentDiv tree
} else {
// click was not in our parentDiv tree
}
});
Regardless of where the click was located, you can get the top of your div tree id="parentDiv" at any time with this with this jQuery:
$("#parentDiv")
If, you just want the top-most div that is above what is clicked, no matter where the click is in the document, you can use event bubbling like this to get that:
$(document).click(function(e) {
e.stopPropagation();
var topMostDiv = $(e.target).parents("div").last();
// do whatever you want with topMostDiv here
});

Observing click of ajax code checks elements in order

I have a problem where I need the document observe click function (or something similar) to get elements in order from child out. The reason being is I want to have e.stopPropagation() on the child element, but the parent calls anyways because it is first in line.
For example:
<script type="text/javascript">
document.observe('click', function(e, el) {
if (el = e.findElement('.parent a')) {
e.stopPropagation();
}
if (el = e.findElement('.parent')){
alert('parent');
}
});
</script>
<div class="parent">
Child Click Function
Parent Click Function
</div>
In this example, parent gets found first, so the alert gets called. the reason I have to to do it this way rather than the element.observer is that its Ajax generated content and Prototype doesn't appear to have a live() function like jQuery.
Does anyone have a work around for this?
Thanks.
Prototype definitely does have a .live() equivalent and it is called Event.on(). It also works as an instance method, Element#on().
document.on('click', '.parent', function(event, element) {
if (!event.findElement('.parent a')) {
alert('parent');
}
});
You're observing on "document", the currentTarget of your event e is document.
'.parent a' and '.parent' exists in your document, so el.findElement('.parent a') and e.findElement('.parent') will always return an element.
.parent is not found first in your script, but you dont stop the process ( or use an if/else statement ) when you enter in your first if. So the process continue and the script find the .parent element in document.
Can you explain what you're trying to do ? Why do you want the event to stop bubbling ?
btw :
1) el is undefined in your script.
2) you use "=" and not "==" in your script when you're using findElement();

Categories

Resources