different types of jQuery selectors - javascript

What’s the difference between $(“#foo .bar”) and $(“#foo”).find(“.bar”)?
$('#foo').on('click', function(){
$(this).find('.bar').css('background-color', 'yellow');
})
$('#foo_two .bar_two').on('click', function(){
$(this).css('background-color', 'red');
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id = "foo">
<p class= 'bar' style='background: green'> Hello there</p>
</div>
<div id = 'foo_two'>
<p class = 'bar_two' style='background: orange'> Hello there</p>
</div>
In the snippet, I tried to outline what I thought was the difference but seem to now not know what's going on...

$('#foo').on('click', function(){
means that the parent #foo is the click target Element
$('#foo_two .bar_two').on('click', function(){
... click on the parent #foo_two if you dare! http://jsfiddle.net/0qcssuue/2/
(.bar_two has now the click event bound to it. #foo_two just helped jQuery and the JS parser to find it's child .bar_two Element)
To conclude, the $(this) inside the function refers to the targeted Selector.
In the first case it's #foo,
in the second it's #foo_two .bar_two (the #foo_two's children .bar_two)
In your case you could not notice the difference cause the parent was wrapping so close the child element that every click seemed to target the same selector. Adding some padding to the parent (like in my demo) makes the difference more clear.

The difference is in which object you are attaching the listener for click event.
For case:
$('#foo').on('click', function(){
$(this).find('.bar').css('background-color', 'yellow');
})
You are attaching the listener to the #foo object.
For case:
$('#foo_two .bar_two').on('click', function(){
$(this).css('background-color', 'red');
})
You are attaching the listener to the #foo_two .bar_two object
I adjust your fiddle to show the difference. Green label changes when you click de div element but orange label changes when you click the p element
http://jsfiddle.net/0qcssuue/3/

Related

jQuery's cloned elements lose click events after being removed and appended to a container twice

Check this fiddle: https://jsfiddle.net/L6poures/
item.click(function()
{
alert("It works")
})
$("#container").append(item)
var stored = item.clone(true, true)
function add_remove()
{
$("#container").html("")
$("#container").append(stored)
}
Basically, if I clone an element with .clone(true, true), after I replace the container with .html and appended again, and repeat that process again, the click event is gone.
Is there something wrong with jQuery or am I doing something wrong?
When you have event listeners in content you add dynamically, it usually simplifies things to use event delegation instead. This means that you attach the event listener to a parent container that is not deleted - in this case your #container element - and you use a selector in the jQuery .on() call to specify which child elements you are interested in.
Here's an updated fiddle that illustrates the technique for your use case, and here it is as a snippet:
$("#container").on( "click", "#item", function() {
alert("It works")
})
var html = "<div id='item'>Hi</div>"
$("#container").html(html)
function add_remove() {
$("#container").html(html)
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='container'></div>
<br>
<button onclick="add_remove()">
Remove And Add Again
</button>
Note that the code doesn't even use .clone() now; it just inserts the HTML code each time without worrying about event listeners at all. You could use .clone() as in your original code, but event delegation gives you the flexibility to do it either way. In any case you wouldn't need the .clone(true,true) arguments because you don't care about preserving event listeners in the inserted code.
Check the below code (have made minor changes to your code, to make it work). You don't even need to clone():
var item = $("<div id='item'>Hi</div>");
$("#container").on('click', '#item', function() {
alert("It works");
});
$("#container").append(item);
function add_remove() {
$("#container").html("").append(item);
alert('cloned and appended successfully.');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='container'></div>
<br>
<button onclick="add_remove()">
Remove And Add Again
</button>

How to embed a clickable div inside another clickable div

In a previous question I asked about toggling a child div from the parent which was answered and the answer given works. Now I have a different issue: When I click anywhere within the inner (such as the link "inside inner div" it causes the outer div to toggle. I want the inner div to toggle only by itself. If I click as described, then div containing "This is the inner div" should disappear but the class openData should be active for the outer div. Instead it gets set to closeData.
This is my code:
<html>
<head>
<style>
.openData{font-size:18px;background-color:lightgreen;color:blue;}
.closeData{font-size:18px;background-color:lightblue;color:blue;)
</style>
<script src="/js/jquery.js"></script>
<script>
function insideDiv(f) {
var e=window.event;
e.cancelBubble=true;
e.stopPropagation();
toggleDiv(f);
return false;
}
function setCursor(e) {
e.style.cursor="pointer";
}
function clearCursor(e) {
e.style.cursor="default";
}
function togglePlusMinus(f) {
$(f).children('div:first').toggle();
$(f).toggleClass("openData closeData");
}
</script>
</head>
<body>
<div class="closeData" onmouseover="setCursor(this);" onmouseout="clearCursor(this);" onclick="togglePlusMinus(this);">This is the outer div
<p>Inside outer div</p>
<div style="display:none;;background-color:#ffffff;" onclick="insideDiv(this);">This is the inner div
<div>
<p style="margin-left:20px;margin-top:0px;font-size:15px">inside inner div</p>
</div>
</div>
<p>Also in outer div</p>
</div>
This is just some trailing text.
</body>
</html>
Everything I've read says that I need to stop the click propagation (which I think I am doing correctly).
This is the smallest working failure example. The actual program shows expandable data sets nested within each other.
Try adding an eventListener to your inner div and use stopPropagation like in the parent.
var myDiv = document.querySelector('#myDiv'); //assuming your child div has a "myDiv" id
myDiv.addEventListener(pEvent) {
pEvent.stopPropagation();
};
EDIT :
To make it work with every first child div of each .closeData element you can do (assuming you have only one direct child div):
//Selects all .closeData elements
var parents = document.querySelectorAll('.closeData');
//For each .closeData, find the first div and stops the propagation
for(var i = 0; i < parents.length; i++) {
var child = parents[i].querySelector('div');
child.addEventListener('click', function(pEvent) {
pEvent.stopPropagation();
})
}
Edit: it seems that the problem is that you are calling stopPropagation to the window event, not the actual element that you are clicking.
You are looking most likely for the event bubbling tutorial (at least if I understood correctly). Please check this out as it describes your problem:
http://javascript.info/tutorial/bubbling-and-capturing
And in shorthand to stop the inner event to propagate to outer div use:
event.stopPropagation()
and for IE9 earlier:
event.cancelBubble = true
If only the outer div function is firing try setting a z-index on the inner div that is higher than the parent div.
Explicitly pass event to your function such that
Onclick="function(event || window.event, this)"
Then add a a param for the event on your function and do event propagation cancelation on that.

Two OnClick events overlap

I have an element inside an element, when I click the element underneath I want the slider to open. When I click on the outermost element I want the slider to close.
Unfortunately when I click on the outermost it clicks the underneath element as well. Is there a way to click only on the outermost element ignoring the click on the underneath element? The events are triggered on click and executed with javascript.
I tried with z-index but it still captures the underneath element clicked as well, and because the functions are contrary to one another nothing happens.
edit: on a "code is worth 1000 words" tip
var $target = $(this).data('pos', i) //give each li an index #
$target.data('hpaneloffsetw', $target.find('.hpanel:eq(0)').outerWidth()) //get offset width of each .hpanel DIV (config.dimensions.fullw + any DIV padding)
$target[haccordion.ismobile? "click" : "mouseenter"](function(){
haccordion.expandli(config.accordionid, this)
config.$lastexpanded=$(this)
})
if (config.collapsecurrent){ //if previous content should be contracted when expanding current
$('.close').click(function(){
$target.stop().animate({width:config.paneldimensions.peekw}, config.speed) //contract previous content
})
$target.dblclick(function(){
$(this).stop().animate({width:config.paneldimensions.peekw}, config.speed) //contract previous content
})
}
Because the code is borrowed, I don't understand much of it. But basically I want the "click" : "mousteenter" function to work on click, without interfering with the .close().click
It sounds like you need to stop the click event bubbling up the DOM to be caught by parent elements. You can use stopPropagation() to do this:
$('.close').click(function(e) {
e.stopPropagation();
$target.stop().animate({ width: config.paneldimensions.peekw }, config.speed);
})
$target.dblclick(function(e) {
e.stopPropagation();
$(this).stop().animate({ width: config.paneldimensions.peekw }, config.speed);
})
Try the following fiddle
$("#outer").click(function(){alert("outer clicked")});
$("#inner").click(function(e){
alert("inner clicked")
e.stopPropagation();
});
To identify the element you have "really" clicked on, you can try to identify it through accessing the target property of the jquery-event-object.
After you identified the target you clicked on, you could prevent other event handlers from firing.
Use CSS specific jquery to point exact element like below, use > to point exact child
table > tbody > tr > td > input[type='text']
like this.

jquery event bubbling and event.targets

I'm trying to get my head around how to stop a click event from bubbling up,out,down when a particular element is clicked.
<div class="clickable">
clicking here shouldn't affect parents or children
<div class="clickable">
clicking here shouldn't affect parents or children
<div class="clickable">
clicking here shouldn't affect parents
</div>
</div>
</div>
Basically, if an element with the class "clickable" is clicked, I only want that item to be affected, toggling an even/odd class.
Here's the fiddle: http://jsfiddle.net/LDaA7/
When you run the fiddle and click a particular item, you'll see that various parents and children also get toggled.
From experimenting, event.stopPropagation(), returning false/true, .one, etc. impacts click events not targets per se. I may want other (unrelated) click events to work.
How do I target only the element I'm clicking?
You can just check if the target equals the bound element (this):
$("body").on "click", ".clickable", (event) ->
if this is event.target
clickTarget = $(event.currentTarget).closest(".clickable")
clickTarget.addClass "clicked"
if clickTarget.hasClass "odd"
clickTarget.addClass("even").removeClass("odd")
else
clickTarget.addClass("odd").removeClass("even")
FIDDLE
You want to use $(this) to target the element you have clicked. Also, .stopPropagation() so it won't bubble up the events.
See Demo here
$('.clickable').click(function (e) {
e.stopPropagation();
var elem = $(this);
elem.addClass('clicked');
if (elem.hasClass('odd')) {
elem.addClass('even');
elem.removeClass('odd');
} else {
elem.removeClass('even');
elem.addClass('odd');
}
});

Jquery - Difference between event.target and this keyword?

What is the difference between event.target and this?
Let's say I have
$("test").click(function(e) {
$thisEventOb = e.target;
$this = this;
alert($thisEventObj);
alert($this);
});
I know the alert will pop different value. Anyone could explain the difference? Thanks a million.
They will be the same if you clicked on the element that the event is rigged up to. However, if you click on a child and it bubbles, then this refers to the element this handler is bound to, and e.target still refers to the element where the event originated.
You can see the difference here: http://jsfiddle.net/qPwu3/1/
given this markup:
<style type="text/css">div { width: 200px; height: 100px; background: #AAAAAA; }​</style>
<div>
<input type="text" />
</div>​
If you had this:
$("div").click(function(e){
alert(e.target);
alert(this);
});
A click on the <input> would alert the input, then the div, because the input originated the event, the div handled it when it bubbled. However if you had this:
$("input").click(function(e){
alert(e.target);
alert(this);
});
It would always alert the input twice, because it is both the original element for the event and the one that handled it.
​
Events can be attached to any element. However, they also apply to any elements within said object.
this is the element that the event is bound to. e.target is the element that was actually clicked.
For example:
<div>
<p>
<strong><span>click me</span></strong>
</p>
</div>
<script>$("div").click(function(e) {
// If you click the text "click me":
// e.target will be the span
// this will be the div
}); </script>
Crispy answer
this gives you the reference of the DOM element where the event is actually attached.
event.target gives you the reference of the DOM element where the event occurs.
Long answer
jQuery(document).ready(function(){
jQuery(".outer").click(function(){
var obj = jQuery(event.target);
alert(obj.attr("class"));
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="outer">
Outer div starts here
<div class="inner">
Inner div starts here
</div>
</div>
When you run the above code snippet you will see that event.target is alerting the class name of the div that is actually clicked.
However this will give the reference of the DOM object on which the click event is bind. Check the below code snippet to see how this works, always alerting the class name of the div on which the click event is bind even if you click the inner div.
jQuery(document).ready(function(){
jQuery(".outer").click(function(){
var obj = jQuery(this);
alert(obj.attr("class"));
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="outer">
Outer div starts here
<div class="inner">
Inner div starts here
</div>
</div>

Categories