I'm trying to make a function that will be fired with the 'onclick' event of a procedurally added div.hb-menu-subMenuToggle element. The function works when using the initial selector as anything but '$(this)'
// FUNCTION: hbMenuSubToggle()
// Toggles CSS classes for animation of .hb-menu-sub-open. Fires when clicking the div element with .hb-menu-subMenuToggle class
function hbMenuSubToggle(){
// TESTING: This works as far as opening the submenus; however, it does not open only the submenu that is a direct sibling of the hb-menu-subMenuToggle element.
$('a.withSubmenu').siblings('ul').toggleClass('hb-menu-sub-open');
// DESIRED EFFECT: Does not work
$(this).siblings('ul').toggleClass('hb-menu-sub-open');
};
Here's a link to the
Codepen Project
Any help would be greatly appreciated!
The correct way to do this would be to use jQuery event handlers rather than using onClick and a function inline in your HTML.
For example if you place this within your $(document).ready() it will attach a click event handler to all A elements in your top menu. When it is clicked you will be able to get $(this) (which is the A element) and then traverse to its parent (the UL element) and then find the child UL elements (the sub menu) to toggle the class.
$('#main-nav>ul>li').on('click', '>a', function(){
$(this).parent().find('ul').toggleClass('hb-menu-sub-open');
});
Similarly your function to show the main menu could also be written as follows
$(document).on('click', '.hb-menu-btn', function(){
$('.hb-menu-btn, .hb-menu, .hb-menu-page').toggleClass('hb-menu-open');
});
See it working on CodePen here: http://codepen.io/anon/pen/rOKQOJ
function hbMenuSubToggle(divyouneed){
// TESTING: This works as far as opening the submenus; however, it does not open only the submenu that is a direct sibling of the hb-menu-subMenuToggle element.
$('a.withSubmenu').siblings('ul').toggleClass('hb-menu-sub-open');
// DESIRED EFFECT: Does not work
divyouneed.siblings('ul').toggleClass('hb-menu-sub-open');
};
and use it
hbMenuSubToggle($(this))
for $(this) you have to had selected one element before. In a function you dont have it like that.. So it will only work if you select it directly and not with $(this)
function hbMenuSubToggle() {
$('.blablabla').blablabla();
}
And read this to find out more about jQuerys basics
Related
I have two lists. I am making it so when you click the first list (instrument), you get a class list based on that instrument.
The first list is pretty clickable and everything seems to be working. But when I click the second list (li) element nothing happens. It seems so far that I can do anything with the second list except for targeting on click i have tried add class and it works but on click doesn't work.
Here's a sample.
The left list onclick works fine but the right one doesn't
Here is a link to the codepen
Link to the Code Pen
Here is the specific code that targets my li element with the class "classList"
$(".classList").on('click',function(){
$(".classList").removeClass("clicked");
$(this).addClass("clicked");
$(".studentInformationView").show();
$("#nameInput").show();
});
The code is too long to put a snippet here so please access the codepen.
Please let me know what's wrong.
Since you are adding your .classList dynamically after the page load you will after to attach your click event differently, as a delegated event.
You can read about jQuery .on() delegated events here.
Delegated events have the advantage that they can process events from
descendant elements that are added to the document at a later time.
Like this:
$(document).on('click', '.classList', function(){
$(".classList").removeClass("clicked");
$(this).addClass("clicked");
$(".studentInformationView").show();
$("#nameInput").show();
});
So attach the event to the document (which will always exist on page load when you are attaching the event), and it will delegate it to the .classList when it gets added at a later time.
Here is an updated CodePen
I have a clickable item, which contains child elements, too. My problem stems from wanting to animate the :active state of the clicked item by using a 1px translation.
The mousedown of the click lands on a child element
The 1px translate moves the child element from under the mouse pointer
The mouseup event now happens on the parent element
This results in the click getting canceled. I can prevent the child element from catching the click using pointer-events: none in CSS, but since it's both new and unstable, I'd love to find a more compatible fix. For now, I've settled on just sticking a transparent DIV on top of the whole item, but that's ugly.
Exaggareted demo in this pen: http://codepen.io/JonFabritius/pen/mJuzy
Try clicking the bottom half of the orange bar, the pointer remains on top of the child element. Then click on the top half, which causes the element to move from under the pointer.
It's probably staring me in the face, but I haven't been able to find a simple fix- any ideas appreciated.
Disclaimer: I don't jQuery.
This is a response better considered as a comment, though with the addition of code.
You say that "the click target is the parent" - Sorry to be a little thick here, but when you say it's the click target, is the parent the element that has the event listener attached to it, or by click target, do you mean that it is the value returned by evt.target? (Where evt is the single variable passed to the event handling function)
To better illustrate what I'm getting at, consider the following code:
JS portion:
window.addEventListener('load', mInit, false);
function mInit()
{
document.getElementById('clickTarget').addEventListener('click', handleClick, false);
}
function handleClick(evt)
{
console.log(this.id + ': is the id of the "this" element');
console.log(evt.target.id + ": was the id of the evt.target");
}
HTML portion:
<body>
<div id='clickTarget'><a id='link1'>Link1</a><a id='link2'>Link2</a></div>
</body>
Now then, when you click on link1, the output shown in the console is:
clickTarget: is the id of the "this" element
link1: was the id of the evt.target
Predictably, clicking on link2 shows the following:
clickTarget: is the id of the "this" element
link2: was the id of the evt.target
So, you can clearly see that in this example, the <div> is the parent of the two <a> elements.
Yet, in each instance the target is different - it's not the parent, it's the actual element that was clicked.
You've used jQuery, which, while simple to add functionality, hides implementation details, slows JS execution and (usually) adds unnecessarily to page-weight. Your code is very short and sweet, yet what is being returned requires some investigation - it's certainly not obvious.
As a side note, a quick look at the jQuery Docs: jQuery .delegate tells us that as of jQuery 1.7, the preferred method use to achieve this functionality is .on() - it's likely of no consequence, but one never knows..
Turns out if you use the current .on syntax, it works fine:
$(function() {
// target ON event, delegate
$('#container').on('click', '.item', function() {
$('.item').append('*');
});
});
UPDATE Could you do this with a custom class? This seems to work so long as the pointer doesn't leave the .item element. Child elements behave as expected.
$(function() {
$('#container').on('mousedown', '.item', function() {
$(this).addClass('active');
$('.item').append('*');
}).on('mouseup', '.item', function() {
$(this).removeClass('active');
});
});
DEMO: http://codepen.io/anon/pen/lponk
I am basically having a little trouble with a <li> of items, that I am running a plugin through, which dynamically adds a data-tag ID to the data-* attribute.
This for some reason means that all items are dynamically added, and another function I am running on the same list elements won't run, because the event isn't dynamically attached.
What happens is:
1) Page renders
2) My 'other' function is available whilst DOM is loading
3) Page loads, the plugin code is available, but my 'other' function (which adds a hover box title which comes from below and animates up) no longer works. So it basically works until the other plugin kicks in.
My findings so far are:
I can use the jQuery 'on' to dynamically attach events to dynamically edited/created items (the #stage li items). Using this:
$('body').on('hover', '#stage li', function() {
// Do dynamic stuff
}
But this only works with 1 hover, and doesn't give me a mouseenter/mouseout solution which I really need. Does anyone have any ideas on how to accomplish this?
Yup:
$('#stage').on({
mouseenter: function(){
// do mouseentery shtuff
},
mouseleave: function(){
// mouse bye bye
}
},'li');
Changed .on() event binding from body to #stage and filter li from there, because it will be faster.
The cool thing about doing it this way (the XML way) is that you can easily add more stuff to it ... adding a mousemove function is just another comma and function below it in the same item, all contained within the one .on() binding. :)
Here's what you're looking for. Also, note that hover is no longer supported as of jQuery 1.9
$('mydiv').on('mouseenter', '#stage li', function( event ) {
// do something
}).on('mouseleave', '#stage li', function( event ) {
// do something different
});
I have the following code:
var $reviewButton = $('span.review_button');
$reviewButton
.live('click',
function(){
$('#add_reviews').show();
}
)
Later in the script, I use an AJAX call to load some content and another instance of $('span.review_button') enters the picture. I updated my code above to use '.live' because the click event was not working with the AJAX generated review button.
This code works, as the .live(click //) event works on both the static 'span.review_button' and the AJAX generated 'span.review_button'
I see however that .live is depracated so I have tried to follow the jquery documentations instructions by switching to '.on' but when I switch to the code below, I have the same problem I had before switching to '.live' in which the click function works with the original instance of 'span.review_button' but not on the AJAX generated instance:
var $reviewButton = $('span.review_button');
$reviewButton
.on('click',
function(){
$('#add_reviews').show();
}
)
Suggestions?
The correct syntax for event delegation is:
$("body").on("click", "span.review_button", function() {
$("#add_reviews").show();
});
Here instead of body you may use any static parent element of "span.review_button".
Attention! As discussed in the comments, you should use string value as a second argument of on() method in delegated events approach, but not a jQuery object.
This is because you need to use the delegation version of on().
$("#parentElement").on('click', '.child', function(){});
#parentElement must exist in the DOM at the time you bind the event.
The event will bubble up the DOM tree, and once it reaches #parentElement, it is checked for it's origin, and if it matches .child, executes the function.
So, with this in mind, it's best to bind the event to the closest parent element existing in the DOM at time of binding - for best performance.
Set your first selector (in this case, div.content) as the parent container that contains the clicked buttons as well as any DOM that will come in using AJAX. If you have to change the entire page for some reason, it can even be change to "body", but you want to try and make the selector as efficient as possible, so narrow it down to the closest parent DOM element that won't change.
Secondly, you want to apply the click action to span.review_button, so that is reflected in the code below.
// $('div.content') is the content area to watch for changes
// 'click' is the action applied to any found elements
// 'span.review_button' the element to apply the selected action 'click' to. jQuery is expecting this to be a string.
$('div.content').on('click', 'span.review_button', function(){
$('#add_reviews').show();
});
How does the click() function in jquery work when working with multiple stacked divs?
I have one main div and another div inside of the main div, when i click on the div inside, its also considered a click on the main div, but i dont want that, i want it to only consider a click on the inside div.
<div id="main"><div id="inner"></div></div>
Lets say the main div is a lot larger and the innner div is just a small square, when i click on the inner div(small square) I dont want it to trigger anyting as if i were to click on the main div. How do I maneuver this? Thanks again!
Events bubble up from the one that was clicked, through all its ancestors. Any ancestor that handles that event will have its handler fired.
What you need to do is to call event.stopPropagation() in order to prevent the event from bubbling up to its ancestor elements.
$('#inner').click(function(evt) {
evt.stopPropagation();
// your code
});
http://api.jquery.com/event.stopPropagation/
Another alternative is to return false; at the end of your handler.
$('#inner').click(function(evt) {
// your code
return false;
});
You can test it out here: http://jsfiddle.net/ZpeYr/
$('#inner').click(function() {
alert('clicked inner div'); // do something
});
you can call your inner div using using the css id.