How to select 'this' onclick? - javascript

By triggering an onClick event I would like to select the same element the onClick event is attached to, to add a class to that same element. What I tried is the following:
<div class="class1" onClick="TestFunction();">Click</div>
<script>
function TestFunction() {
$(this).addClass('active');
}
</script>
After clicking the div, the class "active" should be added to the same element, resulting in...
<div class="class1 active" onClick="TestFunction();">Click</div>
However this doesn't work. I am wondering whether the this selector works differently in this case.
The structure of the div element should stay the same and also the function should stay in the same place as it is on the onClick attribute.

The reason is this refers to the global Window object inside the function.
You have to pass this to the function so that you can refer that inside the function:
.active{
color:green;
font-size: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="class1" onClick="TestFunction(this);">Click</div>
<script>
function TestFunction(el) {
console.log(this.constructor.name) //Window
$(el).addClass('active');
}
</script>
Though it is better to avoid inline event handler:
$('.class1').click(function(){
$(this).addClass('active');
});
.active{
color:green;
font-size: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="class1">Click</div>

When using an inline handler the function invoked runs under the scope of the window element, not the element which raised the event. To work around that you can pass this as an argument:
<div class="class1" onClick="TestFunction(this);">Click</div>
function TestFunction(el) {
el.addClass('active');
}
However this is not good practice. Inline event attributes are outdated and now considered bad practice. The better way to achieve this is to attach unobtrusive event handlers. In plain JS it would look like this:
<div class="class1">Click</div>
document.querySelectorAll('.class1').forEach(el => {
el.addEventListener('click', function() {
this.classList.add('active');
});
});
In jQuery it would look like this:
<div class="class1">Click</div>
jQuery($ => {
$('.class1').on('click', function() {
$(this).addClass('active');
});
});

Related

stopPropagation & preventDefault are not working, parent click is still firing

In my code, I have added onclick on parent div and want to perform other action on inner div, but clicking on inner div also triggering parent click.
how to stop that?
$(document).on('click', '.child', function(e) {
e.preventDefault();
e.stopPropagation();
console.log('child');
});
function parentfun(sender) {
console.log('parent');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent" onclick="parentfun(this)">
parent
<div class="child">child</div>
</div>
Above divs are generated on run time on some other event.
Clicking on child, also trigger parent's click. preventDefault & stopPropagation are not working.
FYI: my question is different than How do I prevent a parent's onclick event from firing when a child anchor is clicked?
What you are actually doing here is binding the click-event to the document, not the child-element. So the event has already bubbled up all the way to the document, it's too late to try to stop the bubbling with stopPropagation.
See here when I change the click-handler to the child instead:
$(".child").on('click', function(e) {
e.preventDefault();
e.stopPropagation();
console.log('child');
});
function parentfun(sender) {
console.log('parent');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent" onclick="parentfun(this)">
parent
<div class="child">child</div>
</div>
Edit
As the question changed a bit, here is what you can do (for example) if the elements are created dynamically:
$(document).on('click', '.parent, .child', function(e) {
e.stopPropagation();
if ($(this).is(".child")) {
console.log('child');
} else {
console.log('parent');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
parent
<div class="child">child</div>
</div>
Using plain vanilla JS it works as expected:
function logEventTarget(e) {
e.stopPropagation();
console.log(e.target.id);
}
parentDiv.addEventListener('click', logEventTarget)
childDiv.addEventListener('click', logEventTarget)
<div id="parentDiv">
parent
<div id="childDiv">child</div>
</div>
Using an inline event handler won't pass the event to the handler function:
function logEventTarget(e) {
e.stopPropagation();
console.log(e.target.id);
}
childDiv.addEventListener('click', logEventTarget)
<div id="parentDiv" onclick="logEventTarget()">
parent
<div id="childDiv">child</div>
</div>
One of the many reasons you shouldn't use inline event handlers at all. Note that e.stopPropagation() still works for the childDiv.
You can notice that when clicking the chlid element the parent triggers first (that is why parent prints first then child ) because of event capturing which precedes event bubbling. In-order to stop the event capturing phase from parent you can stop propagating that event and then only child event will trigger.
$(document).on('click', '.child', function(e) {
//e.preventDefault();
e.stopPropagation();
console.log('child');
});
$(document).on('click', '.parent', parentfun);
function parentfun(e) {
e.stopPropagation();
console.log('parent');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
parent
<div class="child">child</div>
</div>
You can also resolve this problem by editing little bit in Your html code
<div class="parent" id="parent-div">
<!-- Just adding parent div text inside span tag -->
<span>parent</span>
<div class="child">child</div>
</div>
now go to jquery code
$('.parent span').on('click',function(){
//only print child text u can do more
alert($('.child').text());
//Change color of child
$('.child').css('color','red');
});

Event delegation in jQuery plugin

How to get selector string from jQuery plugin initialization, for event delegation use.
Here is simple case:
(function($){
$.fn.pluginTest = function(){
$(document).on("click", this, function(e){
// action here
});
}
}(jQuery));
Above code will not work since .on selector type need to be string. So the question is how to get the selector in plugin init.
$(".box").pluginTest()
How to get .box for example. I have been searching this and some suggested to use .selector but now it's deprecated and removed.
You can add the event handler to the target selector by using .selector.
JS CODE:
$(document).on("click",this.selector, function(e) {
alert('You clicked me!!!');
});
Live Demo # JSFiddle
In above example you will not get any alert when you click on .bigBox & you will get alert only on .box since the event handler is bound to the target element by its selector.
There are literally hundreds of pages devoted to extending jQuery. You haven't explain why the following won't work for your plugin:
(function($){
$.fn.pluginTest = function(){
this.on("click", this, function(e){
// action here
});
return this;
}
}(jQuery));
For example:
(function($){
$.fn.pluginTest = function(){
this.on("click", this, function(e){
$(this).toggleClass('red');
});
return this;
}
}(jQuery));
$('.box').pluginTest();
.red { background-color: red; }
.box { cursor: pointer; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box">Box 1</div>
<div class="box">Box 2</div>
<div class="box">Box 3</div>

Listen event from Shadow Dom

How do I listen a mouseover event from shadow DOM. I did try as snipcode below but nothing happen. The template instance is generated after button Add is clicked and I register mouseover event for it and hopping this event is fired when mouseover.
Thank a lot
HTML
<body>
<h1 class="text-center">Test import Node</h1>
<div class="container-fluid" style=" background-color: #FAFAFA"></div>
<div class="col-md-12" id = 'root'>
<button type="button" class="btn btn-default go" id='_add'><i class="fa fa-pencil-square-o"></i> Add</button>
<div id = 'textbox' style="height: 200px; width: 400px; font-size: 18px"></div>
</div>
<template id = 'area'>
<div style="height : 400px; width: 300px ; background-color: red"></div>
</template>
</body>
Javascript
$(document).ready(function() {
var button = document.querySelector('#_add');
button.addEventListener('click', function(){
check();
}, false);
});
function check(){
// document.querySelector('#textbox').innerHTML = "Ukie";
var content = document.querySelector('#area').content;
content.addEventListener('mouseover', function(){
display();
}, false);
var root = document.querySelector('#root');
root.appendChild(document.importNode(content, true));
}
function display(){
document.querySelector('#textbox').innerHTML = "Here";
}
As per addEventListener docs:
The event target may be an Element in a document, the Document itself, a Window, or any other object that supports events (such as XMLHttpRequest).
Therefore element must exist in the DOM, when you call addEventListener on it.
As a workaround, you can use event delegation using jquery on method to achieve the same. Here is a working jsfiddle by tweaking your sample a bit.
$('#root').on('mouseover', '.dyn', function(){
display();
});
Here bound element will be parent of template content(about which you are sure that it will exist while binding event) and you'll pass selector of your content html to .on method as argument. Thus whenever event occurs on child(in this case your template content) it will bubble up to parent and callback will be triggered.
You can use on function with jQuery. With on function you can "bind" events on element which not created in the DOM when the code was executed.
Read this: http://api.jquery.com/on/

JQuery event handler not firing after changing class

I'm trying to have the span, on click, toggle its classes between .btn-warning and .btn-primary. However, my code only works for the first click. Every click thereafter doesn't work.
JavaScript
$(document).ready(function(){
$('.btn-warning').on('click',function(){
$(this).removeClass('btn-warning').addClass('btn-primary');
});
$('.btn-primary').on('click',function(){
$(this).removeClass('btn-primary').addClass('btn-warning');
});
});
HTML
<span class="btn btn-warning" >Click me</span>
Changing the class does not magically add the events that were previously added. You either need to unbind/bind the events once again, or use a generic onclick handler that knows how to handle it, or use event delegation.
All that code could be reduced to:
$(".btn").on("click", function() {
$(this).toggleClass('btn-warning').toggleClass('btn-primary');
});
.btn-primary { background-color: blue; }
.btn-warning { background-color: yellow; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<span class="btn btn-warning" >Click me</span>
You need to use event delegation method because you're binding event to dynamically added class element:
$(document).ready(function(){
$(document).on('click','.btn-warning',function(){
$(this).removeClass('btn-warning').addClass('btn-primary');
});
$(document).on('click','.btn-primary',function(){
$(this).removeClass('btn-primary').addClass('btn-warning');
});
});
Simply you may do like this:
$(document).on("click",".btn", function() {
$(this).toggleClass('btn-warning btn-primary');
});

How to onclick outside an input element which is inside a div?

It maybe easy but i can't think anything to find the way when i click outside the textbox to alert something in javascript BUT when i click inside the text nothing to happen.The input text is inside the div element.
So,let's assume that my html is like bellow:
<div id="myone" onclick="javascript: myfunc();">
<input type="text" id="myInput"></input>
</div>
function myfunc()
{
alert('ok');
}
How to change that?
Thank you a lot!
Do this:
var div = document.getElementById('myone');
var funct = function(){
var input = div.querySelector("#myInput");
return false;
};
div.onclick = funct;
You shoud use this condition. e.target !== this
It is often useful to compare event.target to this in order to determine if the event is being handled due to event bubbling. This property is very useful in event delegation, when events bubble.
Use it inside your click function like this and see it in action:
$('.divover').on('click', function(e) {
if (e.target !== this) return;
thefunc();
});
var thefunc = function myfunc() {
alert('ok');
}
.divover {
padding: 20px;
background: yellow;
}
span {
background: blue;
color: white;
padding: 8px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='divover'>somelabel:
<span><input type="text" class="as" name="forename"></span>
</div>
This will work, if you do this carefully.
<div id="myone" onclick="javascript: myfunc();">
//your stuff in the clickable division.
</div>
<div style="position:absolute;">
<!--Adjust this division in such a way that, it comes inside your clickable division--><input
type="text" id="myInput"></input>
</div>
//Your script function/code here
function myfunc()
{
alert('ok');
}

Categories