Check whether a div or one of its children were clicked - javascript

I have a div as follows
<div class="parent">
<!--several child divs now-->
</div>
Now, I have registered a click handler on body using AngularJS as follows:
HTML:
<body ng-click="registerClick($event)">
</body>
Controller:
$scope.registerClick(e) {
//Here check if the parent div or one of its children were clicked
}
How, can use $event in my handler to determine if the div with class 'parent' or one of its children were clicked?

Change it to this:
$scope.registerClick(e) {
if (e.target.classList.contains('parent')){
// The .parent div is clicked
} else if (e.target.parentNode.classList.contains('parent')){
// Some child of the .parent div is clicked
} else {
var elem = e.target;
while(elem.tagName != 'body' || !elem.classList.contains('parent')){
elem = elem.parentNode;
}
if (elem.classList.contains('parent')){
console.log('DIV .parent')
} else {
console.log('Body tag reached. No .parent element found');
}
}
}
e.target is the clicked element. Use it to determine which element was clicked. This is a clean JavaScript solution. You wont even need the $scope.registerClick(e) { part if can attach the event like so:
someDiv.onclick = function(){/* Same code as above. */}
if you use the latter approach, 'this' points to the div, so you can that the validations a little bit.

You can do something like
var app = angular.module('my-app', [], function() {})
app.controller('AppController', function($scope) {
$scope.registerClick = function($event) {
//if has jQuery
if ($($event.target).closest('.parent').length) {
console.log('clicked parent');
$scope.jQuery = true;
} else {
$scope.jQuery = false;
}
var isParent = false;
if (angular.isFunction($event.target.closest)) {
isParent = !!$event.target.closest('.parent');
} else {
var tmp = $event.target;
do {
isParent = tmp.classList.contains('parent');
tmp = tmp.parentNode;
} while (tmp && tmp.classList && !isParent);
}
$scope.native = isParent;
};
})
.parent {
border: 1px solid grey;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="my-app">
<div ng-controller="AppController" ng-click="registerClick($event)">
<div>outside</div>
<div class="parent">
parent
<div>div</div>
<div>div</div>
</div>
<div>
jQuery: {{jQuery}}
</div>
<div>
native: {{native}}
</div>
</div>
</div>

Related

JavaScript and HTML to show or hide an element

I think this is very easy, but I just can't seem to twig it at the moment. I want to use a JavaScript function to set the visibility of an HTML tag.
I realise the below is wrong as hidden doesn't take a boolean. I'm just struggling to click what the easiest way to do it is?
So I have some script like this:
<script>
function evaluateBoolean() {
if (location.hostname.indexOf("someval" > 0) {
return true;
} else {
return false;
}
}
</script>
And I wanted to use it something like this:
<div hidden="evaluateBoolean()">
this will be shown or displayed depending on the JavaScript boolean
</div>
I would recommend doing it by altering the display style in the JavaScript code.
const el = document.getElementById('container');
const btn = document.getElementById('btn');
btn.addEventListener('click', function handleClick() {
if (el.style.display === 'none') {
el.style.display = 'block';
btn.textContent = 'Hide element';
} else {
el.style.display = 'none';
btn.textContent = 'Show element';
}
});
You have a div with id: myDIV
<div id="myDIV" class="card-header">
Hello World
</div>
You then call this Javascript function to show the element:
function showDiv() {
document.getElementById('myDIV').style.display = "block";
}
and this one to hide it:
function hideDiv() {
document.getElementById('myDIV').style.display = "none";
}
Note, that you can hide a div by:
<div id="myDIV" class="card-header" style="display:none">
Hello World
</div>
And then call the function to show it.
You trigger must be outside of the element which you hide. because if hided you cant even clicked. The js function classList toggle would be good.
function evaluateBoolean() {
const d = document.querySelector('.w div');
d.classList.toggle('hide');
}
.w {
height: 40px;
background: yellow;
}
.hide {
display: none;
}
<div class="w" onclick="evaluateBoolean()">
<div> this will be shown or displayed depending on the javascript boolean </div>
</div>
You can't explicitly run js in your html, if you aren't using any framework like angular or react, where property binding is allowed.
For achieving your intentions with js you can use this approch:
Add to your div an id:
<div id="myDiv"> Toggled div </div>
In your js script modify your function evaluateBoleean() to show/hide the element:
function evaluateBoolean() {
const div = document.querySelector("#myDiv");
if (location.hostname.indexOf("someval" > 0) {
div.hidden = true;
} else {
div.hidden = false;
}
There's a very easy option:-->
having a blank text
firsly replace the html code with this:-->
<div hidden="evaluateBoolean()" id="ThingToBeHidden"> this will be shown or displayed depending on the javascript boolean </div>
and put js code:-->
document.getElementById("ThingToBeHidden").innerHTML = "";
So you have assigned the div to have it's special id which none other element has.
So now the js code selects the div with that id and then sets the context of it to blank.
If you want the text to appear again, the js code is:-->
document.getElementById("ThingToBeHidden").innerHTML = "this will be shown or displayed depending on the javascript boolean";
You can hide an element in several ways (using jQuery):
const o = $(cssSelectorForElementToStyle);
$(o).hide();
$(o).toggle();
$(o).css('display', 'none');
$(o).addClass('css_class_for_hiding_stuff');
Here using vanilla JavaScript:
const o = document.querySelector(cssSelectorForElementToStyle);
o.style.display = 'none';
o.classList.add('css_class_for_hiding_stuff');
But your question doesn't point out exactly when you are going to make this check. So let's assume you are going to check the boolean value once when the page is loaded and hide or show a given element according to that value:
$(document).ready(
() => {
if (evaluateBoolean() === true) {
// do nothing in this case
} else {
$('#elementWithThisId').css('display', 'none');
}
}
);
Without jQuery:
document.addEventListener("DOMContentLoaded", function() {
if (evaluateBoolean() === true) {
// do nothing in this case
} else {
document.querySelector('#elementWithThisId').style.display = 'none';
}
});

How to display hidden div after mouse out or hover

Hi guys can someone help me here I want to make a hidden div being displayed after I trigger the event to display and I remove the mouse on that div here is my code
<div id='MainContainer'>
<div id='btn-img' onmouseover='DisplayHidden()'>content 1</div>
<div id='container2'>content 2</div>
</div>
function DisplayHidden()
{
$('#container2').show();
}
is it possible?
I preferred this way because if you want to add more attributes and comparisons parameters you may add it easily and attribute binding is dynamical.
$(document).ready(function(){
$("#MainContainer > div").on("click",function(e){
if(false === !!$(this).attr('data-click')){
$(this).attr("data-click", true);
alert('No');
}else{
alert('Clicking on same div');
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='MainContainer'>
<div id='container1'>content 1</div>
<div id='container2'>content 2</div>
</div>
Here is what you could do, using pure javascript.
Bind the click event on the container element and use event.target attribute to check the previous click element and take appropriate action.
Event.target documentation on MDN
document.addEventListener("DOMContentLoaded", function() {
var prevElement = null;
document.querySelector("#MainContainer").addEventListener("click", function(event) {
if (prevElement === event.target) {
console.log("Yes")
} else {
console.log("No");
}
prevElement = event.target;
});
});
<div id='MainContainer'>
<div id='container1'>content 1</div>
<div id='container2'>content 2</div>
</div>
var lastClick = null;
$('div#MainContainer div').click(function() {
var clickedId = $(this).attr('id');
if (clickedId == lastClick) {
alert('Clicked the same div');
}
else {
alert('Clicked on a different div');
lastClick = clickedId;
}
});
Here a simple solution with plain javascript:
var g_lastTarget = null
var g_handleClick = function(e) {
var target = e.currentTarget
if (g_lastTarget === target) {
alert('You clicked the container twice. Container ID = ' + target.id)
}
g_lastTarget = target
}
var c1 = document.getElementById('container1')
var c2 = document.getElementById('container2')
c1.addEventListener('click', g_handleClick)
c2.addEventListener('click', g_handleClick)
Create a common class & use querySelectorAll to select the desirable elements.
Then loop through it attach eventListener method to it.Create a variable to store the id of the currently clicked element. On subsequent click check if the variable value and id is same. If it is same then throw an alert.
var getElements = document.querySelectorAll(".elem");
var clickedElem = "";
getElements.forEach(function(item) {
item.addEventListener('click', function() {
if (item.id === clickedElem) {
alert('Clicking on same div')
} else {
clickedElem = item.id
}
})
})
<div id='MainContainer'>
<div id='container1' class="elem">content 1</div>
<div id='container2' class="elem">content 2</div>
</div>

Javascript -- how to click anywhere on page to hide opened div

I have a javascript that opens up a hidden div:
<script>
function dropdown()
{ document.getElementById("login_dropdown").style.display="block"; }
</script>
The html is:
<div onclick="dropdown()">
<div id="login_dropdown">STUFF</div>
</div>
The CSS is:
<style>
#login_dropdown {
width: 150px;
display:none;
}</style>
Using javascript alone, how can I hide this div when I click anywhere else on the page, excluding the opened DIV itself.
Something like this with vanilljs
document.addEventListener('click', function(event){
const yourContainer = document.querySelector('....');
if(!yourContainer.contains(event.target)) {
//hide things classes.. yourContainer.classList.add('hidden');
}
});
You could do this
var elem = document.getElementById("login_dropdown");
(document.body || document.documentElement).addEventListener('click', function (event) {
// If the element on which the click event occurs is not the dropdown, then hide it
if (event.target !== elem)
elem.style.display="none";
}, false);
function closest(e, t){
return !e? false : e === t ? true : closest(e.parentNode, t);
}
container = document.getElementById("popup");
open = document.getElementById("open");
open.addEventListener("click", function(e) {
container.style.display = "block";
open.disabled = true;
e.stopPropagation();
});
document.body.addEventListener("click", function(e) {
if (!closest(e.target, container)) {
container.style.display = "none";
open.disabled = false;
}
});
#popup {
border: 1px solid #ccc;
padding: 5px;
display: none;
width: 200px;
}
<div id="container">
<button id="open">open</button>
<div id="popup">PopUp</div>
</div>
Something like this:
$("document").mouseup(function(e)
{
var subject = $("#login_dropdown");
if(e.target.id != subject.attr('id'))
{
subject.css('display', 'none');
}
});
works like this. When you click anywhere on the page, the handler fires and compares the ID of the open tab vs the id of the document (which there is none) - so it closes the tab. However, if you click the tab, the handler fires, checks the ID, sees the target is the same and fails the test (thus not closing the tab).

Issues with using classList to hide and show elements

I need to implement a feature where a div shows up when another div is clicked and should hide if the div is clicked again.
Here is the fiddle with a small portion of the code : https://jsfiddle.net/6dgL6zqb/1/
var portfolio = document.getElementById('portfolio');
EventUtil.addHandler(portfolio, 'click', function(event) {
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
switch(target.id) {
case 'kk':
console.log('kk clicked');
var idName = target.id + 'Details',
doc = document,
currentProject = doc.getElementById(idName),
otherProjects = doc.getElementsByClassName('projectDetails');
console.log(currentProject);
for (var i = otherProjects.length - 1; i >= 0; i--) {
var projectClassList = otherProjects.item(i).classList;
if (projectClassList.contains('showMe')) {
projectClassList.remove('showMe');
projectClassList.add('hideMe');
}
};
var currentProjectClassList = currentProject.classList;
console.log(currentProjectClassList);
if (!currentProjectClassList.contains('showMe')) {
currentProjectClassList.remove('hideMe');
currentProjectClassList.add('showMe');
} else {
currentProjectClassList.remove('showMe');
currentProjectClassList.add('hideMe');
}
break;
}
});
I am using an EventUtil handler to handle events, along-with event delegation.
So, when I click on Section 1 with the id 'kk', another div with id 'kkDetails' displays. But, I expect the div with id 'kkDetails' to disappear when I click on the div with id 'kk'. How can I get that to happen?
As far as I can see, the currentProjectClassList object is not updating as I expect. Although, I don't understand why.
PS: I am new at programming, so please bear with any ignorance.
There problem that you are having is this section:
otherProjects = doc.getElementsByClassName('projectDetails');
for (var i = otherProjects.length - 1; i >= 0; i--) {
var projectClassList = otherProjects.item(i).classList;
if (projectClassList.contains('showMe')) {
projectClassList.remove('showMe');
projectClassList.add('hideMe');
}
};
You are actually hiding your element and then later showing it again, as an example modify this section to be something like:
otherProjects = doc.getElementsByClassName('projectDetails');
for (var i = otherProjects.length - 1; i >= 0; i--) {
if(otherProjects.item(i).id !== idName){
var projectClassList = otherProjects.item(i).classList;
if (projectClassList.contains('showMe')) {
projectClassList.remove('showMe');
projectClassList.add('hideMe');
}
}
};
In this section you are swapping the visible state of your selected div:
if (!currentProjectClassList.contains('showMe')) {
currentProjectClassList.remove('hideMe');
currentProjectClassList.add('showMe');
} else {
currentProjectClassList.remove('showMe');
currentProjectClassList.add('hideMe');
}
however in the previous section of code because your selected element also has the class projectDetails it gets its showMe removed and hideMe added. So when it gets to section of code above this if(!currentProjectClassList.contains('showMe')) will always be true.
I would use a single class to toggle visibility. It is a lot more manageable. Also I would link click element with the toggled element via an attribute of some kind (instead of using a switch statement in javascript).
EventUtil.addHandler(portfolio, 'click', function(event) {
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
var divId = target.getAttribute('href');
if (divId) {
event.preventDefault();
Array
.from(document.querySelectorAll('.projectDetails:not(.hideMe)'))
.forEach(function(a) {
a.classList.add('hideMe')
});
document.querySelector(divId).classList.remove('hideMe')
}
});
// Cross-browser event handler
var EventUtil = {
addHandler: function(element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent("on" + type, handler);
} else {
element["on" + type] = handler;
}
},
getEvent: function(event) {
return event ? event : window.event;
},
getTarget: function(event) {
return event.target || event.srcElement;
},
preventDefault: function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
removeHandler: function(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) {
element.detachEvent("on" + type, handler);
} else {
element["on" + type] = null;
}
},
stopPropagation: function(event) {
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
};
var portfolio = document.getElementById('portfolio');
EventUtil.addHandler(portfolio, 'click', function(event) {
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
var divId = target.getAttribute('href');
if (divId) {
event.preventDefault();
Array
.from(document.querySelectorAll('.projectDetails:not(.hideMe)'))
.forEach(function(a) {
a.classList.add('hideMe')
});
document.querySelector(divId).classList.remove('hideMe')
}
});
.projectDetails {
display: block;
}
.projectDetails.hideMe {
display: none;
}
<body>
<div class="container">
<section id="portfolio">
<div class="row">
<div class="col-sm-4">
Section 1
</div>
<div class="col-sm-4">
Section 2
</div>
<div class="col-sm-4">
Section 3
</div>
</div>
<div class="row">
<div id="kkDetails" class="hideMe projectDetails">
<p>Text</p>
</div>
<div id="arthDetails" class="hideMe projectDetails">
<p>Text 2</p>
</div>
<div id="bobyPinzDetails" class="hideMe projectDetails">
<p>Text 3</p>
</div>
</div>
</section>
</body>

Removing attributes of an element on clicking outside with Vanilla JS

How can I remove an attribute of an element on click outside or on another div of same type? Here's my code:
HTML:
<div id="container">
<div data-something></div>
<div data-something></div>
</div>
JavaScript:
var elements = document.querySelectorAll("[data-something]");
Array.prototype.forEach.call(elements, function(element) {
// Adding
element.onclick = function() {
this.setAttribute("data-adding", "");
};
// Removing -- Example
element.onclickoutside = function() {
this.removeAttribute("data-adding");
};
});
I would probably use a click handler on the document, and then remove the attribute from any element that had it that wasn't in the bubbling path.
document.addEventListener("click", function(e) {
Array.prototype.forEach.call(document.querySelectorAll("*[data-adding][data-something]"), function(element) {
var node, found = false;
for (node = e.target; !found && node; node = node.parentNode) {
if (node === element) {
found = true;
}
}
if (!found) {
element.removeAttribute("data-adding");
}
});
}, false);
...or something along those lines.
Live Example:
document.addEventListener("click", function(e) {
Array.prototype.forEach.call(document.querySelectorAll("*[data-adding]"), function(element) {
var node, found = false;
for (node = e.target; !found && node; node = node.parentNode) {
if (node === element) {
found = true;
}
}
if (!found) {
element.removeAttribute("data-adding");
}
});
}, false);
*[data-adding] {
color: red;
}
<div data-adding data-something>One</div>
<div data-adding data-something>Two</div>
You can use Node.contains() inside a global click event handler to check if a click is outside an element, and handle the event appropriately:
box = document.getElementById('box');
lastEvent = document.getElementById('event');
box.addEventListener('click', function(event) {
// click inside box
// (do stuff here...)
lastEvent.textContent = 'Inside';
});
window.addEventListener('click', function(event) {
if (!box.contains(event.target)) {
// click outside box
// (do stuff here...)
lastEvent.textContent = 'Outside';
}
});
#box {
width: 200px;
height: 50px;
background-color: #ffaaaa;
}
<div id="box">Click inside or outside me</div>
<div>Last event: <span id="event">(none)</span>
</div>

Categories