I have a div over the whole page to close a dropdown menu when the big divis clicked. The thing is that I need pointer-events: none; because if I don't use it, the whole page gets blocked by the big div.
JS onclick won't work when I have pointer-events:none; So, I don't really know how to solve this.
function test() {
if (document.getElementById('div1').style.display == 'block') {
document.getElementById('div1').style.display = 'none';
}
else{
}
}
#big_div{
width: 100%;
height: 100%;
display: block;
pointer-events:none;
}
<div id="big_div" onclick="test()"></div>
Instead of using a div covering your whole page, put a click listener on the document, check to see if the clicked element is the menu or a child of the menu, if not then hide the menu
document.addEventListener("click",function(e){
var menu = document.getElementById("myMenu");
var target = e.target;
if(target !== menu && !menu.contains(target)){
menu.style.display = "none";
}
});
Demo
document.addEventListener("click",function(e){
var menu = document.getElementById("myMenu");
var target = e.target;
var openBtn = document.querySelector("button");
if(target !== menu && !menu.contains(target) && target !== openBtn){
menu.style.display = "none";
}
});
document.querySelector("button").addEventListener("click",function(){
document.getElementById("myMenu").style.display = "block";
});
menu {
width:120px;
height:300px;
background:#88DDFF;
display:none;
}
<menu id="myMenu"><span>some item</span></menu>
<button>Open menu</button>
pointer-events: none means no events will come through. Instead, you should close the menu by listening to click/mousedown events on the entire document (and remove your div that is set to pointer-events: none).
document.addEventListener('mousedown', function(e) {
// You may need a better check involving e.target because
// you won't want to close the menu when clicking inside the menu
// or on the button (if the menu is not open)
if (!e.target.contains(menuNode)) {
document.getElementById('div1').style.display = 'none';
}
});
Sorry, I didn't read your question carefully so I got downvotes for my wrong answer.
But, according to your question, you want to cover the whole page with that div to block the click event but you still want to receive the click event then you can do like this actually:
1) Remove pointer-events:none; from that div and add the cursor:
#big_div {
width: 100%;
height: 100%;
display: block;
cursor: none;
}
2) Add the listener to your div like I previously mentioned and prevent the click from there:
document.getElementById("big_div").addEventListener("click", function(e) {
e.preventDefault();
// Do whatever you want to do
if (document.getElementById('div1').style.display == 'block') {
document.getElementById('div1').style.display = 'none';
}
});
Related
I have an <a> element:
<a id='addNewElementk' onclick='//Some Js Code' class='continueButton'>Click To Add</a>
When this anchor is clicked , A new element added:
New Added Element
And the first anchor which was clicked , Is removed.
I want to select that new element.
I tried:
window.onload = function(){
var newElem = document.getElementsByClassName('continueButton')[1];
alert(newElem.innerHTML);
}
I'm using ('continueButton')[1] , As there is another input with the same class before that anchor.
But for sure I get Click To Add from the first one , As that's was found when the page is loaded.
So how can I select that new element?
You're attempting to select the element before it exists in the DOM.
You instead need to run that code within the click event handler of the first <a>, like this:
window.onload = function() {
document.querySelector('#addNewElementk').addEventListener('click', function(e) {
e.preventDefault();
var a = document.createElement('a');
a.textContent = 'New Added Element';
a.href = '#';
a.classList.add('continueButton');
a.addEventListener('click', function(e) {
console.log(a.innerHTML);
});
this.parentNode.insertBefore(a, this);
this.remove();
});
}
<a id='addNewElementk' href="#" class='continueButton'>Click To Add</a>
Note the use of addEventListener() over the outdated on* event attributes which should be avoided.
You are attempting to select on an element that doesn't exist in the DOM. Dynamically added elements can be accessed in a couple of ways, above someone has an answer that adds an event listener to the created element which is a solid solution. The other most common way would be to use event delegation (if you are familiar with jQuery that would be $(parentElement).on('action', 'elementWeWantToWatch', function)) in Vanilla js the pattern is effectively the same, find or make a container element for your dynamic html, then add a listener to that container. Inside the listener you will want to ensure the target matches whatever your dynamic selection would be and execute when you find a match.
In this Example
The event listener is initiated on page load to watch the container element. The listener watches for clicks on elements with the continueButton class and when it finds one it removes the clicked element and adds a new element (the counter is to demonstrate that new content is being displayed :D)
(function() {
let i = 1;
const makeButton = () => {
const a = document.createElement('a');
a.classList.add('continueButton');
a.href = '#';
a.textContent = `Button ${i}`
i++;
return a;
}
const init = () => {
const container = document.querySelector('.test');
container.addEventListener('click', e => {
if (e.target.classList.contains('continueButton')) {
let button = makeButton();
container.appendChild(button);
container.removeChild(e.target);
return;
}
});
};
if (document.readyState == 'loading') {
window.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})()
.test {
width: 100%;
display: block;
text-align: center;
}
.continueButton {
display: block;
color: white;
background-color: green;
border-radius 2px;
padding: 15px 30px;
line-height: 2;
margin: 50px auto;
width: 200px;
text-decoration: none
}
<section class="test">
<a id='addNewElementk' class='continueButton'>Click To Add</a>
</section>
Clicking on the button shows and hides the corresponding content.
function funC(id) {
var el = document.getElementById(id);
if(el.style.display == 'inline-block')
el.style.display = '';
else
el.style.display = 'inline-block';
}
button {margin:2px; outline:0; font-size:12px;}
span {padding:2px; border:1px solid silver;
font-size:12px;}
.cb {display:none;}
<button onclick="funC('cnt1');">b1</button><span id="cnt1" class="cb">content b1...</span>
<br />
<button onclick="funC('cnt2');">b2</button><span id="cnt2" class="cb">content b2...</span>
<br />
<button onclick="funC('cnt3');">b3</button><span id="cnt3" class="cb">content b3...</span>
fiddle example
1. But, how to hide content when clicking outside its area,
and as with showing the next content, hide the previous one?
2. Is it possible to do the same without using id?
Only pure javascript. Thank you.
This might not be a perfect solution but here is a proposition :
function hideAllContent() {
var elements = document.querySelectorAll(".cb");
for(var i =0, l = elements.length; i < l; i++) {
var element = elements[i];
element.visible = false;
element.style.display='none';
}
}
function funC(id, event) {
// We need to stop the event to avoid bubling until the body
event.stopPropagation();
// let's hide others before displaying the new one
hideAllContent();
var el = document.getElementById(id);
if(el.visible) {
el.visible = false;
el.style.display = 'none';
} else {
el.visible = true;
el.style.display = 'inline-block';
}
}
document.body.onclick = function(event) {
if (!event.target.classList.contains('cb')) {
hideAllContent();
}
}
button {margin:2px; outline:0; font-size:12px;}
span {padding:2px; border:1px solid silver;
font-size:12px;}
.cb {display:none;}
<button onclick="funC('cnt1', event);">b1</button><span id="cnt1" class="cb">content b1...</span>
<br />
<button onclick="funC('cnt2', event);">b2</button><span id="cnt2" class="cb">content b2...</span>
<br />
<button onclick="funC('cnt3', event);">b3</button><span id="cnt3" class="cb">content b3...</span>
About avoiding ids, you could use the target property on click event and find the sibling node or something like that or use a querySelector. But ids are safe and fine i would say.
No inline on-clicks attached.
No IDs use.
Used backward-compatible syntax for IE 11.
// JavaScript
// get all button and span tags
var btns = document.querySelectorAll('button');
var otherSpans = document.querySelectorAll('span');
// Detect all clicks on the document
document.addEventListener("click", function(event) {
const spanElems = document.querySelectorAll('span');
const spanElemsArray = Array.prototype.slice.call(spanElems);
let matches = event.target.matches ? event.target.matches('button') : event.target.msMatchesSelector('button');
// If user clicks inside the element, do nothing
if (matches) {
return;
} else {
// If user clicks outside the element, hide it!
spanElemsArray.forEach( function (spanElem) {
spanElem.classList.remove("open");
});
}
});
// convert buttons and spans variable objects to arrays
const btnsArray = Array.prototype.slice.call(btns);
const otherSpansArray = Array.prototype.slice.call(otherSpans);
// loop through every button and assign a click to each one
btnsArray.forEach( function (btn) {
btn.addEventListener('click', spanFunc)
});
// Pass the button clicked as a reference
function spanFunc(){
openSpan(this);
}
// toggle the display class on the span next to the button using nextElementSibling method
function openSpan(e) {
e.nextElementSibling.classList.toggle("open");
// hide every other spans
function otherSpanFunc() {
otherSpansArray.forEach( function (otherSpan) {
if (otherSpan !== e.nextElementSibling) {
otherSpan.classList.remove('open');
}
});
}
otherSpanFunc();
}
/* css */
button {margin:2px; outline:0; font-size:12px;}
span {padding:2px; border:1px solid silver;
font-size:12px;}
.cb {display:none;}
.open {display:inline-block;}
<!-- HTML -->
<button>b1</button><span class="cb">content b1...</span>
<br />
<button>b2</button><span class="cb">content b2...</span>
<br />
<button>b3</button><span class="cb">content b3...</span>
jsFiddle: https://jsfiddle.net/ypofz4d5/55/
I want to disable the link using it's id in Javascript. By default it's invisible as shown below. I will enable the link when the particular id came from back end.
HTML
<li id="viewroleId" style="display: none;">
<spring:message code="label.viewrole" />
</li>
Javascript:-
if (key == 1) {
var id = value;
var div = document.getElementById(id);
if(div != null){
if (div.style.display == 'none' || div.style.display == '') {
// Here it will display the link
div.style.display = 'block';
}
}
}
In the above Javascript code I will display the link, but I want to display and disable the link. How can I disable the link with CSS instead?
First, create a rule like this in css
.disabled {
display: block !important; /* since you set the element's display to none inline,
we need to use !important flag (which is pretty bad)
to override the inline style */
pointer-events: none; /* Disable an element interaction, so it will not respond any event */
color: #ccc; /* Gray out the text color to signify being disabled */
}
Now in your javascript, just give the element you want to disable the class disabled like so
if (key == 1) {
var id = value;
var div = document.getElementById(id);
if(div != null){
if (div.className.indexOf('disabled') === -1) {
// Your element will be visible, and disabled
div.className += ' disabled';
}
}
}
If your app is based on Angular use ng-if, this is the "natural way"
<a ng-if="true" href="yourlink.html">Link<a/>
<a ng-if="!true" href="#">Link<a/>
Is better to try to overwrite browser native implementation (link...);
I have a procedural feed within my website which loads in data every time the user scrolls to the bottom of the page; the usual stuff.
The pagination itself works fine; however, the clicking of buttons which utilize JavaScript do not work. At all.
This is the JavaScript trigger for the buttons which is not working:
var modalTrigger = document.querySelectorAll(".ts-modal__trigger"), // the buttons
modal;
document.onclick = function(e){ // document on click
for(var i = 0; i < modalTrigger.length; i++){ // iterate through each button
if(e.target == modalTrigger[i]){ // if target clicked was button
e.stopPropagation(); // stop dom event from bubbling
modal = document.getElementById(modalTrigger[i].getAttribute("data-activemodal"));
document.body.style.overflow = "hidden"; // disable scroll on page
modal.style.display = "block"; // display modal
}
}
}
As far as I'm aware, this should be working (with the use of stopPropagation()), but alas, it does not.
I was going to use Inline JS, but I feel like it's extremely unnecessary and could be done it just a couple of lines of separate JavaScript, instead of adding extra HTML into the mix for no reason.
So any, and all help is appreciated,
Thanks. :)
Fiddle: https://jsfiddle.net/xhp4cesr/
EDIT: I noticed that after removing the span within the button, it would work, but as soon as it was added back, it would not.
One way you can do this is to remove e.stopPropogation and also target the children
var modalTrigger = document.querySelectorAll(".ts-modal__trigger"), // the buttons
modal;
document.onclick = function(e) { // document on click
for (var i = 0; i < modalTrigger.length; i++) { // iterate through each button
if (e.target == modalTrigger[i] || modalTrigger[i].children) { /* <- added children as target */
modal = modalTrigger[i].getAttribute("data-activemodal");
console.log(modal);
}
}
}
a {
background: red;
padding: 40px;
}
span {
color: yellow;
}
<a class="ts-modal__trigger" data-activemodal="ts-main-feed_status-comments-overlay">
<span>11</span>
</a>
On a test webpage I have, there is a link like so:
HOME
The style for it is like so:
nav > a {
text-decoration: none;
color: #0000aa;
display: inline-block;
width: 80px;
padding: 0 10px;
}
nav > a:hover {
background-color: #eeeeee;
}
and switchf() (switch field) is like so:
function switchf(field,tab) {
document.getElementById("home").style.display = "none";
document.getElementById("about").style.display = "none";
document.getElementById("account").style.display = "none";
document.getElementById("contact").style.display = "none";
document.getElementById("t1").style.backgroundColor = "#dddddd";
document.getElementById("t2").style.backgroundColor = "#dddddd";
document.getElementById("t3").style.backgroundColor = "#dddddd";
document.getElementById("t4").style.backgroundColor = "#dddddd";
document.getElementById(field).style.display = "inline-block";
tab.style.backgroundColor = "#cccccc";
}
The link basically acts as a tab, to show a different thing. There are three others like it.
The JavaScript works fine switching tabs, but when I hover over a tab after I've used switchf(), it doesn't change color anymore.
Is there something wrong with my code?
thanks.
EDIT
this is how I fixed mine:
first, I added class="tab" to all the links, so they looked like this:
HOME<br />
second, I changed the javascript so that the function switchf() was like this:
function switchf(field,tab) {
document.getElementById("home").style.display = "none";
document.getElementById("about").style.display = "none";
document.getElementById("account").style.display = "none";
document.getElementById("contact").style.display = "none";
var t = document.getElementsByClassName("tag"); // here is different
for(var i = 0; i < t.length; i++) {
t[i].style.backgroundColor = "#dddddd";
t[i].addEventListener("mouseover");
t[i].addEventListener("mouseout");
}
document.getElementById(field).style.display = "inline-block";
tab.style.backgroundColor = "#cccccc";
}
and it worked.
Inline CSS takes precedence over stylesheets. Once you click on a link, it will set the background-color property for all links, hence all links will not change color when you hover over it.
A better alternative than hard-coding the style in your elements, you can try adding a CSS class to your links (like page-active) and style those elements as needed.
Yet another alternative that saves you from clearing old classes is adding a class or ID to the page and use that to hide/show links as needed.
<style>
nav > a {
display: none;
}
#page-about nav > a#link-home {
display: inline-block;
}
<body id="page-about">
<nav>
Home
About
</nav>
</body>
This should give you a general idea, polishing it is an exercise for the reader.