Here is the thing with jquery when i want to close div when i click outside the div .
$(document).on("click", function (e) {
if (e.target.id != "user-login-top" && !$(e.target).closest("#user-login-wrapper").length) {
$("#user-login-wrapper").removeClass("wide");
}
});
what's the equal thing in angular ?
the Fiddle
many thanks
Through implementing a customized directive, clicking outside the top menu will hide the right sidebar.
Check out this: http://jsfiddle.net/zqdmny41/20/
app.controller('mainCtrl', function ($scope) {
// Add a function to hide the right sidebar.
$scope.hideSideMenu = function() {
$scope.bodyCon = false;
$scope.noneStyle = false;
}
...
})
.directive("outsideClick", ['$document', function( $document){
return {
link: function( $scope, $element, $attributes ){
var scopeExpression = $attributes.outsideClick,
onDocumentClick = function(event){
if(event.target.id != 'rightMenu' && event.target.id != 'toggle-menu') {
$scope.$apply(scopeExpression);
}
};
$document.on("click", onDocumentClick);
$element.on('$destroy', function() {
$document.off("click", onDocumentClick);
});
}
}
}]);
In your HTML:
<aside class="rightbar" id="rightMenu" ng-class="{'noneStyle' : noneStyle}" outside-click="hideSideMenu()">
The effect is:
clicking on the top icon will toggle the right sidebar,
clicking on the right sidebar itself will trigger nothing,
and clicking on somewhere else will hide the right sidebar.
The basic logic is:
Create a customized directive named "outsideClick" and apply it to the right sidebar menu by adding an attribute outside-click="hideSideMenu()"
The function name hideSideMenu is passed in to the directive, which adds an click event to the document.
When user clicks to the document, if the target id is not rightMenu and not toggle-menu, the right sidebar will be hidden.
Reference: http://vadimpopa.com/onblur-like-for-a-div-in-angularjs-to-close-a-popup/
Related
So I have a custom navbar toggler effect to show when the hamburger is clicked.. but annoyingly it doesnt work an angular component but worked fine on simple non angular websites.
This is my code which is in home.component.ts and is within the ngOnInit method.
It gets the body and elements no problem, JQuery all works, yet when I click on the hamburger the
navbarCollapse.on('show.bs.collapse) event does not fire. Is there some issue with capturing bootstrap4 events in an angular component? show.bs.collapse is a bootstrap event.
var body = $('#mainbody');
var navbar = $('.navbar');
var navbarCollapse = $('.navbar-collapse');
// Add the needed HTML elements for the plugin to work.
// All the elements are styled in navbar-sidemnu.css.
body.append('<div class="side-menu-overlay"></div>');
var overlay = $('.side-menu-overlay');
console.log(overlay);
body.append('<div id="side-menu"></div>');
var sideMenu = $('#side-menu');
console.log(sideMenu);
sideMenu.append('<button class="close"><span aria-hidden="true">×</span></button>')
var sideMenuCloseBtn = sideMenu.find('.close');
sideMenu.append('<div class="contents"></div>')
var sideMenuContents = sideMenu.find('.contents');
// Configure Slide menu direction
if (navbar.hasClass('better-bootstrap-nav-left')) {
sideMenu.addClass('side-menu-left');
}
// This event is trigerred when the user clicks the navbar toggle button.
navbarCollapse.on('show.bs.collapse', function (e) {
// Stop the default navbar behaviour (don't open the collapse navigation).
e.preventDefault();
alert("clicked hamburger!");
// Instead we copy the navbar contents and add them to our side menu.
var menuContent = $(this).html();
sideMenuContents.html(menuContent);
// Animate the side menu into frame.
slideIn();
});
// Hide the menu when the "x" button is clicked.
sideMenuCloseBtn.on('click', function (e) {
e.preventDefault();
slideOut();
});
// Hide the menu when the overlay element is clicked.
overlay.on('click', function (e) {
slideOut();
});
// Listen for changes in the viewport size.
// If the original navbar collapse is visible then the nav is expanded.
// Hide/Show the menu accordingly.
$(window).resize(function () {
if (!navbarCollapse.is(":visible") && body.hasClass('side-menu-visible')) {
sideMenu.show();
overlay.show();
}
else {
sideMenu.hide();
overlay.hide();
}
});
function slideIn() {
body.addClass('overflow-hidden');
sideMenu.show();
setTimeout(function () {
body.addClass('side-menu-visible');
overlay.fadeIn();
}, 50);
}
function slideOut() {
body.removeClass('side-menu-visible');
overlay.fadeOut();
setTimeout(function () {
sideMenu.hide();
body.removeClass('overflow-hidden');
}, 400);
}
This was solved by putting the js in an injectable service and using that in my component.
I have a dropdown menu within a div element. Calling the javascript function HideDropdown() hides the menu when any other main link on the page is clicked (not including links in the dropdown menu itself):
<script>
function HideDropdown() {
$("#dropdown-content-id2").hide();
$("#dropdown-content-id").hide();}
</script>
I also want to call HideDropdown() to hide the menu (if it's open) when I click anywhere on the body except the dropdown menu itself.
In the body tag I inserted this:
<body onload="ShowPage(1)" onclick="HideDropdown()">
That successfully hides the dropdown when I click anywhere on the screen. I want to exclude clicks on the link that shows the dropdown menu and anywhere on the dropdown menu itself, so I revised the body tag:
<body onload="ShowPage(1)" onclick="HideDropdownCall(e)">
and created a new javascript function to call from the body onclick:
<script>
function HideDropdownCall(e) {
if(e.target.id != "dropdown-content-id" ){
HideDropdown();
}
</script>
but that didn't work, so I revised it:
<script>
function HideDropdownCall(e) {
if(e.target.id != "dropdown-content-id" ){
$("#dropdown-content-id2").hide();
$("#dropdown-content-id").hide();}
}
</script>
but that still doesn't work.
So my question is, how can I call the HideDropdown() function from a body click, filtered so that clicks on the dropdown menu itself don't count?
Thanks very much for any help.
EDIT:
After some work, I whittled down my problem to this: I can call the HideDropdown() function from the body tag like this:
<body onload="ShowAjax(1)" onclick="HideDropdown()">
That works. But when I change it to the same function with qualifications and (not if the click event is fired by the dropdown menu), the dev console says "TypeError: e is undefined" so it has something to do with the conditional statement:
<body onload="ShowAjax(1)" onclick="HideDropdown_B()">
<script>
function HideDropdown_B(e) {
if(e.target.id != "dropdown-content-id" ){
$("#dropdown-content-id2").hide();
$("#dropdown-content-id").hide();}
}
</script>
So my problem now boils down to finding out why the new function above returns a type error when the same program without the if statement works.
What you could do is add the property data-prevent='true' on the elements that you want to prevent hiding the dropdown.For example:
Link
and modify your function to filter out those elements like so:
function hideDropdown(evt) {
evt.preventDefault(); // you might not need this (usefull in case of a tags & preventing redirects)
if (!evt.target.getAttribute('data-prevent') || evt.target.getAttribute('data-prevent') === 'false') {
$("#dropdown-content-id2").hide();
$("#dropdown-content-id").hide();
}
}
Here is an example of how it could be done:
let menu = document.getElementById('menu');
document.body.addEventListener('click', e => {
if (!menu.contains(e.target))
console.log('close menu');
});
<div id='menu'><a id='link'>link</a> and menu</div>
document body here
However, you may actually want to close menu depending on which link were clicked.
Another way to do so:
let menu = document.getElementById('menu');
menu.addEventListener('click', e => e.stopPropagation());
document.body.addEventListener('click', e => console.log('close menu'));
<div id='menu'><a id='link'>link</a> and menu</div>
document body here
Thanks to everyone who answered. I solved this problem. Here is the solution:
In the body tag:
<body onload="ShowPage(1)" onclick="HideDropdown_B(event)">
The HideDropdown_B function:
<script>
function HideDropdown_B(event) {
TargetID = event.target.getAttribute('id');
TargetClass = event.target.getAttribute('class');
if((TargetID != "dropdown-content-id") && (TargetClass != "button_01") && (TargetClass != "dropdown") && (TargetClass != "button_dropdown") ) {
$("#dropdown-content-id2").hide();
$("#dropdown-content-id").hide();}
}
</script>
That works to close the menu when clicking anywhere except the excluded elements.
Here's my function,
$(document).ready(function () {
$('.a').click(function () {
var here = $(this).next('.b');
if (here.is(":visible")) {
here.hide();
} else {
here.show();
}
return false;
});
});
So, whenever I click the button it opens a small tab on same webpage & whenever I click it again it closes it. But once I open the tab I can't close it by just clicking somewhere on webpage apart from tab. I have to click the button again to close it.
How can I close tab just by clicking somewhere on webpage also by on the button?
I end up searching for this on almost every project, so I made this plugin:
jQuery.fn.clickOutside = function(callback){
var $me = this;
$(document).mouseup(function(e) {
if ( !$me.is(e.target) && $me.has(e.target).length === 0 ) {
callback.apply($me);
}
});
};
It takes a callback function and passes your original selector, so you can do this:
$('[selector]').clickOutside(function(){
$(this).removeClass('active'); // or `$(this).hide()`, if you must
});
Nice, chainable, elegant code.
On document click, the closest helps to check whether the tab has been clicked or not:
$(document).click(function (e) {
if($('.b').is(':visible')&&!$(e.target).closest('.b').length){
$('.b').hide();
}
});
You want to check for a click on the body :
$("body").click(function(e) {
if(e.target.id !== 'menu'){
$("#menu").hide();
}
});
menu would be the id of the menu.
If the body is clicked and the id of the div clicked doesn't equal that of the menu, then it closes.
Check this implementation
jQuery(document).ready(function() {
$(document).on('click','body, #btn',function(ev){
ev.stopPropagation()
if(ev.target.id== "btn"){
if($('#modal').is(':visible')) {
$('#modal').fadeOut();
} else{
$('#modal').fadeIn();
}
} else {
$('#modal').fadeOut();
}
});
});
html, body {
height: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">
Click Me!
</button>
<div id="modal" style="background-color:red;display:none;">
BLA BLA BLA
</div>
To check if the clicked element is outside of a given container, i.e. a menu, we can simply check if the event target is a child of the container. Using JQuery -
$('body').click(function(e) {
if ( 0 === $(e.target).parents('#container-id').length ) {
/// clicked outside -> do action
}
})
you have to add a click listener to the parent element, like here:
$('.parent-div').click(function() {
//Hide the menus if visible
});
Also because click events bubbled up from child to the parent,
you can exclude the click on the child element to get bubbled up and count as the parent click too. you can achieve this like below:
//disable click event on child element
$('.child-div').click(function(event){
event.stopPropagation();
});
I'm using the following for a dropdown:
/* recurse through dropdown menus */
$('.dropdown').each(function() {
/* track elements: menu, parent */
var dropdown = $(this);
var menu = dropdown.next('div.dropdown-menu'), parent = dropdown.parent();
/* function that shows THIS menu */
var showMenu = function() {
hideMenu();
showingDropdown = dropdown.addClass('dropdown-active');
showingMenu = menu.show();
showingParent = parent;
};
/* function to show menu when clicked */
dropdown.bind('click',function(e) {
if(e) e.stopPropagation();
if(e) e.preventDefault();
showMenu();
});
/* function to show menu when someone tabs to the box */
dropdown.bind('focus',function() {
showMenu();
});
});
/* hide when clicked outside */
$(document.body).bind('click',function(e) {
if(showingParent) {
var parentElement = showingParent[0];
if(!$.contains(parentElement,e.target) || !parentElement == e.target) {
hideMenu();
}
}
});
Notice:
$(document.body).bind('click',function(e) {
The problem is that the dropdown opens on click or when you tab to it. But it only closes on click, not when you tab out.
How can I bind an event to mean "tabbing out" ,losing focus, so the dropdown closes?
Thanks
You could trigger a click outside when you press the tab key. Like this:
$('#your_dropdown').bind('keydown', function(e) {
var keyCode = e.keyCode || e.which;
if (keyCode == 9) { //If it's the tab key
$("body").click(); //Force a click outside the dropdown, so it forces a close
}
});
Hope this helps. Cheers
Try the blur event, which will be triggered when the control loses focus (i.e., when the user clicks outside the control or uses the keyboard to tab to the next control).
Put something like this just after your existing focus binding:
dropdown.bind('blur',function() {
// whatever tests you want
hideMenu();
});
(You shouldn't then need the separate click binding that you're currently using to hide the menu.)
P.S. You might also consider focusout, which is similar to blur except that it bubbles.
Seems like you're looking for the onblur event?
I'm trying to write a web app which replaces the context menu (right-click menu) with my own customized ones. I want it so that when the user clicks on a table row, they get one certain context menu and when they click on the background of the page, they get a different one.
I have already written the menus and gotten them working. The problem comes in when trying to figure out how to get the background's menu to show ONLY when clicking on the background and how to get the table row's menu to show when that is clicked.
I tried using document.body.oncontextmenu for the body and and setting the oncontextmenu function for each table row, but the body's oncontextmenu function overrides the row's so I get the wrong menu. The menu for the table rows DOES work if I stop using the body's menu, so that's not the issue.
I could be using the wrong events, so is there a different event for just the background (and not the elements on top of the background)? Or a way to "prioritize" the events so the table row's function takes precedence?
This is how the code looks:
var tableMenu;
var bodyMenu;
window.onload = function()
{
bodyMenu = new rightClickMenu("bodyMenu");
document.body.oncontextmenu = function() { bodyMenu.show(); tableMenu.hide(); }
bodyMenu.add("Add Entry", function()
{
alert("ADD");
});
tableMenu = new rightClickMenu("tableMenu", "tblSims");
simRows = getElementsByClassName("trSimRow");
for (var i in simRows)
simRows[i].oncontextmenu = function() { tableMenu.show(this.id.substring(2)); bodyMenu.hide(); }
tableMenu.add("Delete Entry", function(mac)
{
alert("DELETE");
});
document.body.onclick = function()
{
bodyMenu.hide();
tableMenu.hide();
};
}
You can capture the target element, e.g.:
$('*').click(function(e) {
alert(e.target);
alert(e.target.tagName);
if(e.target.tagName == 'html') {
// show background menu
}
});
You have to work with the Javascript Event Propagation model. What happens is that your click event is automatically passed down the layers of objects on a page that have been registered as event listeners, unless you explicitly tell it to stop, try something like this:
function setupClickHandlers()
{
document.getElementsByTagName('body')[0].onclick = doBodyMenu;
document.getElementById('tableID').onclick = doTableMenu;
}
function doBodyMenu()
{
//do whatever it does
}
function doTableMenu(e)
{
//do whatever it does
//stop the event propagating to the body element
var evt = e ? e : window.event;
if (evt.stopPropagation) {evt.stopPropagation();}
else {evt.cancelBubble=true;}
return false;
}
This should deal with the way each browser handles events.
$( document ).ready(function() {
var childClicked = false;
// myContainer is the nearest container div to the clickable elements
$("#myContainer").children().click(function(e) {
console.log('in element');
childClicked = true;
});
$("#myContainer").click(function(e){
if(!childClicked) {
console.log('in background');
e.preventDefault();
e.stopPropagation();
}
childClicked = false;
});
});
#myContainer {
width:200px;
height:200px;
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="myContainer" style="">
link
<div style="width:50px;height:50px;background-color: white;">
another link
</div>
</div>