Made this example: https://jsfiddle.net/d8ak0edq/2/
document.getElementById('outer').oncontextmenu = function() { return false; };
outer = document.getElementById('outer');
outer.addEventListener('mousedown', foo);
function foo(evt) {
if (evt.which === 1) {
evt.target.style.backgroundColor = 'red';
} else if (evt.which === 3) {
evt.target.style.backgroundColor = 'blue';
}
}
/*
$outer = $('#outer');
$outer.on('mousedown', 'div', foo);
function foo(evt) {
if (evt.which === 1) {
$(this).css('background-color', 'red');
} else if (evt.which === 3) {
$(this).css('background-color', 'blue');
}
} */
#outer {
border: 2px solid black;
width: 300px;
height: 300px;
}
#inner {
position: relative;
left: 25%;
top: 25%;
border: 2px solid black;
width: 150px;
height: 150px;
}
<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Monoton">
<link rel="manifest" href="site.webmanifest">
<link rel="apple-touch-icon" href="icon.png">
<!-- Place favicon.ico in the root directory -->
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<div id="outer">
<div id="inner">
</div>
</div>
<script src="js/vendor/modernizr-3.5.0.min.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-3.2.1.min.js"><\/script>')</script>
<script src="js/plugins.js"></script>
<script src="js/main.js"></script>
</body>
</html>
As you can see the jQuery has a nice way to do it, the 2nd parameter sets the 'target' and 'this' and if you click on the outer div nothing will happen even the event handler is on the outer div.
How do I make this without jQuery?
So by making the event handler on inner would obviously "fix" the problem, but I want that the event stays on the outer div but targets only inner, how to make this work (and not by adding && !(evt.target===outer))?
The basic technique for delegation is: set a selectorable attribute on the inner, then attach event handler to the outer, then check for whether the event came from inner:
document.getElementById('outer').addEventListener('mousedown' function(outer_evt) {
if (outer_evt.target.id == 'inner') {
// I mousedowned on inner
}
});
If you have other events attached to outer (this includes events attached to any ancestor of outer), and don't want them fired when you fire the inner event, use outer_evt.stopImmediatePropagation() and/or outer_evt.stopPropagation() (respectively).
If you want to refer to the element that the event bubbled up to, that's .currentTarget. (that is, above, outer_evt.currentTarget === document.getElementById('outer'))
See also EventTarget.addEventListener()
Related
function clickHide(){
if (MouseEvent.button === 0) hide();
}
function hide(){
using.style.display = "none";
hidden.style.display = "none";
}
I have a problem with event bubbling. The thing is that I have this function hide(), which should be called only when clicking the red div. The problem is that it also gets called when I click the yellow div, which is placed inside the red div. Is there a nice way to prevent this from happening? Heard something about event.stopPropagation(), but I don't know how I would use it in this case.
You should use Event.stopPropagation(). Simply just call the stopPropagation() method on the event you are listening to.
Also see here for more info.
Edit: You can try it like this, it will only fire the event when you click on the parent element. The if statement checks if the target of the event is the parent element then calls hide() if not then it returns nothing.
const parentElement = document.querySelector(".parentElement");
const childElement = document.querySelector(".childElement");
parentElement.addEventListener("click", clickHide);
function clickHide(event) {
if(event.target !== parentElement){
return;
}
hide();
}
function hide() {
parentElement.classList.add('hidden');
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title></title>
<meta name="description" content="" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="" />
<style>
.parentElement {
border: 20px solid red;
}
.childElement {
background: yellow;
padding: 20px;
}
.hidden {
display: none;
}
</style>
<script src="test.js" async defer></script>
</head>
<body>
<div class="parentElement">
<div class="childElement"></div>
</div>
</body>
</html>
I have two events: A button event and a container event. I want to apply stopPropagation() for container function, when I click on button. How to do this in vanilla js?
Now when I click on button #btn two functions will called. My goal is, when I click on button #btn, the code for #btn should only run. Click on div with id #container shall do it the same.
const btn = document.getElementById('btn');
btn.addEventListener('click', ()=> {
console.log('click on btn')
})
const container = document.getElementById('container');
container.addEventListener('click', ()=> {
console.log('click on container')
})
#container {
border: 1px solid red;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<title>Welcome</title>
</head>
<body>
<div id="container">
<button id="btn">click</button>
</div>
</div>
<script src="app.js"></script>
</body>
</html>
You can use Element.closest() to detect click outside or inside specific element
check this example
const btn = document.getElementById('btn');
btn.addEventListener('click', ()=> {
console.log('click on btn')
})
const container = document.getElementById('container');
container.addEventListener('click', (e)=> {
if(!e.target.closest('#btn')){
console.log('click on container')
}
})
#container {
border: 1px solid red;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<title>Welcome</title>
</head>
<body>
<div id="container">
<button id="btn">click</button>
</div>
</div>
<script src="app.js"></script>
</body>
</html>
Simply add event.stopPropagation in your btn click handler
btn.addEventListener('click', ()=> {
console.log('click on btn')
event.stopPropagation()
})
I'm trying to display the window size, whenever I resize my window. but I'm not able to until I refresh the window, I want to see the window size on the fly while I'm resizing the window.
window.onload = init();
window.onresize = init();
function init() {
var status = document.querySelector("#pagesize");
status.innerHTML = "" + window.innerHeight + " " + window.innerWidth;
}
#pagesize {
border: 1px solid red;
padding: 2px;
color: red;
}
html code:-
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="style.css">
<title>window resize</title>
</head>
<body>
<p>PAGE WINDOW SIZE <span id="pagesize">NOT LOADED YET</span></p>
<script src="script.js"></script>
</body>
</html>
You need to add a reference to the function to the event handler. Or even better use addEventListener() so you don't overwrite existing handlers. You stored the result of the init() function in the event handler.
window.onload = init;
window.onresize = init;
/* or better use this */
//window.addEventListener('load', init);
//window.addEventListener('resize', init);
function init() {
var status = document.querySelector("#pagesize");
status.innerHTML = "" + window.innerHeight + " " + window.innerWidth;
}
#pagesize {
border: 1px solid red;
padding: 2px;
color: red;
}
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="style.css">
<title>window resize</title>
</head>
<body>
<p>PAGE WINDOW SIZE <span id="pagesize">NOT LOADED YET</span></p>
<script src="script.js"></script>
</body>
I need to know how can i toggle an event listener that works when the screen is less than 700px and when the screen is more than 700px the event listener gets removed
function myFunction(x) {
if (x.matches) { // If media query matches
document.getElementById("resources").addEventListener("click", function() {
alert("media worked")
})
} else {
document.getElementById("resources").removeEventListener("click", function() {
alert("media worked")
})
}
}
var x = window.matchMedia("(max-width: 979px)")
myFunction(x) // Call listener function at run time
x.addListener(myFunction) // Attach listener function on state changes
h1 {
color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1 id="title">abrir y cerrar</h1>
<button id="resources">click to toggle</button>
</body>
</html>
You need to use named functions if you want to use removeEventListener, since the function that you remove has to be the same one you added.
function clickHandler() {
alert("media worked");
}
function myFunction(x) {
if (x.matches) { // If media query matches
document.getElementById("resources").addEventListener("click", clickHandler)
} else {
document.getElementById("resources").removeEventListener("click", clickHandler)
}
}
var x = window.matchMedia("(max-width: 979px)")
myFunction(x) // Call listener function at run time
x.addListener(myFunction) // Attach listener function on state changes
h1 {
color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1 id="title">abrir y cerrar</h1>
<button id="resources">click to toggle</button>
</body>
</html>
Barmar has given the correct answer to the problem of your code. But I still wanted to add this to show that it's a possibility.
You could use CSS to, for example, disable a click on an element uing the pointer-events property.
var links = document.querySelectorAll('a');
function onClick(event) {
console.log(event);
event.preventDefault();
}
links.forEach(function(link) {
link.addEventListener('click', onClick);
});
.events-none {
pointer-events: none;
}
Without pointer-events: none
With pointer-events: none
I want to active the draggable and resizable function in jquery when (and only) the ctrl+alt button is pressed and disable when it's released and I wrote this code
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery UI Draggable - Default functionality</title>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<style>
#para {
width: 150px;
height: 150px;
padding: 0.5em;
}
.ui-resizable-helper {
border: 2px dotted #00F;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
$(function(e) {
if (e.ctrlKey || e.altKey) {
$("#para").draggable();
$("#para").resizable({
helper: "ui-resizable-helper"
});
}
});
</script>
</head>
<body>
<div id="para" class="ui-widget-content">
<h1 contenteditable>Header</h1>
<hr />
<p contenteditable>paragraph</p>
</div>
</body>
</html>
After I finished this code I tried to press ctrl+alt in the browser but it doesn't work, I've removed the if (e.ctrlKey || e.altKey) logic part and it works successfully but as I replace the logic statement back there it doesn't work
How do I solve this?
You'll need an event handler to catch the keypresses.
You can initialize the plugin as disabled and then enable it when the keys are pressed, and disable it again when the keys are released
$(function() {
$("#para").draggable({
disabled : true
});
$("#para").resizable({
helper : "ui-resizable-helper",
disabled : true
});
$(document).on({
keydown : function(e) {
if (e.ctrlKey && e.altKey) {
$("#para").draggable( "enable" );
$("#para").resizable( "enable" );
}
},
keyup : function() {
$("#para").draggable( "disable" );
$("#para").resizable( "disable" );
}
});
});
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery UI Draggable - Default functionality</title>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<style>
#para {
width: 150px;
height: 150px;
padding: 0.5em;
}
.ui-resizable-helper {
border: 2px dotted #00F;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body>
<div id="para" class="ui-widget-content">
<h1 contenteditable>Header</h1>
<hr />
<p contenteditable>paragraph</p>
</div>
</body>
</html>