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);
});
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've implemented a navbar using Bulma but I'm having trouble getting it to close after the user has clicked on an element inside the navbar. I have a single page setup so the page does not refresh, therefore the navbar doesn't "reset" and close.
Sorry if the answer is obvious or simple, I'm very new to JavaScript. I've attached a snippet of the code below.
document.addEventListener('DOMContentLoaded', () => {
// Get all "navbar-burger" elements
const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
// Check if there are any navbar burgers
if ($navbarBurgers.length > 0) {
// Add a click event on each of them
$navbarBurgers.forEach( el => {
el.addEventListener('click', () => {
// Get the target from the "data-target" attribute
const target = el.dataset.target;
const $target = document.getElementById(target);
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
el.classList.toggle('is-active');
$target.classList.toggle('is-active');
});
});
}
});
Any help would be greatly appreciated, thank you!
When elements get added to the DOM (in your case the .navbar-burgers) then you need to reattach the listeners. You could wrap your above javascript in a function and call it again when the content of your site has changed.
Or you specify a parent element which listens to a click event and check if the clicked target inside of it has a class .navbar-burger. E.g.:
document.addEventListener('DOMContentLoaded', () => {
if (document.querySelector('.navbar-burger')) {
document.querySelector('body').addEventListener('click', (el) => {
if (el.currentTarget.classList.contains('.navbar-burger')) {
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
el.classList.toggle('is-active');
document.getElementById(el.getAttribute('data-target')).classList.toggle('is-active');
}
});
}
});
In this example I specified body but I recommend you to be more specific. Because every click on your site will get into this event and checks if it is a navigation thing. However, the first option to reattach the listeners is a better practice.
I added an event listener on every navbar item to close the burger menu
item.addEventListener("click", () => {
document.getElementById(burger_el.dataset.target).classList.remove('is-active');
$target.classList.remove('is-active');
});
Here is the complete code I use to add the listeners for the burger menu:
document.addEventListener('DOMContentLoaded', () => {
const navbarBurgers = document.querySelectorAll('.navbar-burger');
const navbarItems = document.querySelectorAll(".navbar-item");
navbarBurgers.forEach(burger_el => {
burger_el.addEventListener('click', () => {
// Toggle burger-menu
document.getElementById(burger_el.dataset.target).classList.toggle('is-active');
$target.classList.toggle('is-active');
});
navbarItems.forEach(item => {
item.addEventListener("click", () => {
// Close burger-menu
document.getElementById(burger_el.dataset.target).classList.remove('is-active');
$target.classList.remove('is-active');
});
});
});
});
I have a div who can be displayed or not. When it's display I want to pass display to none if you click somewhere not in that div. So what I did is :
document.addEventListener('click',closeDiv)
document.getElementById('myDiv').addEventListener('click',stopPropagation)
function closeDiv(){
let div = document.getElementById('myDiv')
div.style.display='none'
}
But with that even if I click on the div, the display goes to none
Found the solution :
document.addEventListener('click',closeModal)
document.getElementById('myDiv').addEventListener('click',stopPropagation)
function stopPropagation(e){
e.stopPropagation();
}
function closeDiv(){
let div = document.getElementById('myDiv')
div.style.display='none'
}
If you make an window.addEventListener('click', outDiv);
and this function :
let myDiv = document.querySelector('myDiv');
function outDiv (event) {
if (!myDiv.classList.contain(event.target)) {
// Make Something
}
}
I use the jQuery to hide and show a div.
function bindIconClick() {
$('span.scroIcon').click(function(event) {
var eventIcon = $(event.target);
var contentPanel = eventIcon.parents('.panelTitle').next();
if (contentPanel.is(':hidden')) {
contentPanel.slideDown('slow');
} else {
contentPanel.slideUp('slow');
}
});
}
I want to test the function, I can use the trigger() to simulate the click event, but I don't know how to test the slideDown() and slideUp() effect.
I want to test the function bindIconClick ,means if I use the trigger() function simulate the click event, I want know does the contentPanel hide or show.
I want to test the full function bindIconClick , not the part of it. I want to test the full function is correct!
In fact , I want to test the effetc that when the span be clicked, will contentPanel hide or show ?
Use slideToggle function instead of if and else
function bindIconClick() {
$('span.scroIcon').click(function(event) {
var eventIcon = $(event.target);
var contentPanel = eventIcon.parents('.panelTitle').next();
contentPanel.slideToggle('slow');
});
}
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>