displaying the ELEMENT NAME that triggered mouse event in javascript - javascript

I'm trying to get the alert box to display the element name (here is html) (without hard-coding obviously) that triggered the event onclick with ctrl pressed.
<!DOCTYPE html>
<html onclick="alertD(event)">
<head>
<title>
</title>
</head>
<body>
<!--<p>click anywhere on the page to display alert dialog</p>-->
<script type="text/javascript">
function alertD(event)
{
if (event.shiftKey)
{
alert(event);
}
else if(event.ctrlKey)
{
alert("html"); //-- this is where it would say something like alert(document.element)???
}
else
{
alert();
}
}

You can use the target property of the event to get the element. Then get the name of that element using tagName property of the element.
function alertD(event)
{
if (event.shiftKey)
{
alert(event);
}
else if(event.ctrlKey)
{
alert(event.target.tagName); // <-- tag name
}
else
{
alert();
}
}

Related

Can't create "a" element on clicking and subsequently classList.toggle() not working

I am making a to-do list application. You enter an item. It gets appended to the list. On clicking the item on the list, it gets crossed. Can't make the text clickable and thus can't add the classList.toggle() function to cross the item from the list.
I've tried to create an empty "li" element to which an "a" element is created inside it. (Note: all this happens when we add the item to the list). I thought, using the "a" element, I could hover over the text and thus make it clickable and connect it to the classList.toggle() function.
<html>
<head>
<style>
.done
{
text-decoration:line-through;
}
</style>
</head>
<body>
<input type="text" id="user_input">
<ul></ul>
<script>
var input = document.getElemenyById("user_input");
function addingNewList()
{
var li = document.createElement("li");
var tag = document.createElement("a");
tag.appendChild(document.createTextNode(input.value));
li.appendChild(tag);
ul.appendChild(li);
tag.onclick=tag.classList.toggle("done");
}
function input_length()
{
return input.value.length;
}
input.addEventListener("keypress",function(event)
{
if(input_length() >0 && event.which == 13)
{
addingNewList();
}
})
</script>
</body>
</html>
The expected output should be that, if the user add: "Do Laundry" to the list, It gets added to the list. On clicking "Do Laundry", there should be line through it, i.e it should be crossed. Currently, the items are getting added, but are not getting crossed. No error message is showing up either.
I have made it work very similar to the answer from Saurabh with the following:
<html>
<head>
<style>
.done
{
text-decoration:line-through;
}
</style>
</head>
<body>
<input type="text" id="user_input">
<ul id="list"></ul>
<script>
var input = document.getElementById("user_input");
function addingNewList()
{
var li = document.createElement("li");
var tag = document.createElement("a");
tag.appendChild(document.createTextNode(input.value));
var ul = document.getElementById("list");
li.appendChild(tag);
ul.appendChild(li);
tag.addEventListener("click",function()
{
toggleClass(this);
})
}
function toggleClass(e) {
e.classList.toggle("done");
}
function input_length()
{
return input.value.length;
}
input.addEventListener("keypress",function(event)
{
if(input_length() >0 && event.which == 13)
{
addingNewList();
}
})
</script>
</body>
</html>
In the above example in your question you had spelt getElementById wrong in one place and you did not define ul. I also added the toggle function to add to the click event you need to create.
While adding new li inside ul you need to bind addEventListener in new element, then on element click you need to add done class in to that element.
Try this:
<html>
<head>
<style>
.done {
text-decoration:line-through;
}
</style>
</head>
<body>
<input type="text" id="user_input">
<ul id="list"></ul>
<script>
var input = document.getElementById("user_input");
function addingNewList() {
var li = document.createElement("li");
var tag = document.createElement("a");
tag.appendChild(document.createTextNode(input.value));
li.appendChild(tag);
li.addEventListener("click", function (event) {
event.target.classList.add('done');
})
var ul = document.getElementById("list");
ul.appendChild(li);
// tag.onclick=tag.classList.toggle("done");
}
function input_length() {
return input.value.length;
}
input.addEventListener("keypress", function (event) {
if (input_length() > 0 && event.which == 13) {
addingNewList();
}
})
</script>
</body>
</html>

