I have a function that I am calling with two images like so.
$('#image1').bind('click',doNext);
$('#image2').bind('click',doNext);
I need to be able to tell which one called the function.
function doNext(){
if(target == $('#image1'){
alert('image1');
}else{
alert('image2');
}
}
this within doNext will be the raw DOM element, so:
function doNext() {
if (this.id === "image1") {
alert('image1');
}else{
alert('image2');
}
}
There I'm branching on the id because you specifically did that in your code, but usually you just interact with the object.
If you need to use any jQuery functions, wrap the raw DOM element in a jQuery object (var $this = $(this);), but you don't need to if all you want to do is look at the id as I did above.
Within jQuery event handlers, there are (at least) two significant DOM elements you have access to: The element on which you hooked the event (this), and the element that triggered the event (event.target). In your case, assuming that image1 and image2 are img elements, they'll be the same because img can't contain any other element, but in the case of elements that can contain other elements (div, p, etc. — e.g., most elements), event.target may be different from this. Say you have:
<div id="foo">
<p>Blah blah blah</p>
</div>
and this
$("#foo").click(function(event) {
alert(this.tagName);
alert(event.target.tagName);
});
If you click the paragraph, you'll get
DIV
P
...because you hooked the event on the div, but it was triggered by a click on the p. (This is the basis of event delegation.)
var id = $(this).attr('id');
if (id == 'image1') {
alert('image1');
} else{
alert('image2');
}
Use the attr() function to retrieve the ID of the element. Also, I would further simplify this by adding a common class to both images so that you can do this:
$('.myimages').click(function() {
if($(this).attr() == 'image1') {
alert('image1');
}
else {
alert('image2');
}
});
You can use event.target:
function doNext(event){
if($(event.target).attr('id') == 'image1'){
alert('image1');
}else{
alert('image2');
}
}
You can get the event.target in the event handler function:
function doNext(event) {
var target = event.target;
}
Alternatively, this will refer to the clicked element:
function doNext() {
var clickedID = this.id;
}
$(document).ready(function() {
$('#image1').click(function(){doNext('image1')});
$('#image2').click(function(){doNext('image2')});
});
doNext = function (target){
if(target == "image1"){
alert('image1');
}else{
alert('image2');
}
}
Related
$("input").on("keypress",function(e){
if(e.which===13){
$("ul").last().append("<li>"+$(this).val()+"</li>");
}
$("li").on("click",function(){
$(this).toggleClass("striked");
});
$("li").on("mouseenter",function(){
$(this).css("color","green");
});
});
$("li").on("click",function(){
$(this).toggleClass("striked");
});
$("li").on("mouseenter",function(){
$(this).css("color","green");
});
$("#slide").on("click",function(){
$("input").slideToggle();
});
Here, I have used the onClick event on<li> to apply the striked class two times just to make it work for both dynamic and non-dynamic elements on the page. But the code is replicated and seems long. Is there any way to shorten so that I can write it once and it gets activated for both types of elements?
Use event delegation instead, on the ul, so you only have to set up listeners once, rather than setting up multiple listeners for every element on load and on each .append. Also, save the ul and the input jQuery-wrapped elements in a variable once rather than selecting them and wrapping them with jQuery each time they're used:
const $ul = $("ul");
const $input = $("input");
$input.on("keypress", function(e) {
if (e.which === 13) {
$ul.last().append("<li>" + $(this).val() + "</li>");
}
});
$ul.on("click", 'li', function() {
$(this).toggleClass("striked");
});
$ul.on("mouseenter", 'li', function() {
$(this).css("color", "green");
});
$("#slide").on("click", function() {
$input.slideToggle();
});
A rather generic approach would be to capture the click event and check if it is from ul
document.body.onclick = function(e){
e = e || event;
var from = findParent('ul',e.target || e.srcElement);
if (from){
/* it's a link, actions here */
}
}
//find first parent with tagName [tagname]
function findParent(tagname,el){
while (el){
if ((el.nodeName || el.tagName).toLowerCase()===tagname.toLowerCase()){
return el;
}
el = el.parentNode;
}
return null;
}
now you can change the tagName passed to the findParent function and do accordingly
Read Here
You can try using the jquery all selector $('*'). For more information on this see
https://api.jquery.com/all-selector/.
Or you can add a specific class to every element you want to have an onClick action.
I have a listener which runs when I click on document.
document.addEventListener('click', print);
function print(element)
{
doSomething();
}
It creates div id=panel, where I print some information.
When I run the print function I would like to detect whether I clicked outside of the div#panel (The panel exists when I click second time).
I wish not to use the mouseout event listener because I think it is redundant to use listener for mouse movements when the event click is already fired.
How to detect when I clicked out of div#panel?
You can check the target of jQuery's click event, which element it was:
$(document).click(function(e) {
var target = $(e.target);
if( !target.is("#panel") && target.closest("#panel").length === 0 ) {
// click was not on or inside #panel
}
});
Your event handler gets passed an event object, not an element. Since you are listening for the click event, the event will be of type MouseEvent and that event object will have a target property which you can use to check if the target element matches your desired element.
function handler(event) {
if (event.target == document.getElementById("panel")) {
// Do stuff
}
}
document.addEventListener('click', handler);
Edit: I intentionally gave the vanilla JS answer since your own code fragments don't use jQuery. But jQuery wouldn't change anything as its event handling API is almost just a thin wrapper over JS.
I am just using event from the click. Here it is
var elem=document.getElementById("elem");
var rects=elem.getBoundingClientRect();//get the bounds of the element
document.addEventListener('click', print);
function print(e)
{
//check if click position is inside or outside target element
if(e.pageX<= rects.left +rects.width && e.pageX>= rects.left && e.pageY<= rects.top +rects.height && e.pageY>= rects.top){
console.log("Inside element");
}
else{
console.log("Outside element");
}
}
JS Bin link : https://jsbin.com/pepilehigo/edit?html,js,console,output
A different approach, using only javascript is:
function print(evt) {
if (!(evt.target.tagName == 'DIV' && evt.target.classList.contains('myDiv'))) {
var div = document.createElement('div');
div.classList.add('myDiv');
div.textContent="new div";
document.body.appendChild(div);
}
}
window.onload = function() {
document.addEventListener('click', print);
}
.myDiv {
border:1px solid green;
}
Is there a way to add some kind of listener for a type of html element? For example if i wanna call a function when the user clicks any p element
the easiest answer would be using addEventListener() if you want a specific html tag just like what i wanted in my question then you'll find the answer there ill paraphrase it here too
add this
<script>
document.addEventListener("click", function(e){
//your desired nodeName like : DIV , SPAN , LI etc
if(e.target && e.target.nodeName== 'DIV')
//add a function below to trigger
{alert('bingo')}
});
</script>
to the end of your document
by the way don't forget to use uppercase nodeNames or just put a toLowerCase() before it. cheers :)
Add the event listener to the window / document / document.body and check the type of the element and the types of its parents because if you have a <span> inside a <p>, clicking the span won't trigger the click in the paragraph.
document.addEventListener("click", function (eventArgs) {
var target = eventArgs.target;
var elementToLookFor = "p";
while (target !== null) {
if (target.tagName.toLowerCase() === elementToLookFor) {
// Do magic stuff with the paragraph
console.log(target);
}
target = target.parentElement;
}
});
This technique is called "event delegation."
Edit: Note that you cannot early return from the loop above. If your have nested paragraphs, i.e.
<p>
Hey,
<p>there!</p>
</p>
Having an early return will only call your event handler for the inner paragraph, whereas you said that you'd like the handler to be invoked on every paragraph which is why you need to traverse all the ancestors of the element.
I assume that you are looking for code along these lines:
var paras = document.getElementsByTagName("p");
// Loop through elements.
for(var i = 0; i < paras.length; i++) {
// Add listener.
paras[i].addEventListener("click",
function() {
// Execute function.
}, false);
}
I'd just select all the elements on the page and add eventListeners on them like so:
function addListeners(elementType, eventType, callback) {
Array.prototype.slice.call(document.querySelectorAll(elementType)).forEach(function (el, i) {
el.addEventListener(eventType, callback, false);
});
}
Above we use querySelectorAll to pick all the wanted elements, convert it to an Array (if you use es6, you can use Array.from) and then we loop through the array and add listeners with the wanted callback.
Here's an example: https://jsfiddle.net/a7en4d4s/
Look at this JSFiddle, and see if it works for you
<span>Click Yes</span><br/><br/>
<span>Click No</span><br/><br/>
<a>Clicked: <b id="result"></b></a>
<script>
$("span").click(function(){
var a = $(this).html();
$("#result").html(a);
});
</script>
I have several jQuery click functions- each is attached to a different DOM element, and does slightly different things...
One, for example, opens and closes a dictionary, and changes the text...
$(".dictionaryFlip").click(function(){
var link = $(this);
$(".dictionaryHolder").slideToggle('fast', function() {
if ($(this).is(":visible")) {
link.text("dictionary ON");
}
else {
link.text("dictionary OFF");
}
});
});
HTML
<div class="dictionaryHolder">
<div id="dictionaryHeading">
<span class="dictionaryTitle">中 文 词 典</span>
<span class="dictionaryHeadings">Dialog</span>
<span class="dictionaryHeadings">Word Bank</span>
</div>
</div>
<p class="dictionaryFlip">toggle dictionary: off</p>
I have a separate click function for each thing I'd like to do...
Is there a way to define one click function and assign it to different DOM elements? Then maybe use if else logic to change up what's done inside the function?
Thanks!
Clarification:
I have a click function to 1) Turn on and off the dictionary, 2) Turn on and off the menu, 3) Turn on and off the minimap... etc... Just wanted to cut down on code by combining all of these into a single click function
You can of course define a single function and use it on multiple HTML elements. It's a common pattern and should be utilized if at all possible!
var onclick = function(event) {
var $elem = $(this);
alert("Clicked!");
};
$("a").click(onclick);
$(".b").click(onclick);
$("#c").click(onclick);
// jQuery can select multiple elements in one selector
$("a, .b, #c").click(onclick);
You can also store contextual information on the element using the data- custom attribute. jQuery has a nice .data function (it's simply a prefixed proxy for .attr) that allows you to easily set and retrieve keys and values on an element. Say we have a list of people, for example:
<section>
<div class="user" data-id="124124">
<h1>John Smith</h1>
<h3>Cupertino, San Franciso</h3>
</div>
</section>
Now we register a click handler on the .user class and get the id on the user:
var onclick = function(event) {
var $this = $(this), //Always good to cache your jQuery elements (if you use them more than once)
id = $this.data("id");
alert("User ID: " + id);
};
$(".user").click(onclick);
Here's a simple pattern
function a(elem){
var link = $(elem);
$(".dictionaryHolder").slideToggle('fast', function() {
if (link.is(":visible")) {
link.text("dictionary ON");
}
else {
link.text("dictionary OFF");
}
});
}
$(".dictionaryFlip").click(function(){a(this);});
$(".anotherElement").click(function(){a(this);});
Well, you could do something like:
var f = function() {
var $this = $(this);
if($this.hasClass('A')) { /* do something */ }
if($this.hasClass('B')) { /* do something else */ }
}
$('.selector').click(f);
and so inside the f function you check what was class of clicked element
and depending on that do what u wish
For better performance, you can assign only one event listener to your page. Then, use event.target to know which part was clicked and what to do.
I would put each action in a separate function, to keep code readable.
I would also recommend using a unique Id per clickable item you need.
$("body").click(function(event) {
switch(event.target.id) {
// call suitable action according to the id of clicked element
case 'dictionaryFlip':
flipDictionnary()
break;
case 'menuToggle':
toggleMenu()
break;
// other actions go here
}
});
function flipDictionnary() {
// code here
}
function toggleMenu() {
// code here
}
cf. Event Delegation with jQuery http://www.sitepoint.com/event-delegation-with-jquery/
How do I style a clicked link with CSS in JavaScript?
Here is my link:
<li><id="106" onClick="configurator(this)" href="#">10.6 µ</a><li>
I am trying to run a function called configurator and return the ID of the this link so I can set the CSS.
Help! I am a JS newbie!
Here is my function:
function configurator(clicked) {
document.getElementById(clicked);
alert(clicked.name);
}
If your onClick function is called as "configurator(this);", then you passed it the element itself, not the ID of the element.
function configurator(clicked) {
// document.getElementById(clicked); // doesn't work because "clicked" is an element, not an ID
clicked.style.fontWeight = "bold";
// OR
clicked.className = "boldClass";
alert(clicked.name);
}
EDIT:
Also just noticed that you are missing the "a" tag. It should be:
<li><a id="106" onClick="configurator(this)" href="#">10.6 µ</a><li>
You can style an element like this:
element.style.color = 'white';
element.style.backgroundColor = 'red';
To get the element which was clicked you could use the event:
function doSomething(e) {
var targ;
if (!e) var e = window.event;
if (e.target) targ = e.target;
else if (e.srcElement) targ = e.srcElement;
if (targ.nodeType == 3) // defeat Safari bug
targ = targ.parentNode;
}
Example function from quirksmode.org.
EDIT: Other thing: It's bad practice to add onclick properties directly to the html. You could use unobtrusive javascript.
EDIT 2: A jQuery example.
$(function() // Alias for $(document).ready()
{
$('li a').click(function()
{
$(this).css({
color: 'red'
});
});
});
There are a few problems with the above example, I've tried to clean it up as best I can. Here's code that I tested, that works by itself. It's not pretty, but it works:
<li>10.6 µ</li>
<script type="text/javascript">
function configurator(clicked) {
alert(clicked.id);
}
</script>
You can use Element.addEventListener() to achieve this.
This is completely untested but it should give you some direction. Passing the whole css object came to me on the fly, you could alternatively omit this and hardcode the styles you are trying to change (but why would you wanna do that =P).
// Function to change the content of t2
function modifyStyle(styles) {
//save element
var that = this;
for each (property in styles){
that.style.property = styles[property];
}
}
// Function to add event listener anchor
function load() {
var el = document.getElementById("myAnchor"),
cssObj = {
background-color: 'black',
font-size: 1.2em
}
//set the function call to an anonymous function that passes your css object
el.addEventListener("click",
function(){modifyStyle(cssObj)},
false);
}
<li><a id="106" onClick="configurator(this.id)" href="#">10.6 µ</a><li>
function configurator(clicked)
{
var elementClicked = document.getElementById(clicked);
//Set the styles using the ID element.clicked.style......
alert(clicked);
}
Use document.getElementById(clicked); to get the sent ID and then you can set the styles to this. You missed out the a tag, and you was passing the element name not ID.