Detect click event in any nested element of an specific div - javascript

I need to be able to detect any click that happens within a specific container referenced by class, if the user clicks on any of the nested elements I should be able to detect the click and update a flag
<div class="container" >
<div class="x1">
<div class="x2">
<div class="">
<span class="">
<ul class="">
</div>
</div>
I tried using jquery but I prefer to do it using backbone.
//$(document).on('click','.container', function(e){
//$('.container').delegate("div", "click", function(e) {
Not sure what event I need to use when the users are clicking in some of the nested elements within the div that have the container class. Basically, I need to update a flag in case of the user clicks outside of this div, but I don't want to have a large scope on the event handler that listens to the whole body.

Since you asked for a Backbone example, here's how to listen to clicks on a div and its children.
var View = Backbone.View.extend({
className: "my-test-view",
template: '<div class="container"><div class="x1"><div class="x2">test</div></div></div>',
events: {
'click .container': 'onClick',
},
render: function() {
this.$el.empty().append(this.template);
return this;
},
onClick: function(e) {
console.log("clicked on", e.target, " triggered from ", e.currentTarget);
},
});
var view = new View();
$("body").append(view.render().el);
Clicking the test text should output:
clicked on <div class=​"x2">​test​</div>​ triggered from <div class=​"container">​…​</div>​
With jQuery, the above is (roughly) the equivalent to:
$('.my-test-view').on('click', '.container', function(e) {
console.log("clicked on", e.target, " triggered from ", e.currentTarget);
});
But for most case, this should be enough:
$('.container').on('click', function(e) {
console.log("clicked on", e.target, " triggered from ", e.currentTarget);
});
Don't use .children().on(...) as this will create a new listener for each child and it's inefficient.
Detecting a click outside a div is quite different and there are many ways to achieve it but none is perfect.
See :
Backbone view with custom event to detect clicks outside of it
How to detect a click outside an element?
Use jQuery to hide a DIV when the user clicks outside of it
Personally, I used focus and blur events (don't forget tabindex="-1" on the element).

Maybe this?:
$(document).on('click','.container *', function(e){
console.log(e.target);
});
The great thing about jQuery is that you can use the same selectors as you would use with CSS hence I used .container * to target all elements inside the container.

I used the jquery .children() method. Check out this code pen.
var flag = 'whatever';
$(.container).children().on('click', function() {
flag = 'updated';
});
Essentially, saying for all children of whatever element is class container (div in this case) add an event handler.

Related

How does $(this) know what my target is?

How does $(this).keyup know I want the keyup listener associated with the #searchString input, and not the parent div? Doesn't $(this) represent the parent div? I dumped out $(this) to the console, and it looks like an object for the parent div.
Long story short:
How is this working? $(this).keyup
Instead of explicitly saying: $('#searchString').keyup ??
$('<div id="msg">' + <input id="searchString" name="searchString" type="text" value="" /> + '</div>').dialog({
open: function () {
$(this).keyup(function (e) {
if (e.keyCode == $.ui.keyCode.ENTER)
$('#btnFind').click();
return false;
})
},
buttons: [
{
text: "Find",
id: "btnFind",
icon: "ui-icon-search",
click: function () {
//do stuff
}
}
]
});
Did some testing; here are my observations:
$(this) is representative of the parent <div id="msg">
$(this).keyup is targeting any (and all) extra inputs I add to <div id="msg">
I don't think this this is event bubbling/capturing (the listeners are not nested):
$('#btnFind').click(); is an action nested inside the keyup listener
the jQuery UI dialog button id: "btnFind" has a separate event listener, outside of the the parent <div id="msg">
I went ahead and explicitly indicated the target for the listener: $('#searchString').keyup
Who cares?
Well, I didn't think you could establish event listeners on inputs via the dialog open event. I'm creating my dialog on-the-fly, and my assumption was that the input may not exist while the open event was trying to establish the event listener.

jQuery dialog is not working for element created dynamically

I am working with jQuery dialog. I have one problem that trying to solve that is:
I have created the dialog on click of of anchor class and its working. Than after this I have created one more anchor tag with same class and on click of that new created tag dialog is not working.
Here is html:
<div id="loader_ajax"></div>
<a id="show_hide_window1" class="show_hide_window" href=""> Dialog </a>
<div class="next_tg"></div>
Here is jQuery code:
$(function(){
$(".show_hide_window").click(function(){
showDialog();
});
$('.next_tg').html('<a class="show_hide_window" href=""> Dialog Created By Jquery </a>');
});
function showDialog()
{
$("#loader_ajax").dialog({ modal: true, height: 400,width:650,title: title });
return false;
}
I have already tried with delegation(Event binding) its not working. For Dynamically created anchor it give error in console: TypeError: $(...).dialog is not a function
Please help!! Thanks
You can currently binding click event to elements that are present in the DOM when binding code executes. You need event delegation for dynamically created elements. You also need to add the newly create element to DOM, suppose you want to add to loader_ajax
Here static parent could be any html element, in your case it would be loader_ajax
You code would be
$("#loader_ajax").on("click",".show_hide_window", function(){
showDialog();
});
var newTextBoxDiv = $(document.createElement('div'));
newTextBoxDiv.html('<a class="show_hide_window" href=""> Dialog Created By Jquery </a>');
$("#loader_ajax").append(newTextBoxDiv);
Delegated events
Delegated events have the advantage that they can process events from
descendant elements that are added to the document at a later time. By
picking an element that is guaranteed to be present at the time the
delegated event handler is attached, you can use delegated events to
avoid the need to frequently attach and remove event handlers.
Use on Event. This will manage dynamically added elements.
$(function(){
$('body').on('click', '.show_hide_window', function() {
showDialog();
})
$('.next_tg').html('<a class="show_hide_window" href=""> Dialog Created By Jquery </a>');
});
Fiddle : http://jsfiddle.net/fqt0yztb/
Reference : In jQuery, how to attach events to dynamic html elements?
I have make it from my own code. Now dialog successfully working for dynamically created element.
fiddle
$(document).on('click', '.show_hide_window', function (evt) {
var dialog = $('<div></div>').append('<img src="../images/themeroller.gif"/>');
var getContentUrl = $(this).attr('href');
dialog.load(getContentUrl + ' #content').dialog({
title: $(this).attr('title'),
modal: true,
height: 400,
width:650
});
dialog.dialog('open');
return false;
});

How to get the inside div element child and handle event in extjs4

I want to select the div with class "icon-right" and add the click event.
Html code:
<div class="msg">
<div>
<div class="sample"></div>
</div>
<div>
<div class="icon-right"></div>
</div>
</div>
I want to select the div which has class icon-right and handle click event..
Extjs code:
var message = Ext.select('div:next(div.icon-right)');
message.on('click', function () {
alert('test msg');
}, message);
But i need to change the div with class icon-right as div with icon-left when on click and now when i click the icon-left it change to div with class icon-right.. vice versa happens
Can you do:
Ext.select('.icon-right').up('div').on('click', function() {});
As per the documentation, Ext.select returns a CompositeElement or a collection of DOM elements. You should be using Ext.query which will return an HTMLElement, which you can then define the onclick event handler:
var target = Ext.query(".icon-right").pop(); // return the first div of the query
target.onclick = function(){ alert('clicked!'); }
Alternatively, if you wish to utilize Ext event listeners, you must make use of the Ext.dom.Element class, an instance of which is returned by Ext.get, which calls for an ID, DOM Node or Existing Element as per the documentation. If you were to retrieve the element via Ext.get, you could then assign a listener via Ext.dom.Element.on as you have in the provided code.
Working jsFiddle: http://jsfiddle.net/LcRWB/ (shows both examples)
This should work.
var el = Ext.Element.select("[class=icon-right]");
el.on('click', function() {
alert("hi");
});
You can see an example on jsfiddle http://jsfiddle.net/XzKKZ/

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

Hide a DIV when it loses focus/blur

I have a JavaScript that displays a DIV (sets its display css property from 'none' to 'normal'. Is there a way to give it focus as well so that when I click somewhere else on the page, the DIV loses focus and its display property is set to none (basically hiding it). I'm using JavaScript and jQuery
For the hide the div when clicking any where on page except the selecteddiv
$(document).not("#selecteddiv").click(function() {
$('#selecteddiv').hide();
});
if you want to hide the div with lost focus or blur with animation then also
$("#selecteddiv").focusout(function() {
$('#selecteddiv').hide();
});
with animation
$("#selecteddiv").focusout(function() {
$('#selecteddiv').animate({
display:"none"
});
});
May this will help you
The examples already given unfortunately do not work if you have an iframe on your site and then click inside the iframe. Attaching the event to the document will only attach it to same document that your element is in.
You could also attach it to any iframes you're using, but most browsers won't let you do this if the iframe has loaded content from another domain.
The best way to do this is to copy what's done in the jQuery UI menubar plugin.
Basic example HTML:
<div id="menu">Click here to show the menu
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</div>
And the jQuery needed to make it work:
var timeKeeper;
$('#menu').click(function()
{
$('#menu ul').show();
});
$('#menu ul').click(function()
{
clearTimeout(timeKeeper);
});
$('#menu').focusout(function()
{
timeKeeper = setTimeout(function() {$('#menu ul').hide()}, 150);
});
$('#menu').attr('tabIndex', -1);
$('#menu ul').hide();
What it does is give the menu a tab index, so that it can be considered to have focus. Now that you've done that you can use the focusout event handler on the menu. This will fire whenever it has been considered to lose focus. Unfortunately, clicking some child elements will trigger the focusout event (example clicking links) so we need to disable hiding the menu if any child elements have been clicked.
Because the focusout event gets called before the click event of any children, the way to achieve this is by setting a small timeout before hiding the element, and then a click on any child elements should clear this timeout, meaning the menu doesn't get hidden.
Here is my working jsfiddle example
$(document).mouseup(function (e)
{
var container = $("YOUR CONTAINER SELECTOR");
if (!container.is(e.target)&& container.has(e.target).length === 0)
{
container.hide();
}
});
You can bind a function on click of body and check if its the current div using e.target (e is the event)
$(document).ready(function () {
$("body").click(function(e) {
if($(e.target).attr('id') === "div-id") {
$("#div-id").show();
}
else {
$("#div-id").hide();
}
});
});
Regarding mouse clicks, see the other answers.
However regarding lost focus, .focusout is not the event to attach to, but rather .focusin. Why? Consider the following popup:
<div class="popup">
<input type="text" name="t1">
<input type="text" name="t2">
</div>
What happens on moving from t1 to t2:
t1 sends focusout, which bubbles up to $('.popup').focusout
t2 sends focusin, which bubbles up to $('.popup').focusin
... so you get both types of event even though the focus stayed completely inside the popup.
The solution is to analogous to the magic trick done with .click:
$(document).ready(function() {
$('html').focusin(function() {
$('.popup').hide();
});
$('.popup').focusin(function(ev) {
ev.stopPropagation();
});
});
(side note: I found the .not(...) solution not working bc. of event bubbling).
Bonus: working fiddle click me - open the popup, then try tabbing through the inputs.
I was also looking for this and here I found the solution https://api.jquery.com/mouseleave/. This may be useful for future readers.
The mouseleave event differs from mouseout in the way it handles event bubbling. If mouseout were used in this example, then when the mouse pointer moved out of the Inner element, the handler would be triggered. This is usually undesirable behavior. The mouseleave event, on the other hand, only triggers its handler when the mouse leaves the element it is bound to, not a descendant.
On triggering mouseup() event, we can check the click is inside the div or a descendant and take action accordingly.
$(document).mouseup(function (e) {
var divContent= $(".className");
if(!divContent.is(e.target) && divContent.has(e.target).length === 0) {
$(".className").hide();
}
});
I personally haven't tried blur on divs, only on inputs etc. If blur eventhandler works, it's perfect and use it. If it doesn't, you could check this out:
jQuery animate when <div> loses focus
$('.menu > li').click(function() {
$(this).children('ul').stop().slideDown('fast',function()
{
$(document).one('click',function()
{
$('.menu > li').children('ul').stop().slideUp('fast');
});
});
});
Showing is easy
$('somewhere').click(function {$('#foo').show();})
For hiding
How do I hide a div when it loses its focus?
With jQuery you can hide elements with hide(), ex: $("#foo").hide()
Hide element in event listener:
$("#foo").blur(function() {
$("#foo").hide();
});

Categories

Resources