Excluding an area of the DOM on addEventListener

I would like to have an event to trigger when clicking on a box, and a different one when clicking on anyplace less that box. Here's the code:
<body>
<p id="demo"></p>
<script>
document.querySelector("#demo").addEventListener("mouseover", funcion);
document.querySelector("#demo").addEventListener("click", funcion2);
document.querySelector("#demo").addEventListener("mouseout", funcion3);
document.body.querySelector("#demo").addEventListener("click", funcion4, false);
function funcion() {
document.getElementById("demo").innerHTML += "Mouse encima!<br>";
}
function funcion2() {
document.getElementById("demo").innerHTML += "Click dentro<br>";
}
function funcion3() {
document.getElementById("demo").innerHTML += "Mouse fuera!<br>";
}
function funcion4() {
document.getElementById("demo").innerHTML += "Click fuera<br>";
}
document.querySelector("#demo").addEventListener("click", function(e) {e.stopPropagation();}, true);
</script>
</body>
"Tecnically" that should solve it, though i am getting the reverse solution I am looking for, it triggers both events (in & out) when clicking over the box, and none of the events when clicking out of it. I'm out of ideas.
You can add an event listener to the document itself and detect the real target of the event from there.
var box = document.getElementById('demo');
document.addEventListener('click', function(e) {
if (e.target === box) {
console.log('Clicking on the box');
} else {
console.log('Clicking outside of the box');
}
});
<p id="demo">This is the box!</p>

How to recognize that a file-input has opened a window

I have a function that runs when the user presses the esc button:
$(document).on('keyup', function (e) {
if (e.keyCode == 27) {
foo();
}
});
I have a form with a file field.
<input type="file" />
When you click it, it opens a file-manager dialog, which can be closed with the esc as well. In that case, I want to avoid running the foo function. Is there a way to recognize it with javascript?
Here is some code that can do what you want (a complete test-page):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>test-page</title>
<script type="text/javascript">
//<!--
var ignr=false;
function func(e)
{ if(!ignr)
{ //add any key-specific tests here
foo();
}
ignr = false;
return;
}
function foo()
{
return;
}
function func2(e)
{ //Could add a condition to do/not-do the next line, depending on the key...
ignr = true;
return;
}
// -->
</script>
</head>
<body onkeyup="func(event);">
<input type="file" onkeyup="func2(event);" />
</body>
</html>
The trick is to assign a different function to the input tag. This won't prevent the other function from being called, but the herein-specified func2() is called first, giving you the chance to set a flag-variable that can control what gets done in the "main" onkeyup function. Note while I didn't specify any tests for the Escape key, you can certainly add them, and even completely control which keys you want to allow "through" func2() to call foo() inside the main onkeyup function. At the moment, no keys pressed during the file-input will have any chance of calling foo().

Detect click outside element (vanilla JavaScript)

