xul : creating a right click context menu item for only hyperlinks - javascript

I got a question to ask on building firefox plugin, basically my aim is to do following things,
1) In my plugin I want to show right click context menu item for only links[anchor tags] and hide the menu item for rest of the page
2) How to add dynamic list to my menu, i.e., adding the number of menu list items dynamically depending upon user's choice.
Can someOne point me to a right direction
Thanks !!

Bind an event listener for the contextmenu event and check whether the clicked element is a link, e.g.:
window.addEventListener("contextmenu", function(e) {
var menu = document.getElementById('your-menu-id');
if(e.target.nodeName == 'A') {
menu.hidden = false;
}
else {
menu.hidden = true;
}
}, false);
Read more about event properties and the menu element properties.
Have a look at the menu element's appendItem method.

Related

Hide other dropdowns when one is already open not working

Building a mega menu that mostly works. Last step I'm trying to achieve is when a user clicks on a mega menu item, it closes all other mega menus that are open.
Here's the JavaScript code I have below. The mega menu currently toggles correctly when clicking on each parent navigation link, but doesn't currently hide other mega menus when one mega menu is open.
const navLink = document.getElementsByClassName("menu-item-has-children");
// Loop over main navigation links
for (let i = 0; i < navLink.length; i++) {
// Grab specific ID that each mega menu has
const menuId = document.querySelector(`#${dropDownMenu[i].id}`);
// On click of top nav items, toggle mega menu visibility (this works).
navLink[i].addEventListener("click", () => {
menuId.classList.toggle("display-on");
});
// If the mega menu is open (display-on class is active), then don't show the other mega menus.
// (This does not work).
return menuId.classList.contains("display-on")
? (menuId.style.display = "none")
: "";
}
Link to live demo including HTML here if need be.
Thanks.
I have forked your example and simplified it. You can see the code here.
I make usage of Event Delegation. This allows you to handle all the click events (open dropdown, close dropdown via close button) in a single event handler (line 14 in the example) which is easier to read and maintain in my opinion.
The example does also close an already opened dropdown menu (see line 21 - 23).
I have also added an event handler to the document object to handle clicks outside of a dropdown to close it like you did.
Hope it solves your problem.
Best regards

The back button does not work in the responsive menu

What I want to do is to return to the previous menu when the return button is clicked, can you help? I'm leaving a link on how to write the code here
const submenutitle = document.querySelector('.submenutitle');
https://codepen.io/tolgagnydnn/pen/abWmMpp
The problem was you had two listeners and the second (the back button) was being overwritten by the first (because the back button is part of the group of listeners from the first set). Essentially, the back button had 2 event listeners on it. I consolidated them. I had to change some of the code, so that it would find the right element to add/remove classes from:
for (const mobilemainmenuitem of mobilemainmenuitems) {
mobilemainmenuitem.addEventListener("click", (e) => {
const submenu = e.target;
if (submenu.classList.contains("btn"))
submenu
.closest(".mobilesubmenu")
.classList.remove("showleft", "showvisibility");
else
submenu
.closest("li")
.querySelector(".mobilesubmenu")
.classList.add("showleft", "showvisibility");
});
}
https://codepen.io/kinglish/pen/OJmRevq?editors=1111

How to make a top level drop down item clickable

