Using Parents() on an element which gets reinserted on click - javascript

I have created a dropdown functionality using Jquery with one event listener that allows me to close the dropdown when clicked anywhere outside the dropdown container and another event listener which handles the submenu items.
By design the dropdown should stay open even if the submenu items are clicked and should only close if the toggle button is clicked or the user clicks outside the dropdown container.
The problem
Lets say that general.js has the click event listener as follows
$('document').on('click.namespace',function(e){ // do stuff });
Now anotherscript.js has an event listener which handles the actual sub menu clicks
$('#clickbutton').on('click', function(e){
// Remove all html from inside the .dropdown container
// Recreate the html using another js function
$('.container').html(recreatedhtml);
});
The problem occurs when I try to identify who the parent of the submenu button click target is, because I want to know if the click was inside the container or outside.
Since a click on #clickbutton removes html from the container and reinserts it I believe this causes problems for the parents() function therefore the parents('.dropdown') function returns false even though the sub menu item is a descendent of the dropdown class.

Check the target of the event
$(document).on('click.namespace',function(e){
if(!$(e.target).closest(dropdownContainerSelector).length){
// click is not in dropdown container
}
});
Note that document is not a string, it is a global object within window

Related

Hide context menu on outside click

I have a context menu that appears when you right click inside the <div>, and it only goes away if the user click left click inside the <div> again.
How do i hide it when a user click anywhere on the page?
my fiddle
change these two functions to the following:
_onPageClick: function(e) {
e.stopPropagation()
if (this.refs.contextMenu.getDOMNode() !== e.target){
this.contextMenu.setState({contextMenuLocation: ''});
}
},
componentDidMount: function(){
this.contextMenu = this.refs.contextMenu;
document.addEventListener('click', this._onPageClick)
},
all we have to do is to move _onPageClick from the wrapper div to a listener on the document. the above code will close the menu if the user clicks anywhere that is not inside the context menu. if you want it to close if the user clicks the context menu as well, then change _onPageClick to:
_onPageClick: function(e) {
e.stopPropagation()
this.contextMenu.setState({contextMenuLocation: ''});
}
(also, the wrapper div should no longer have the onClick handler)
http://jsfiddle.net/yikevinqu/eeu9unhm/1/
Check out Ben Alman's clickoutside jQuery plugin. Even if you are not using jQuery, you can review his mechanism for catching these click events as they bubble up.
http://benalman.com/projects/jquery-outside-events-plugin/
All click events get bubbled up through the DOM, so if you click an inner element, if you don't event.stopPropagation(), it will bubble up to the parent element. So just catch the click on the parent element (can even be document to hide your context menu).
Check out my fiddle for a pure JS example: http://jsfiddle.net/jsc8zLaj/
There's actually an existing React mixin on npm you can use for this:
https://github.com/Pomax/react-onclickoutside
Since mixins have fallen out of favour now, you may want to implement it as a wrapper component instead, but this is an excellent starting point.

Fire onclick on <select> element but not on <option>

My element updates its options using the onclick() listener when clicked. The problem is the listener is firing when an option is clicked as well, so the user is unable to select anything in the updated list.
groupSelect.onclick = function() {
PopulateList();
}
I'd like to run my function only when the select element is clicked(when the menu has not dropped down yet) but not when a specific option is clicked. How can I do so? I'm writing the JS part using NodeJS.
Events will bubble up the hierarchy, so a click on an option will also trigger any events bound to its parent select.
This is fixed by stopping propagation of the event on your option listener
$('option').click(function(event){
event.stopPropagation();
//rest of code
})

Attach Click Event to HTML after Menu Click

I've got a dropdown menu on a site I'm working on that has different classes added to it when it is activated. It's built into a WordPress theme so I'm having to build a workaround on it for iPad landscape mode. The site navigation displays the same as desktop when on landscape so I need to create some touch events to mimic the behavior.
The first thing I'm having to do is to deactivate the link on the first click and then reactivate it if it's clicked again. This works fine.
if ('ontouchstart' in document.documentElement) {
$('#masthead nav ul > li:has(.sub-menu) a').click(function(e){
e.preventDefault();
$('li.clicked_link').on('click', function(){
var this_link = $(this).find('> a').attr('href');
document.location.href=this_link;
});
$(this).parent().addClass('clicked_link');
});
}
The problem is that when you click on the li.sub-menu it adds a class of sub-hover onto it which activates a dropdown menu. It's a CSS/jQuery dropdown menu so it's based on the presence of that sub-hover class. It works fine when I first click but I then want to remove that class when you click outside of it. It deactivates it if I click another link in the dropdown but I'd like to bind a click event to the html or body elements so if you click anywhere outside of it, it will remove the sub-hover class, thus removing the dropdown.
I tried to do this:
if ('ontouchstart' in document.documentElement) {
$('#masthead nav ul > li:has(.sub-menu) a').click(function(e){
e.preventDefault();
$('li.clicked_link').on('click', function(){
var this_link = $(this).find('> a').attr('href');
document.location.href=this_link;
});
$(this).parent().addClass('clicked_link');
$('html').on('click',function(){
$('#masthead nav ul > li:has(.sub-menu)').removeClass('sub-hover').removeClass('clicked_link');
});
});
}
It doesn't work though because it seems to fire the first click function and then immediately fire the html click function. I tried to use bind as well but the same thing happened. I also tried it outside of the initial click function but, as you can guess, it fires the two click events simultaneously which doesn't work.
How do I get it to bind but not fire the click event only after the initial click event takes place?
This is not a direct fix for the problem, but something that might help you fix the problem (Too long for a comment).
You are binding click handlers inside another click handler without unbinding the previous ones, So everytime you click a matching <li> new click handlers are being added to <html> and other matching elements. I strongly believe you're not doing it on purpose and isn't aware of it.
Leaving that, You're trying to bind a click for .clicked_link using
$('li.clicked_link').on('click', function(){
This code looks for matching elements currently present in DOM, and probably finds no matching elements since you're actually adding the class clicked_link after it.
You actually need to delegate this handler to check for matching elements in future.
The events are bubbled up till the root element, in other words: you if you click an anchor, starting from the anchor, all the parents till html will receive a click event, which you can prevent using e.stopPropagation();.
Ideally you're code should look something like this:
if ('ontouchstart' in document.documentElement) {
$('#masthead nav ul > li:has(.sub-menu) a').click(function(e){
e.preventDefault();
$(this).parent().addClass('clicked_link');
});
$(document).on('click','li.clicked_link', function(){
var this_link = $(this).find('> a').attr('href');
document.location.href=this_link;
});
$('html').on('click',function(){
$('#masthead nav ul > li:has(.sub-menu)').removeClass('sub-hover').removeClass('clicked_link');
});
}
(Can't go any further with the currently available info. Minimal code such as respective html structure or a demo would be helpful)

Disable Bootstrap nav item click event

I'm using Bootstrap 3 nav as something like "collapsible div" only which holds multiple level menu. but I have an issue with the nav items or its hyperlinks click event and want to disable it so my menu works the way I want.
For sure I've assigned my custom events to the nav items which open the second level but for some reason that doesn't work fine on mobiles.
I even tried javascript:void() for the hyperlinks but I think the click event of bootstrap is assigned to the <li>
Use the following to prevent the default link behavior.
$( "a" ).click(function(e) { // target any selector
e.preventDefault();
});

Closing a menu on mouseout

I have a button that when clicked will popup a menu to the right of the button. This menu is a rather large UL of list items. The page that this menu is on contains lots of other elements.
Once the menu pops up, a user can click an option on the menu and the menu will disappear (menu.hide()).
However, it feels wierd not being able to get rid of the menu any other way. I like the idea of "if the user clicks on anything but the menu, the menu will hide." But i hate doing a "clickoutside" event that binds events to everything but the menu.
Another option is "mouseout" but "mouseout" always gets fired too early, because the mouse has to travel across the screen to get to the menu.
Any ideas on what event I can bind to the menu, so the user can get rid of it naturally, and at will? (not just when he clicks an option)
You can bind one event to the body when the menu is open. Use the click event to determine if the click occurred outside of the menu. If outside of the menu, hide the menu and remove the bind.
// binding function
closeMe = function(e) {
var $target = $(e.target);
// click is not inside the menu
if(!$target.hasClass('menu') && $target.parents('.menu').length !== 1) {
// hide menu
menu.hide();
// unbind events
$('body').unbind('mousedown.menuhide', closeMe);
}
};
// show menu
menu.show(function() {
// bind menu hide event
$('body').bind('mousedown.menuhide', closeMe);
});
Very easy, just use something like this
$('html').click(function() {
menu.close();
});
$('#menu').click(function(e){
e.stopPropagation();
// do stuff
// maybe some nice animation or w/e
menu.close();
});

Categories