I am trying to detect whether a target element is either a child element, or the same element, that I have as an object reference.
I am using the following logic:
$("html").on("mousewheel.scroll DOMMouseScroll.scroll",function(e){
e.preventDefault();
var $scrollableElement = $(".foo").eq(0);
var $target = $(e.target);
if ($target == $scrollableElement
|| $target.parents($scrollableElement).length) {
alert("scroll");
}
});
However "scroll" is alerted even when scrolling over an element which is neither .foo or a child of .foo.
In my JsFiddle example, scroll over the .bar element, and "scroll" is still alerted:
http://jsfiddle.net/Lf3d2/
Why is this? Is it possible to use jQuery object references as the selector of .parents()?
Try .closest() instead of .parents()
$(function () {
var $scrollableElement = $(".foo").eq(0);
$("html").on("mousewheel.scroll DOMMouseScroll.scroll", function (e) {
e.preventDefault();
var $target = $(e.target);
if ($target.closest($scrollableElement).length) {
console.log("scroll");
}
});
});
Demo: Fiddle
If you have a look at the syntax of .parents(), it does not take a jQuery object as a parameter. The only allowed syntax is .parents( [selector ] )
As #A.Wolff asked why don't bind the event to .foo instead
Demo: Fiddle
Related
how is it possible to replace this jQuery with Vanilla:
$( document ).ready(function() {
$('body').on('click', '.f_click', function (e) {
e.preventDefault();
alert("TEST");
});
});
My first try was:
document.addEventListener('click', function (e) {
console.log(e.target);
if (e.target.classList.contains('f_bme_start')) {
alert('open Search!');
return false;
}
}, false);
this works, but not on child elements.
Has somebody an idea how to solve this?
I want to replace all my jQuery code because of slow performance.....
THANKS
You're only checking the element that was actually clicked, not its ancestor elements.
In modern environments you can use the DOM's closest method (and that link has polyfills for older environments):
document.addEventListener('click', function (e) {
const target = e.target.closest(".f_bme_start");
if (target) {
alert('open Search!');
return false;
}
});
That searches through the ancestors of the clicked element for a match for a given CSS selector. If you were hooking the event on a container element other than the document or document.body, I'd also use contains to make sure the search through ancestors didn't go to an ancestor of the container element:
const target = e.target.closest(".f_bme_start");
if (target && e.currentTarget.contains(target)) {
alert('open Search!');
return false;
}
But there's no need if you're hooking the event on document or document.body.
THANKS a lot!
what is the best solution?
For performance and for compatibility?
I think this one is best?:
document.addEventListener('click', function (e) {
for (var target = e.target; target && target != this; target = target.parentNode) {
console.log(target.classList);
if (target.classList.contains('f_click')) {
alert('open without jQuery!');
return false;
}
}
}, false);
$("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.
Is there a keyword that is opposite to the keyword this?
$('.lt-buttonContainer button').click(function () {
var $this = $(this);
$this.addClass("button1Clicked");
$!this.removeClass("button1Clicked");
})
There is no built in method to get all the other elements. Use not() to remove it from the collection.
var buttons = $('.lt-buttonContainer button');
buttons.click(function () {
var $this = $(this);
$this.addClass("button1Clicked");
buttons.not($this).removeClass("button1Clicked");
});
No, there is not a keyword that is the opposite of this in your context.
!this simply takes the logical not of the value of this which will not solve the problem in your code.
Your question could really stand for some clarification, but in your specific example, if you want all elements that were in the original collection, but are not the current value of this and that' what you meant by opposite, then you have to compute that collection yourself.
That could be accomplished like this:
$('.lt-buttonContainer button').click(function () {
$('.lt-buttonContainer button').removeClass("button1Clicked");
$(this).addClass("button1Clicked");
});
Or, if you really want a collection of the elements in the original collection that are not this, then you can do this:
$('.lt-buttonContainer button').click(function () {
$('.lt-buttonContainer button').not(this).removeClass("button1Clicked");
$(this).addClass("button1Clicked");
});
though the extra .not() operation in this second code snippet is not required in this specific case because it does no harm to .removeClass() from all objects in the collection before adding it back on one.
Does following snippet help ?
$('.lt-buttonContainer button').click(function () {
var $this = $(this);
$('.lt-buttonContainer button').removeClass ("button1Clicked");
$this.addClass("button1Clicked");
})
You could use toggleClass() jq method and delegate event using following logic:
$('.lt-buttonContainer').on('click', 'button:not(.button1Clicked)', function (e) {
$(e.delegateTarget).find('button.button1Clicked').add(this).toggleClass("button1Clicked");
});
And if elements button are siblings:
$('.lt-buttonContainer').on('click', 'button:not(.button1Clicked)', function () {
$(this).siblings('button.button1Clicked').add(this).toggleClass("button1Clicked");
});
How does one, through jQuery, get the ID of an element that is being clicked on and then pass it as a parameter into a function? Example jQuery code below.
jQuery(document).ready(function() {
var id = this_id;
jQuery(".lightbox a").click({param: id}, functionName);
});
May I note that the "param" parameter is integral to the structure of the function.
Apologies all, I am no Javascript master by any means.
I'm guessing the point is to pass event data to a function that expects that, as ,click() supports the .click( [eventData ], handler(eventObject) ) syntax, and if so, you have to iterate the collection yourself:
jQuery(document).ready(function($) {
$(".lightbox a").each(function() {
$(this).click({param: this.id}, functionName);
});
});
EDIT:
You could do this with on() as well:
jQuery(document).ready(function($) {
$(".lightbox a").each(function() {
$(this).on('click', {param: this.id}, functionName);
});
});
FIDDLE
Within the click handler, you can access the element ID with this.id or $(this).attr('id'):
jQuery(document).ready(function() {
jQuery(".lightbox a").click(function(){
functionName(this.id);
});
});
You can use this.id inside a click event, example:
jQuery(".lightbox a").click(function() {
var id = this.id;
//pass to a function
testFunction(id);
});
function testFunction(param) {
console.log(param);
}
It's easy just access to the this element to get the clicked element, then extract its id and save it into a variable like this:
jQuery(".lightbox a").click(function(){
var id = jQuery(this).attr("id");
callFunction(id);
});
http://jsfiddle.net/pArW6/
jQuery(document).ready(function() {
jQuery(".lightbox a").click(functionName);
});
function functionName()
{
alert(this.id);
}
You can you Use $(this).att("id").
$(".lightbox a").click(function() {
var ID=$(this).att("id");
//pass to a function
TestFunction(ID);
});
function TestFunction(P) {
console.log(P);
}
Live example
http://jsbin.com/enobop/1/edit
You can do this:
jQuery(document).ready(function () {
jQuery(".lightbox a").click(function (e) {
// Cancel the default action (navigation) of the click.
e.preventDefault();
// 'this' here refers to the link being clicked in the current scope
// you can check the console for the id for debug purpose
console.log(this.id);
// pass the id to the function
functionName(this.id);
});
});
Another way is to use the event parameter that gets passed to the callback function.
jQuery(".lightbox a").click(function(ev) {
console.log(ev.target.id);
}
Of course it's a mix of jQuery and pure JS.
Usually you have a function for an event declared with
function(event)
and the event has a target and the id of the target is, what you want. So
$("SomeElement").on("click", function(e){ callanotherFunction(e.target.id) })
does, what you wanted
You can use this.id or $(this).attr("id");, but you might want to get a reference to $(this) - wrapped or not - immediately and work from a variable if you do much of anything else in there.
I've added a click event as follows and would like to check if the target has a specific parent.
$(document).click(function(event){
// Check here if target has specific parent for example -> #parent
});
How can this be done?
There's a .parent() dom traversal method for this.
according to Pointy's crystal ball, you probably want to do something like this:
$(document).click(function(event) {
if ($(event.target).parents('.selector').length > 0) {
}
});
I'm not sure why are you set click handler on document, maybe looking for event delegation and the .on()?
I believe this also works.. AFAIK jQuery events use the the literal element instead of a jQuery object when calling events. Basically this should be your normal DOM element with normal JavaScript properties.
$(document).click(function(event)
{
let myparent = $(this.parentNode); //jquery obj
let parent = $(this.parentNode)[0]; //plain DOM obj
let myself = $(this); //jquery obj;
let $elf = this; //plain DOM obj
});
Note: sometimes using 'self' as a variable is bad/causes conflicts with certain libraries so i used $elf. The $ in $elf is not special; not a jQuery convention or anything like that.
$(document).click(function(event){
var $parent = $(this).parent();
// test parent examples
if($parent.hasClass('someclass')) { // do something }
if($parent.prop('id') == 'someid')) { // do something }
// or checking if this is a decendant of any parent
var $closest = $(this).closest('someclass');
if($closest.length > 0 ) { // do something }
$closest = $(this).closest('#someid');
if($closest.length > 0 ) { // do something }
});
I have reliably used this in the past:
var target = $( event.target )
This will give you a reference to the jQuery object for the element that had the event invoked. You could use this same approach and see if the parent is "#parent", something like this:
var target = $( event.target )
if (target.parent().attr('id') == "#parent") {
//do something
}