Im making a store in shopify, and have set up the navbar as a dropdown.
Clicking the nav links will only make it display or hide the drop down, but what i need is for it to, on the first click, display, then clicking the parent will follow the link.(for instance,my home item drops down, but i can't actually get home, and need it as a drop down item.)
HeaderView.prototype.events = {
"click .main-nav .dropdown > a": "toggleMenu",
};
HeaderView.prototype.toggleMenu = function(e) {
var dropdown;
e.preventDefault();
dropdown = this.$(e.target).closest(".dropdown");
if (!this.$(e.target).closest(".dropdown-nav").length) {
this.$(".dropdown").not(dropdown).removeClass("active");
return dropdown.toggleClass("active");}
};
Obviously the e.preventDefault is stopping the link from working, but I'm not sure how to make it give an active class on the first click, then allow the link to be followed when the drop down is visible. It works with hover, but then won't work on touch devices.
Any help/suggestions would be appreciated, thanks.
You only need to call e.preventDefault() when you are doing the first click. Otherwise it is, like you said, preventing it from working.
Try this instead:
HeaderView.prototype.toggleMenu = function(e) {
var dropdown;
dropdown = this.$(e.target).closest(".dropdown");
if (!this.$(e.target).closest(".dropdown-nav").length) {
e.preventDefault();
this.$(".dropdown").not(dropdown).removeClass("active");
return dropdown.toggleClass("active");
}
};
Thanks for the response, I was going along the same line of thought and wound up with a simple, "if the class is active prevent default" type statement.
if (!this.$(".dropdown").hasClass("active")){
e.preventDefault();
So basically, if the drop down shows, allow the link, if isn't showing, prevent it;
thus keeping the top level as a link if it's drop down is 'open'.
HeaderView.prototype.toggleMenu = function(e) {
var dropdown;
dropdown = this.$(e.target).closest(".dropdown");
if (!this.$(".dropdown").hasClass("active")){
e.preventDefault();
if (!this.$(e.target).closest(".dropdown-nav").length) {
this.$(".dropdown").not(dropdown).removeClass("active");
return dropdown.toggleClass("active");}
}
};

Get items from Select2 after data has been loaded

I'm trying to force the open method and select item with select2 like this.
$(".select").select2('open')
$(".select").on('select2-loaded', function (e) {
items = e.items.results;
if (items.length == 1) {
$(this).val(items[0].text);
}
});
$(".select").select2('close');
But I cannot get inside the select2-loaded evaluation and the close is happening also to quick. I want to select the first element by default if there is only one element on the list.
When the 'open' occurs, it automatically performs the mechanism to get and load all the elements in my list. If I comment the close method it will take some milliseconds to display the elements on the list.
But what I want is to refresh my list (this is done by the open) then I want to select only if there one element and the close my list ('select')
How can I achieve this? This behaviour will be trigger by a onchange event of another list. (nested selects)
You should move the close call INSIDE the select2-loaded event, so it'll only close the select element after it selected the item. Otherwise you're opening, setting event for future event, then closing immediately.
$(".select").select2('open')
$(".select").on('select2-loaded', function (e) {
items = e.items.results;
if (items.length == 1) {
$(this).val(items[0].text);
$(".select").select2('close');
}
});

How to set the focus on a javascript modal window?

Our website involves some javascript that produces overlay modal windows.
There is one accessibility problem with this though, once the modal is triggered, the focus is still on the trigger element and not on the modal itself.
These modals can include all sorts of html elements, headings, paragraphs and form controls. What I would like is the focus to begin on the first element within the modal, so most likely to be a h4 tag.
I have explored using the focus() function however this does not work with a number of html elements.
One thought was to add an empty a tag in the window which could gain the focus, but I am unsure about this method.
very late to the party, but the existing answers do not respect accessibility.
The W3C wiki page on accessible modals offers more insight than what's asked in the OP, the relevant part is having tabindex=-1 on the modal container (which should also have an aria-dialog attribute) so it can get :focus.
This is the most accessible way of setting the focus on the modal, there is also more documentation about keeping it in the modal only - and returning it to the element that triggered the modal - quite a lot to be explained here, so I suggest anyone interested to check the link above.
You can append textbox to the beginning of the modal HTML, set focus then hide the textbox. Should have the desired effect as far as I understand your needs.
You could try to blur() the element that has the focus.
to trap focus inside the modal I have used this approach. So the basic idea behind it is exactly to trap the focus in the modal HTML elements and not allowing it to go out of the modal.
// add all the elements inside modal which you want to make focusable
const focusableElements =
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
const modal = document.querySelector('#exampleModal'); // select the modal by it's id
const firstFocusableElement = modal.querySelectorAll(focusableElements)[0]; // get first element to be focused inside modal
const focusableContent = modal.querySelectorAll(focusableElements);
const lastFocusableElement = focusableContent[focusableContent.length - 1]; // get last element to be focused inside modal
document.addEventListener('keydown', function(e) {
let isTabPressed = e.key === 'Tab' || e.keyCode === 9;
if (!isTabPressed) {
return;
}
if (e.shiftKey) { // if shift key pressed for shift + tab combination
if (document.activeElement === firstFocusableElement) {
lastFocusableElement.focus(); // add focus for the last focusable element
e.preventDefault();
}
} else { // if tab key is pressed
if (document.activeElement === lastFocusableElement) { // if focused has reached to last focusable element then focus first focusable element after pressing tab
firstFocusableElement.focus(); // add focus for the first focusable element
e.preventDefault();
}
}
});
firstFocusableElement.focus();
you can find it here trap focus inside the modal

Categories

Resources