I have searched for a good solution everywhere, yet I can't find one which does not use jQuery.
Is there a cross-browser, normal way (without weird hacks or easy to break code), to detect a click outside of an element (which may or may not have children)?
Add an event listener to document and use Node.contains() to find whether the target of the event (which is the inner-most clicked element) is inside your specified element. It works even in IE5
const specifiedElement = document.getElementById('a')
// I'm using "click" but it works with any event
document.addEventListener('click', event => {
const isClickInside = specifiedElement.contains(event.target)
if (!isClickInside) {
// The click was OUTSIDE the specifiedElement, do something
}
})
var specifiedElement = document.getElementById('a');
//I'm using "click" but it works with any event
document.addEventListener('click', function(event) {
var isClickInside = specifiedElement.contains(event.target);
if (isClickInside) {
alert('You clicked inside A')
} else {
alert('You clicked outside A')
}
});
div {
margin: auto;
padding: 1em;
max-width: 6em;
background: rgba(0, 0, 0, .2);
text-align: center;
}
Is the click inside A or outside?
<div id="a">A
<div id="b">B
<div id="c">C</div>
</div>
</div>
You need to handle the click event on document level. In the event object, you have a target property, the inner-most DOM element that was clicked. With this you check itself and walk up its parents until the document element, if one of them is your watched element.
See the example on jsFiddle
document.addEventListener("click", function (e) {
var level = 0;
for (var element = e.target; element; element = element.parentNode) {
if (element.id === 'x') {
document.getElementById("out").innerHTML = (level ? "inner " : "") + "x clicked";
return;
}
level++;
}
document.getElementById("out").innerHTML = "not x clicked";
});
As always, this isn't cross-bad-browser compatible because of addEventListener/attachEvent, but it works like this.
A child is clicked, when not event.target, but one of it's parents is the watched element (i'm simply counting level for this). You may also have a boolean var, if the element is found or not, to not return the handler from inside the for clause. My example is limiting to that the handler only finishes, when nothing matches.
Adding cross-browser compatability, I'm usually doing it like this:
var addEvent = function (element, eventName, fn, useCapture) {
if (element.addEventListener) {
element.addEventListener(eventName, fn, useCapture);
}
else if (element.attachEvent) {
element.attachEvent(eventName, function (e) {
fn.apply(element, arguments);
}, useCapture);
}
};
This is cross-browser compatible code for attaching an event listener/handler, inclusive rewriting this in IE, to be the element, as like jQuery does for its event handlers. There are plenty of arguments to have some bits of jQuery in mind ;)
How about this:
jsBin demo
document.onclick = function(event){
var hasParent = false;
for(var node = event.target; node != document.body; node = node.parentNode)
{
if(node.id == 'div1'){
hasParent = true;
break;
}
}
if(hasParent)
alert('inside');
else
alert('outside');
}
you can use composePath() to check if the click happened outside or inside of a target div that may or may not have children:
const targetDiv = document.querySelector('#targetDiv')
document.addEventListener('click', (e) => {
const isClickedInsideDiv = e.composedPath().includes(targetDiv)
if (isClickedInsideDiv) {
console.log('clicked inside of div')
} else {
console.log('clicked outside of div')
}
})
I did a lot of research on it to find a better method. JavaScript method .contains go recursively in DOM to check whether it contains target or not. I used it in one of react project but when react DOM changes on set state, .contains method does not work. SO i came up with this solution
//Basic Html snippet
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="mydiv">
<h2>
click outside this div to test
</h2>
Check click outside
</div>
</body>
</html>
//Implementation in Vanilla javaScript
const node = document.getElementById('mydiv')
//minor css to make div more obvious
node.style.width = '300px'
node.style.height = '100px'
node.style.background = 'red'
let isCursorInside = false
//Attach mouseover event listener and update in variable
node.addEventListener('mouseover', function() {
isCursorInside = true
console.log('cursor inside')
})
/Attach mouseout event listener and update in variable
node.addEventListener('mouseout', function() {
isCursorInside = false
console.log('cursor outside')
})
document.addEventListener('click', function() {
//And if isCursorInside = false it means cursor is outside
if(!isCursorInside) {
alert('Outside div click detected')
}
})
WORKING DEMO jsfiddle
using the js Element.closest() method:
let popup = document.querySelector('.parent-element')
popup.addEventListener('click', (e) => {
if (!e.target.closest('.child-element')) {
// clicked outside
}
});
To hide element by click outside of it I usually apply such simple code:
var bodyTag = document.getElementsByTagName('body');
var element = document.getElementById('element');
function clickedOrNot(e) {
if (e.target !== element) {
// action in the case of click outside
bodyTag[0].removeEventListener('click', clickedOrNot, true);
}
}
bodyTag[0].addEventListener('click', clickedOrNot, true);
Another very simple and quick approach to this problem is to map the array of path into the event object returned by the listener. If the id or class name of your element matches one of those in the array, the click is inside your element.
(This solution can be useful if you don't want to get the element directly (e.g: document.getElementById('...'), for example in a reactjs/nextjs app, in ssr..).
Here is an example:
document.addEventListener('click', e => {
let clickedOutside = true;
e.path.forEach(item => {
if (!clickedOutside)
return;
if (item.className === 'your-element-class')
clickedOutside = false;
});
if (clickedOutside)
// Make an action if it's clicked outside..
});
I hope this answer will help you !
(Let me know if my solution is not a good solution or if you see something to improve.)

Detecting change in hidden form field

Im writing a test code to do a counter that stores the value in a hidden form field. Whenever this counter is incremented with a button click, the counter value is stored in the hidden field. I have no problem with this portion.
However, im having problem to display an alert whenever the hidden field is being changed. Pls see my code below and tell me where i have gone wrong. Thank You.
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>
<script type="text/javascript">
function startRolling() {
var storage=document.getElementById('store').value;
var tonum;
if(parseInt(storage)==0)
{
tonum=1;
}
else {
tonum=parseInt(storage,10);
}
tonum=tonum+1;
document.getElementById('store').value=tonum;
storage=document.getElementById('store').value;
alert(storage)
}
$(document).ready(function() {
var content = $('#store').val();
$('#store').change(function() {
if ($('#store').val() != content) {
alert('Content has been changed')
}
});
});
</script>
</head>
<body>
<input type="button" id="trigger" value="Start" onclick="startRolling()"/>
<input type="text" id="cnt" readonly="readonly"/>
<input type="hidden" id="store" value="0"/>
</body>
What if you just fire the event without trying to detect the change?
function startRolling() {
var storage=document.getElementById('store').value;
var tonum;
if(parseInt(storage)==0)
{
tonum=1;
}
else {
tonum=parseInt(storage,10);
}
tonum=tonum+1;
document.getElementById('store').value=tonum;
if(storage != tonum) {
alertChange();
}
//storage=document.getElementById('store').value;
//alert(storage)
}
function alertChange() {
alert('Content has been changed');
}
You could also look at the trigger event in jquery: http://api.jquery.com/trigger/.
Try this
function startRolling() {
var storage=document.getElementById('store').value;
var tonum;
if(parseInt(storage)==0)
{
tonum=1;
}
else {
tonum=parseInt(storage,10);
}
tonum=tonum+1;
document.getElementById('store').value=tonum;
//storage=document.getElementById('store').value;
//alert(storage)
}
$(document).ready(function() {
//var content = $('#store').val();
$('#store').change(function() {
//if ($('#store').val() != content) {
alert('Content has been changed')
}
});
Why don't you change the first function to jquery?
From the description of the change-event:
The change event occurs when a control loses the input focus and its value has been modified since gaining focus.
Hidden inputs cannot lose focus(because they never have focus), so change will not fire there anyway.
See Any even to detect when the "Class" attribute is changed for a control for a solution.
Rather than using a change event, I've used a loop event that checks every second.
var content="";
function startRolling() {
var storage=document.getElementById('store').value;
var tonum;
if(parseInt(storage)==0)
{
tonum=1;
}
else {
tonum=parseInt(storage,10);
}
tonum=tonum+1;
document.getElementById('store').value=tonum;
storage=document.getElementById('store').value;
content=storage;
alert(storage)
}
function checkifchanged(){
if ($('#store').val() != content) {
alert('Content has been changed');
}
else{
content = $('#store').val();
}
setTimeout('checkifchanged()',1000);
}
$(document).ready(function() {
content = $('#store').val();
checkifchanged();
});
var content = $('#store').val();
You are storing the changed value and comparing with the same value,
this if statement doesn't execute
if ($('#store').val() != content)
don't store the value just call change event directly.
$(document).ready(function() {
$('#store').change(function() {
alert('Content has been changed')
});

Categories