I have the following HTML code:
<script src="http://code.jquery.com/jquery-1.6.2.min.js"></script>
<div id="A" style="width:100px; height: 100px; background: #00FF00; padding: 15px;
z-index: 50; opacity: .5" onclick="javascript:alert('A')">
<div id="B" style="width:50px; height: 50px; background: #FF0000; z-index:10;"
onclick="javascript:alert('B')" >
</div>
</div>
I was hoping this would make it so that clicking on div B's position would not invoke it's onclick, but only A's since A ha a higher z-index.
If not with z-index, how can I achieve this ?
You can use event delegation for that - no need for z-indexes and the like. Assing one (1) click handler to the topmost div and, within the handler, use the event target/srcElement to decide what (not) to do with the originating element. Something like:
<div id="A" style="width:100px; height: 100px;
background: #00FF00; padding: 15px;
z-index: 50; opacity: .5"">
<div id="B" style="width:50px; height: 50px;
background: #FF0000; z-index:10;" ></div>
</div>
The handler function:
function myHandler(e){
e = e || event;
var el = e.srcElement || e.target;
// no action for #B
if (el.id && /b/i.test(el.id)){ return true; }
alert(el.id || 'no id found');
}
// handler assignment (note: inline handler removed from html)
document.querySelector('#A').onclick = myHandler;
See it in action
Your z-index's won't work as you need to change the css position to relative, fixed, or absolute. reference.sitepoint.com/css/z-index.
<div id="A" style="width:100px; height: 100px; background: green; padding: 15px;
z-index: 50; opacity: .5; position:relative;" onclick="alert('A'); return false;">
<div id="B" style="width:100%; height:100%; background: red; z-index:100;position:relative;"
onclick="window.event.stopPropogation();alert('B'); return false;" >
</div>
</div>
http://jsfiddle.net/SmdK8/
I think using position: absolute in your styles and positioning one over the other would do this. Currently div A and div B sit side by side.
<div id="A" style="width:100px; height: 100px; background: #00FF00; padding: 15px;
z-index: 50; opacity: .5" onclick="javascript:alert('A')">
<div id="B" style="width:50px; height: 50px; background: #FF0000; z-index:10;"
onclick="javascript:event.preventDeafult();" >
</div>
</div>
Do a "preventDefault" based on when you don't want B to fire.
Here's one way to handle toggling B's onclick event
example: http://jsfiddle.net/pxfunc/cZtgV/
HTML:
<div id="A">A
<div id="B">B
</div>
</div>
<button id="toggle">Toggle B onclick</button>
JavaScript:
var a = document.getElementById('A'),
b = document.getElementById('B'),
toggleButton = document.getElementById('toggle'),
hasOnClick = true;
a.onclick = function() { alert('hi from A') };
b.onclick = function() { alert('hi from B') };
toggleButton.onclick = function() {
if (hasOnClick) {
b.onclick = "";
} else {
b.onclick = function() { alert('hi from B') };
}
hasOnClick = !hasOnClick;
};
for bonus points there's a jQuery solution in the example.
Related
How do I make this only fire :hover for the target element (ignoring the parents)?
Assume this is recursive design of object inside object, therefore with the same classes and an autogenerated id.
.group:hover {
background-color: red;
}
.group {
border: 1px solid black;
width: 100px;
padding: 20px;
}
<div id="g1" class="group">aaaa
<div id="g2" class="group">bbbb
<div id="g3" class="group">cccc
</div>
</div>
</div>
Since you tagged the question with javascript you can achieve this using it. The key is to use .stopProgagation() which will stop events from "falling through" down to your other elements.
See example below:
document.querySelectorAll(".group").forEach(elem => {
elem.addEventListener('mouseover', function(e) {
e.stopPropagation();
this.classList.add('group-hover');
});
elem.addEventListener('mouseout', function(e) {
this.classList.remove('group-hover');
});
});
.group-hover {
background-color: red;
}
.group {
border: 1px solid black;
width: 100px;
padding: 20px;
}
<div id="g1" class="group">aaaa
<div id="g2" class="group">bbbb
<div id="g3" class="group">cccc
</div>
</div>
</div>
Alternatively, you could intead use e.target to get the target of the event if you wish not to use stopPropagation():
document.querySelectorAll(".group").forEach(elem => {
elem.addEventListener('mouseover', e => e.target.classList.add('group-hover'));
elem.addEventListener('mouseout', e => e.target.classList.remove('group-hover'));
});
.group-hover {
background-color: red;
}
.group {
border: 1px solid black;
width: 100px;
padding: 20px;
}
<div id="g1" class="group">aaaa
<div id="g2" class="group">bbbb
<div id="g3" class="group">cccc
</div>
</div>
</div>
Only with JS, and using events delegate for simpler way
const All_g = document.querySelector('#g1');
All_g.onmouseover = function(event) {
let target = event.target;
target.style.background = 'red';
};
All_g.onmouseout = function(event) {
let target = event.target;
target.style.background = '';
};
.group {
border: 1px solid black;
width: 100px;
padding: 20px;
}
<div id="g1" class="group">aaaa
<div id="g2" class="group">bbbb
<div id="g3" class="group">cccc
</div>
</div>
</div>
some explanations :=> https://javascript.info/mousemove-mouseover-mouseout-mouseenter-mouseleave
You can do it in the following way:
var elements = document.getElementsByClassName('group');
var lastElement = null;
elements.each(element =>{
lastElement = element;
});
lastElement.on('hover', function(){
//do anything you wish with element
})
Approach 1
Register hover event to toggle class and use event.stopPropagation();
https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation
The bubbles read-only property of the Event interface indicates
whether the event bubbles up through the DOM or not.
https://developer.mozilla.org/en-US/docs/Web/API/Event/bubbles
Approach 2
Mouseenter event - By design it does not bubble - so don't have to perform event.stopPropagation()
Though similar to mouseover, it differs in that it doesn't bubble and
that it isn't sent to any descendants when the pointer is moved from
one of its descendants' physical space to its own physical space.
https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseenter_event
I have a click event thats firing. It's working great and does what I need it to do. Here's the problem
The nature of the widget i'm building stacks elements on top of each other through position: absolute When i click on one of these stacked elements, only one event is firing, but id like every element to fire that is under the mouse cursor of the click. Is there a way to do this?
Please check the demo or run the code snippet in full page and click through all the divs to see the result message.
DEMO:
http://plnkr.co/edit/KRWvLmRhGbO200pFkOxL?p=preview
What I am doing here is :
Hide the top element
and
get the next absolute element's co-ordinate with document.elementFromPoint and then repeat.
Stack Snippet:
jQuery(document).ready(function(){
$common = $("div.common").on('click.passThrough', function (e, ee) {
var $element = $(this).hide();
try {
if (!ee) $("#output").empty();
$("<div/>").append('You have clicked on: '+$element.text()).appendTo($("#output"));
ee = ee || {
pageX: e.pageX,
pageY: e.pageY
};
var next = document.elementFromPoint(ee.pageX, ee.pageY);
next = (next.nodeType == 3) ? next.parentNode : next //Opera
$(next).trigger('click.passThrough', ee);
} catch (err) {
console.log("click.passThrough failed: " + err.message);
} finally {
$element.show();
}
});
$common.css({'backgroundColor':'rgba(0,0,0,0.2)'});
});
#output {
margin-bottom: 30px;
}
.common {
position: absolute;
height: 300px;
width: 300px;
padding: 3px;
border: 1px #000 solid;
}
.elem5 {
top: 150px;
left: 150px;
}
.elem4 {
top: 180px;
left: 180px;
}
.elem3 {
top: 210px;
left: 210px;
}
.elem2 {
top: 240px;
left: 240px;
}
.elem1 {
top: 270px;
left: 270px;
}
<script data-require="jquery#3.0.0" data-semver="3.0.0" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js"></script>
<div id="output"></div>
<div class="common elem1">Top Most Element</div>
<div class="common elem2">Element 2</div>
<div class="common elem3">Element 3</div>
<div class="common elem4">Element 4</div>
<div class="common elem5">Bottom Element</div>
Credit for source:
http://jsfiddle.net/E9zTs/2/
You can use customEvent property
Place all div in a parent div
add a click handler to the parent div
if there is a click in the parent box..determine whether the click is in any of the child boxes
If true. then send a click event to all child box
snippet
//This function changes the color of all child divs
function changeColor(e) {
this.style.background = "red";
}
//this function is attached to the parent div which will send that click event to all divs
function trigger(e) {
//create an event
event = new CustomEvent('click');
//if the event originates from a child div
if (e.target.className == 'box')
//loop through all child div
for (var i = 0; i < all_box.length; ++i) {
//dispatch a click event to each child div
all_box[i].dispatchEvent(event);
}
}
document.getElementById('parent').addEventListener('click', trigger)
var all_box = document.getElementsByClassName('box');
for (var i = 0; i < all_box.length; ++i) {
all_box[i].addEventListener('click', changeColor)
}
.box {
padding: 10px;
display: inline-block;
border: solid black;
}
#parent {
border: solid black;
padding: 10px;
}
;
<div id="parent">
<div class="box" id="primary">box1</div>
<div class="box">box2</div>
<div class="box">box3</div>
<div class="box">box3</div>
</div>
Let me explain it in a few words.
I have a menu with different colored buttons. For example When I mouseover/click button A (=blue e.g.) I want the bgcolor of the div also turning blue.
When I mouseover/click button B (=green) I want the bgcolor of the div also turning green.
Is there a possibility to this with a simple script?
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<script>
$(document).ready(function() {
$("button").hover(function () {
$(this).parents("navigatie").css("background-color", $(this).css("background-color"));
},
function () {
$(this).parents("navigatie").css("background-color", "white");
});
});
</script>
</head>
<body>
<div id="container">
<?php include("header.php");?>
<div id="navigatie">
<center>
<button class="A">Button A</button>
<button class="B">Button B</button>
</center>
</div>
<div id="tekst">
BLABLABLA
</div>
</div>
</body>
</html>
/* CSS */
navigatie {
width:100%;
height:100%;
transition:all 0.4s ease;
}
button {
width:75px;
height:50px;
border-style:none;
top: 20px;
position: relative;
color:white;
border: solid 1px white;
}
.A {
background-color:blue;
}
.B {
width: 200px;
height: 100px;
background-color:limegreen;
}
Use this for start you can enhance this with your own coding logic.
$('input:button').each(function() {
var color = $(this).attr("data-color");
$(this).css("background-color", color);
});
$('input:button').click(function() {
var color = $(this).attr("data-color")
$('#wrapper').css("background-color", color);
});
#wrapper {
padding: 50px;
background-color: #d0e4fe;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrapper">
<input type="button" name="color" data-color="red" value="Red">
<input type="button" name="color" data-color="green" value="Green">
<input type="button" name="color" data-color="purple" value="Purple">
<input type="button" name="color" data-color="#d0e4fe" value="Default">
</div>
This is how I would do it:
$("button").hover(function () {
$(this).parents("div").css("background-color", $(this).css("background-color"));
},
function () {
$(this).parents("div").css("background-color", "white");
});
Here is the JSFiddle demo
Full code after fix as per what you provided in your edit:
<html>
<head>
<style>
navigatie {
width:100%;
height:100%;
transition:all 0.4s ease;
}
button {
width:75px;
height:50px;
border-style:none;
top: 20px;
position: relative;
color:white;
border: solid 1px white;
}
.A {
background-color:blue;
}
.B {
width: 200px;
height: 100px;
background-color:limegreen;
}
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<script>
$(document).ready(function () {
$("button").hover(function () {
$(this).parents("#navigatie").css("background-color", $(this).css("background-color"));
},
function () {
$(this).parents("#navigatie").css("background-color", "white");
});
});
</script>
</head>
<body>
<div id="container">
<?php include("header.php");?>
<div id="navigatie">
<center>
<button class="A">Button A</button>
<button class="B">Button B</button>
</center>
</div>
<div id="tekst">
BLABLABLA
</div>
</div>
</body>
</html>
Try using jquery:
$("#[id]").hover(function({
$("#[id]").css({"[propertyname]":"[value]","[propertyname]":"[value]",...});
/*
Fill the brackets with the correct ids / classes and property names and values.
If you want to change the background on a click then replace .hover with .click
*/
If anyone finds something I did wrong or if there is a better way to do it, please correct me or let me know! I'm always open to better ideas! :)
If you're going to use CSS, there's only two ways of changing the style of an element through the state of another:
The targeted element must either be a child of the element receiving a state change, or a direct sibling (right underneath).
Using CSS's "+" selector, you can affect the next sibling element.
In your case this could be used to achieve this effect:
https://jsfiddle.net/Lrptjoh9/
The action occurs here:
.a .button:hover + .bg {
background: red;
}
.b .button:hover + .bg {
background: blue;
}
Although this requires the button and background elements to be siblings.
Vanilla JavaScript:
var btn = document.getElementById('btnA');
btn.addEventListener('click', function(e) {
var event = e || window.event,
target = event.target,
parent = target.parentNode,
color = parent.style.backgroundColor;
if(color === 'blue') {
parent.style.backgroundColor = 'white';
} else {
parent.style.backgroundColor = 'blue';
}
});
btn.addEventListener('mouseover', function(e) {
var event = e || window.event,
target = event.target,
parent = target.parentNode;
parent.style.backgroundColor = 'blue';
});
btn.addEventListener('mouseout', function(e) {
var event = e || window.event,
target = event.target,
parent = target.parentNode;
parent.style.backgroundColor = 'white';
});
.container{
position: relative;
width: 200px;
height: 100px;
text-align: center;
}
.container button{
position: relative;
top: 50%;
transform: translateY(-50%);
}
<div class='container'>
<button id="btnA">Button A</button>
</div>
I have a <div> with a ng-click but this <div> have a child element with also a ng-click directive.
The problem is that the click event on the child element trigger also the click event of the parent element.
How can I prevent the parent click event when I click on his child?
Here is a jsfiddle to illustrate my situation.
Thank you in advance for your help.
EDIT
Here is my code:
<body ng-app ng-controller="TestController">
<div id="parent" ng-click="parentClick()">
<div id="child" ng-click="childClick()"></div>
<p ng-bind="elem"></p>
</div>
<div><p style="text-align:center" ng-bind="childElem"></p></div>
</body>
<script>
function TestController($scope) {
$scope.parentClick = function() {
$scope.elem = 'Parent';
}
var i = 1;
$scope.childClick = function() {
$scope.elem = 'Child';
$scope.childElem = 'Child event triggered x' + i;
i++;
}
}
</script>
You should use the event.stopPropagation() method.
see: http://jsfiddle.net/qu86oxzc/3/
<div id="child" ng-click="childClick($event)"></div>
$scope.childClick = function($event) {
$event.stopPropagation();
...
}
Use event.stopPropagation to stop the event from bubbling up the DOM tree from child event handler.
Updated Demo
function TestController($scope) {
$scope.parentClick = function() {
$scope.elem = 'Parent';
}
var i = 1;
$scope.childClick = function(e) {
$scope.elem = 'Child';
$scope.childElem = 'Child event triggered x' + i;
i++;
e.stopPropagation(); // Stop event from bubbling up
}
}
body {
width: 100%;
height: 100%;
overflow: hidden;
}
#parent {
width: 100px;
height: 100px;
position: relative;
z-index: 1;
margin: 10px auto 0 auto;
background-color: #00acee;
border-radius: 2px;
cursor: pointer;
}
#parent:hover {
opacity: 0.5;
}
#child {
width: 20px;
height: 20px;
position: absolute;
top: 10px;
right: 10px;
z-index: 2;
background-color: #FFF;
border-radius: 2px;
cursor: pointer;
}
#child:hover {
opacity: 0.5;
}
#parent p {
width: 100%;
position: absolute;
bottom: 0px;
text-align: center;
color: #FFF;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script>
<body ng-app ng-controller="TestController">
<div id="parent" ng-click="parentClick()">
<div id="child" ng-click="childClick($event)"></div>
<!-- ^^^^^^^ -->
<p ng-bind="elem"></p>
</div>
<div>
<p style="text-align:center" ng-bind="childElem"></p>
</div>
</body>
also you can use this as it use do the same.
<div id="child" ng-click="childClick();$event.stopPropagation();"></div>
Even if Pieter Willaert's answer is much more beautiful i updated your fiddle with a simple boolean check:
http://jsfiddle.net/qu86oxzc/6/
function TestController($scope) {
$scope.boolean = false;
$scope.parentClick = function () {
if (!$scope.boolean) $scope.elem = 'Parent';
$scope.toggleBoolean();
}
var i = 1;
$scope.childClick = function () {
$scope.boolean = true;
$scope.elem = 'Child';
$scope.childElem = 'Child event triggered x' + i;
i++;
}
$scope.toggleBoolean = function () {
$scope.boolean = !$scope.boolean;
}
}
You can also try $event.stopPropagation();. write it after the child function. It working like a preventdefault.
<body ng-app ng-controller="TestController">
<div id="parent" ng-click="parentClick()">
<div id="child" ng-click="childClick();$event.stopPropagation();"></div>
<p ng-bind="elem"></p>
</div>
<div><p style="text-align:center" ng-bind="childElem"></p></div>
</body>
So I am modifying a web page and there is a table on the bottom of the page that starts minimized. When you click the arrow it opens upward to reveal the table. I am attempting to modify it so that it already starts off opened when the page loads.
HTML Snippet:
<div class="row" id="cp-toggle">
<div class="col-sm-12">
<div class="col-sm-2 col-sm-offset-5 toggle-button">
<a><span class="glyphicon glyphicon-chevron-up"></span></a>
</div>
<div class="col-sm-12" style="height: calc(100% - 25px);max-height: 250px;background-color:#d3d3d3;">
<div style="height: 100%;max-height: 250px;">
<div style="height: 25px;padding-top: 4px;">
<div style="float: left;padding-right: 9px;">
<span> Posts: </span> <span id="posts_count"></span>
</div>
</div>
<div style="overflow-y: scroll;height: 100%;max-height: 225px;">
<table id="result_table" class="table" style="display:table;" >
<thead class="result_thead"></thead>
<tbody class="result_tbody"></tbody>
</table>
</div>
</div>
</div>
</div>
</div>
Javascript:
var control_panel= (function(){
var container = $('#cp-toggle div:first-child');
var btn = $('#cp-toggle div:first-child').find("div").first();
var table_panel = $('#cp-toggle div:first-child div:nth-child(2)').first();
var open_css = "glyphicon-chevron-up";
var close_css = "glyphicon-chevron-down";
var open = function(){
container.find("span").first().switchClass(open_css, close_css);
var h = table_panel.height() + 25;
container.css("top", "calc(100% - "+ h +"px)");
};
var close = function(){
container.find("span").first().switchClass(close_css, open_css);
container.css("top", "calc(100% - 25px)")
};
var isOpen = function(){
return _.contains(container.find("span").first().attr('class').split(/\s+/), close_css);
};
var toggle = function(){
if (isOpen()){
close();
} else {
open();
}
};
btn.on('click', toggle);
return {
open: open,
close: close,
toggle: toggle,
isOpen : isOpen
};
}());
CSS Snippet:
#cp-toggle > div:first-child {
top: calc(100% - 25px);
position: fixed;
z-index: 25;
}
.toggle-button {
height: 25px;
padding-top: 3px;
background-color: #d3d3d3;
border-top-right-radius: 7px;
border-top-left-radius: 7px;
text-align: center;
cursor: pointer;
}
#cp-toggle a {
color: #111;
}
#cp-toggle a:hover {
color: #777;
}
.tab-pane { height: 100%;}
#email-body { height: calc(100% - 80px); }
.body-view { height: 100%; overflow-y: scroll; }
.marked {
color: #ffd700;
}
.marked:hover {
color: #ffd700;
}
I have tried modifying the javascript to call control_panel.open(); at the end. I have tried altering the toggle to start with open();. None of these seem to have any effect on the code. I am not sure if I am looking in the correct area or if I am doing something incorrectly.
Try this (you tried something similar in a comment, but I'll explain in a minute...):
<script>
window.addEventListener('load', function() {
control_panel.open();
});
</script>
The problem with your original attempt...
<script>onLoad=control_panel.open();</script>
... was that it was setting a variable called 'onLoad' with the value of whatever was returned by running the function control_panel.open(), which it did immediately instead of waiting until the page was loaded. Instead, in my example I'm setting an 'onload' listener on the window, so that when the window finishes loading, then it'll run the control_panel.open() function that it is now aware of.