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.
Related
I am building a chrome extension that adds a button to https://www.fashionnova.com/ items.
I'd like to only append my button once, but when I used an if statement my button did not appear. Any suggestions on how to solve this?
jQuery("document").ready(function ($) {
var button = CreateButton();
$(window).scroll(function () {
className = ".product-tile__badges";
console.log($(className).children()[1].className);
console.log("i work");
$(className).append(button);
$(".product-tile__badges").mouseenter(function () {
button.childNodes[1].style.display = "block"; // Makes the dropdown appear
});
$(".product-tile__badges").mouseleave(function () {
button.childNodes[1].style.display = "none"; // Makes the dropdown appear
});
});
});
You could use jQuery's unbind to remove the scroll event listener once the button has been appended.
That would give something like:
jQuery("document").ready(function ($) {
var button = CreateButton();
function injectButton() {
var className = ".product-tile__badges";
// append button
$(className).append(button);
// add event listener to show dropdown on mouse enter
$(className).mouseenter(function () {
button.childNodes[1].style.display = "block";
});
// add event listener to hide dropdown on mouse leave
$(className).mouseleave(function () {
button.childNodes[1].style.display = "none";
});
// remove handler from window scroll event listenenr
$(window).unbind('scroll', injectButton);
}
// attach the event handler on window scroll
$(window).scroll(injectButton);
});
I want to display a form in a sidebar using a panel (https://developer.microsoft.com/en-us/fabric-js/components/panel/panel). The description of this control suggests it's modal, but it's implemented in such a way that panel is dismissed when the overlay is clicked. I want to stop this behaviour so that the panel is only dismissed when the user clicks Ok, Cancel or the close button at the top right.
I know that this is possible using react. I'm trying to achieve something similar to the Panel - Scrolling Content Sample at https://developer.microsoft.com/en-us/fabric#/components/panel
var t = function() {
function e(e) {
if (e)
this.overlayElement = e;
else {
var t = document.createElement("div");
t.setAttribute("class", "ms-Overlay"),
this.overlayElement = t
}
this.overlayElement.addEventListener("click", this.hide.bind(this), !1)
}
return e.prototype.remove = function() {
this.overlayElement.parentElement.removeChild(this.overlayElement)
}
,
e.prototype.show = function() {
this.overlayElement.classList.add("is-visible"),
document.body.classList.add("ms-u-overflowHidden")
}
,
e.prototype.hide = function() {
this.overlayElement.classList.remove("is-visible"),
document.body.classList.remove("ms-u-overflowHidden")
}
,
e
}();
Here's the fabricJS source code, which binds the "hide" function to the click event for the element with class ms-Overlay
if you remove/comment the hide function. The overlay won't be able to be removed on click. That's the easy but dangerous way. Another approach would be to removeEventListener
I have having a little trouble with the slideToggle when I have a link inside of the slideup panel. What I am trying to do is have the ability to press a button and a div will slide up and display related posts and once you press another or the related project button on the page it will close the toggle and reveal another effect that I am using (100% width and heigh popup). The script I am using works perfect but I am running into one problem. When I click a related post inside of the slideToggle it causes the div to slide down instead of going to the page that represents the link.
Here is my code below and an example http://jsfiddle.net/K8vBg/15/.
$(document).ready(function(){
// build a variable to target the #menu div
var menu = $('#menu')
// bind a click function to the menu-trigger
$('#menu-trigger').click(function(event){
event.preventDefault();
event.stopPropagation();
// if the menu is visible slide it up
if (menu.is(":visible"))
{
menu.slideUp(1000);
}
// otherwise, slide the menu down
else
{
menu.slideDown(400);
}
});
$(document).not('.projectHolder-small,#projectSpecs').click(function(event) {
event.preventDefault();
if (menu.is(":visible"))
{
menu.slideUp(400);
}
});
})
If I change .projectHolder-small,#projectSpecs in the .not function to just read #menu then I am able to click the link inside of the panel but the panel will not slideDown when I click another button on the page. The popup from #project specs will just go over the panel instead of closing it.
Is there something I am missing in my script?
Thank you
Try changing the $(document).not().click() to:
$(document).click(function(event){
if(!$(event.target).closest('.projectHolder-small,#projectSpecs').length){
if (menu.is(":visible")){
menu.slideUp(400);
}
}
});
I am using closest() instead of the usual is(), so that even clicking on the children elements of '.projectHolder-small,#projectSpecs' the panel won't close.
I rewrote the script to the following and it works perfect
$(document).ready(function () {
var $frm = $('#menu').hide();
var $bts = $("#menu-trigger").on('click', function () {
var $this = $(this)
$bts.filter(".selected").not(this).removeClass('selected');
$this.toggleClass('selected');
if ($this.hasClass('selected') && $frm.is(':visible')) {
$frm.stop(true, true).slideUp(function () {
$(this).slideDown()
});
} else {
$frm.stop(true, true).slideToggle();
}
});
$bts.filter('.selected').click();
$("#projectSpecs, #menuButton").click(function () {
$bts.filter(".selected").removeClass('selected');
$frm.slideUp();
});
});
The Fiddle: http://jsfiddle.net/bscn3/
Scenario:
I want to use nested toggles inside tabbed containers, as in the fiddle.
My Issue:
When I click on Main Toggle ("Toggle 1") or ("Toggle 2"), the inner contents display.
But it closes if I click on anything inside. For Eg. If I click on Toggle 2, and if I click on Tab 1 -> Nested Toggle 1, Toggle 2 itself closes.
I want it to remain open.
My Guess:
The JQuery working closes the toggle if anything related to the Toggle (Even text content) is clicked.
My Need:
I want the Toggle to close only if those rectangular headers are clicked.
Also, if you can help clean up the code in such a way, that I don't need to write separate JS to make inner nested Toggles work independently of its parent or children toggles, it would great.
Currently I have two Toggle JS Functions written for the two toggles in example.
//TOGGLE
$('.toggle-view li').click(function () {
var text = $(this).children('.t');
if (text.is(':hidden')) {
text.slideDown('fast');
$(this).children('.toggle').addClass('tactive');
} else {
text.slideUp('fast');
$(this).children('.toggle').removeClass('tactive');
}
});
//TOGGLE L2
$('.toggle-view2 li').click(function () {
var text2 = $(this).children('.t2');
if (text2.is(':hidden')) {
text2.slideDown('fast');
$(this).children('.toggle2').addClass('tactive2');
} else {
text2.slideUp('fast');
$(this).children('.toggle2').removeClass('tactive2');
}
});
P.S. I haven't written the JS Code, I am using someone's template.
Thanks! :)
Seems like a pretty simple solution...
It's happening because the toggle currently activates whenever you click anythin inside of the li element (which includes the other toggle elements: .toggle2).
The solution therefore is to make it only activate the toggle when the .toggle/h6 element is clicked and change $(this).children(...) to $(this).siblings(...)
You can use the following as things are (same changes in TOGGLE and TOGGLE L2):
//TOGGLE
$('.toggle-view li .toggle').click(function () { // Changed selector
var text = $(this).siblings('.t'); // Changed to .siblings(...)
if (text.is(':hidden')) {
text.slideDown('fast');
$(this).addClass('tactive'); // Removed .children(...)
} else {
text.slideUp('fast');
$(this).removeClass('tactive'); // Removed .children(...)
}
});
//TOGGLE L2
$('.toggle-view2 li .toggle2').click(function () {
var text2 = $(this).siblings('.t2');
if (text2.is(':hidden')) {
text2.slideDown('fast');
$(this).addClass('tactive2');
} else {
text2.slideUp('fast');
$(this).removeClass('tactive2');
}
});
OR
Just use the first section...
//TOGGLE
$('.toggle-view li .toggle').click(function () {
var text = $(this).siblings('.t');
if (text.is(':hidden')) {
text.slideDown('fast');
$(this).addClass('tactive');
} else {
text.slideUp('fast');
$(this).removeClass('tactive');
}
});
and rename all of the .t2, .toggle2 etc. in your html to the same as the first one (i.e. .t2 becomes .t)
use event.stopPropagation()
i have updated jsfiddle
$('.toggle-view2 li').click(function (event) {
event.stopPropagation();
var text2 = $(this).children('.t2');
if (text2.is(':hidden')) {
text2.slideDown('fast');
$(this).children('.toggle2').addClass('tactive2');
} else {
text2.slideUp('fast');
$(this).children('.toggle2').removeClass('tactive2');
}
});
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>