Prevent parent mouseout jQuery event to trigger on child - javascript

This is probably a known issue or question. However, I only see results for
Element.on('click', callback)
events and I do not know how to do this with and on 'mouseout' event
This is my HTML:
<div class="oneTodo">
<div class="todoText"></div>
<span class="eraseTodo">
<i class="icon ion-ios-close-outline"></i>
</span>
</div>
And my script:
$('.oneTodo').hover(function () {
$(this).find('.eraseTodo').fadeIn(100);
});
$('.oneTodo').on('mouseout', function() { // this is what is not working
$(this).find('.eraseTodo').fadeOut(100);
});
Basically when I hover over my:
<span class="eraseTodo">
<i class="icon ion-ios-close-outline"></i>
</span>
since it basically is not the .oneTodo div anymore it fades Out. I want to prevent this. How can I achieve this?
P.S: I tried:
$('.oneTodo:not(.eraseTodo)').on('mouseout', function() {
$(this).find('.eraseTodo').fadeOut(100);
});
but failed miserably.

Related

jQuery Nested function variable scoping

I cannot get a nested variable value to populate outside a nested function within a button's click event function even though I believe I am using a global variable.
What am I doing wrong to pull value into a console log outside the nested function?
I am creating a shopping cart utilizing jquery pop-up with ajax and php. I am able to add items to the cart as well as add a name & email input field.
When I go to console log in Chrome for the focusout event for the fields they show the values but when trying to use a Checkout button, I am not able to pass the data within the Checkout click outside of a nested function even with a global variable.
--JS--
var formname;
$(document).ready(function() {
...
$(document).on('click', '#check_out_cart', function(){
$('#cart-popover').popover({
html : true,
container: 'body',
content:function(){
return $('#popover_content_wrapper').html();
}
});
$(document).on('click', '#cart-popover', function(){
$('input#namef').focus();
});
$('input#namef').on('focusout', function(){
formname= $('input#namef').val();
console.log(formname);
});
var scart_add = $("input[name='scart_add']").val();
console.log("Scart value is "+scart_add);
console.log("Name is "+formname);
...
});
});
--HTML--
<div class="container">
<nav class="navbar navbar-default" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Menu</span>
<span class="glyphicon glyphicon-menu-hamburger"></span>
</button>
</div>
<div id="navbar-cart" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>
<a id="cart-popover" class="btn" data-placement="bottom" title="Shopping Cart">
<span class="glyphicon glyphicon-shopping-cart-2x"></span>
<span class="badge"></span>
<span class="total_price">$ 0.00</span>
</a>
</li>
</ul>
</div>
</div>
</nav>
<div id="popover_content_wrapper" style="display: none">
<span id="cart_details"></span>
<div>
<form method="POST">
Name: <input type="text" id="namef" >
Email: <input type="text" id="emailf" >
<input type="hidden" name="scart_add" value="1" /><br><br>
</div>
<div align="right">
<button type="button" class="btn btn-primary" id="check_out_cart">
<span class="glyphicon glyphicon-shopping-cart"></span> Check out
</button>
<button type="button" class="btn btn-default" id="clear_cart">
<span class="glyphicon glyphicon-trash"></span> Clear
</button>
</div>
</form>
</div>
</div>
<div id="display_item">
</div>
...
</div>
I am expecting the value from the input#namef text to appear in the console.log ...formname variable but it just shows as "".
The event for focusout isn't added to the input until you click the button:
Also, I don't know if it is how you copied and pasted your HTML and Javascript, but it was throwing errors when I put it into a fiddle.
Move this outside of the button click handler as Rory pointed out:
var formname;
$(document).ready(function() {
//Now focusout handler is added on DOM Ready instead of when you click the button
$('input#namef').on('focusout', function(){
formname= $('input#namef').val();
console.log(formname);
});
$(document).on('click', '#check_out_cart', function(){
var scart_add = $("input[name='scart_add']").val();
console.log("Scart value is "+scart_add);
console.log("Name is "+formname);
});
});
Here is a working fiddle: https://jsfiddle.net/hqgv7zsa/
This is a race condition, of sorts.
On document.ready event, you are setting a click event handler
Inside the click handler, you are setting the focusout event handler
Since the click handler is still executing,
immediately, the code runs to show value of scart and formname.
At that time, formname is still empty because the current function
(click event handler) is still executing, and the focusout event, even
if it fires, will fire after that code is executed.
You should move the focusout handler declaration code outside of the click handler code, which will then set both handlers on document.ready() event.
Here's a breakdown of what's happening and when:
var formname;
$(document).ready(function() {
This fires when DOM is loaded (document.ready event)
$(document).on('click', '#check_out_cart', function(){
This fires when user clicks on some element with ID check_out_cart
$('input#namef').on('focusout', function(){
This event handler is only being set once user clicks on cart, but it is not yet executed!
formname= $('input#namef').val();
console.log(formname);
});
This code fires once the event handler has been set for focusout, but still has not executed. Even if a focusout event is fired, it will only execute when the current function exits.
var scart_add = $("input[name='scart_add']").val();
console.log("Scart value is "+scart_add);
Correctly, you will see that formname is empty at this point.
console.log("Name is "+formname);
...
});
});
Hope this explains the flow you're seeing;
Quick fix as in Ryan Wilson's answer, move the focusout handler declaration to the scope of the document.ready handler, outside the click handler.
Using the solution from Unable to fetch values from an input element in Bootstrap's popover, I was able to adjust my JS code to fetch the values with a .find within the .popover-content class that was added by the popover JS.
var formname;
var formemail;
$(document).ready(function() {
//shopping cart
/*load functions*/
load_product();
load_cart_data();
$('#cart-popover').popover({
html : true,
container: 'body',
content:function(){
return $('#popover_content_wrapper').html();
}
});
$(document).on('click', '#cart-popover', function(){
$('input#namef').focus();
});
$(document).on('focusout', '#namef', function(){
formname = $('.popover-content').find('#namef').val();
});
$(document).on('focusout', '#emailf', function(){
formemail = $('.popover-content').find('#emailf').val();
});
$(document).on('click', '#check_out_cart', function(){
var scart_add = $("input[name='scart_add']").val();
var nameval = $("input#namef").val();
alert("Scart value is "+scart_add);
alert("Name is "+formname);
alert("Email is "+formemail);
});
});

HTML mobile button show/hide after few seconds

i have for my mobilesite some buttons.
<div class="menubottom" id="menumobile">
<div >
<div class="mobilebutton displaynone" id="mobilebuttonLeft" style="float:left;" onclick="swipeRight();"><i class="fa fa-chevron-circle-left fa-3x" aria-hidden="true"></i></div>
<div class="mobilebutton" id="mobilebuttonRight" style="float:right;" onclick="swipeLeft()"><i class="fa fa-chevron-circle-right fa-3x" aria-hidden="true"></i></div>
</div>
</div>
now i want them to disappear if a amount of time with no TouchInput passes away.
And if i Touch again on the display the buttons should be appear again.
I have jquery and jquery mobile installed but i cant find a good resolution for my problem. Did you have any idea?
now i want them to disappear if a amount of time with no TouchInput
passes away
You can do setTimeout which will hide the menu after 2 seconds
function hideMenu(){
setTimeout( function(){
$ ( "#menumobile" ).hide();
}, 2000);
}
To make it reappear again on click, just bind a touchend event
$(document).on( "touchend click", function(){
$ ( "#menumobile" ).show();
hideMenu(); //hide again after 2 seconds
})
You can use touchstart and touchend event for hiding show mobilebutton
settimeout of 3s for hide button after touchend
$("body").on('touchstart mousedown',function (e){
$('.mobilebutton').show();
});
$("body").on('touchend',function (e){
setTimeout(function(){
$('.mobilebutton').hide();
}, 3000);
});

javascript click event not firing

I'm having trouble figuring out why my click event is not firing. I am trying to click on the trash can icon and have a function run that deletes the list element. After the click event, it fails to execute anything else in the script. It doesn't even console.log anything directly below. Below is the markup and my script.
HTML CODE
<div class="col-6">
<div class="js-list-item">
<h3 class="js-list-title"></h3>
<i class="fa fa-pencil" aria-hidden="true"></i>
<i class="fa fa-trash-o" aria-hidden="true"></i>
<p>Date: <span class="js-date"></span></p>
<p>Schedule: <span class="js-schedule"></span> at <span class="js-schedule-time">
</span></p>
</div>
</div>
javascript code
function handleDelete() {
$('.js-list-item').on('click', 'fa-trash-o', function(e) {
console.log('test');
e.preventDefault();
deleteShow(
$(e.currentTarget).closest('.js-list-item').attr('id')
);
});
}
The second parameter of the .on() function is a selector.
http://api.jquery.com/on/
Change:
$('.js-list-item').on('click', 'fa-trash-o', function(e) {
to:
$('.js-list-item').on('click', '.fa-trash-o', function(e) {
('click', 'fa-trash-o', function(e)
fa-trash-o is not a proper selector, use class or id

Inline editing with icon on side

i'm trying to create an inline editing plugin for a new project, I'm working on. It should be very easy. Just an fa-pencil icon on side of the text, which should be edited.
Currently I've got HTML like so (simplified):
<div class="inline-edit-icon">
<i class="fa fa-pencil"></i>
</div>
<div class="inline-edit">
<p id="doctor-info-text" class="inline-edit-text">{{userInfo.description}}</p>
<textarea class="form-control inline-edit-input" ng-model="userInfo.description"></textarea>
</div>
And I'm triggering the visibility of the .inline-edit-icon div via jQuery:
$('.inline-edit-text').hover(function(e){
var coordinates = $(this).offset();
$('.inline-edit-icon').css('top', coordinates.top);
$('.inline-edit-icon').css('left', coordinates.left - $('.inline-edit-icon').width());
$('.inline-edit-icon').show();
}, function(){
$('.inline-edit-icon').hide();
});
The problem is, I can't click on the icon, as it gets hidden before I get my mouse to it.
How can I keep it visible when the mouse is over either text or icon?
Does this example help you? Notice the changes I made with HTML AND CSS:
$('.inline-edit-text, .fa-pencil').hover(function(e){
var coordinates = $(this).offset();
console.log(coordinates)
//$('.inline-edit-icon').css('top', coordinates.top);
//$('.inline-edit-icon').css('left', coordinates.left);
$('.inline-edit-icon').show();
}, function(){
$('.inline-edit-icon').hide();
});
JSFiddle
Add a container around your .inline blocks, and you trigger the hover on it.
Something like :
<div class="inline-container">
<div class="inline-edit-icon">
<i class="fa fa-pencil">o</i>
</div>
<div class="inline-edit">
<p id="doctor-info-text" class="inline-edit-text">{{userInfo.description}}</p>
<textarea class="form-control inline-edit-input" ng-model="userInfo.description"></textarea>
</div>
</div>
and the script part:
$('.inline-container').hover(function(e){
var coordinates = $(this).children('.inline-edit').offset();
var $icon = $(this).children('.inline-edit-icon');
$icon.css('top', coordinates.top);
$icon.css('left', coordinates.left - $icon.width());
$icon.show();
}, function(){
$('.inline-edit-icon').hide();
});
Working Fiddle: http://jsfiddle.net/qej24s5m/
Hope it's gonna help you.
You may want to use mouseenter and mouseleave events:
$('.inline-edit-text, .fa.fa-pencil').on('mouseenter',function(e){
var coordinates = $(this).offset();
$('.inline-edit-icon').css('top', coordinates.top);
$('.inline-edit-icon').css('left', coordinates.left - $('.inline-edit-icon').width());
$('.inline-edit-icon').show();
});
$('.inline-edit-text, .fa.fa-pencil').on('mouseleave',function(e){
$('.inline-edit-icon').hide();
});

jQuery .not not functioning correctly

I'm having a problem with jQuery .not() not working.
I've got a pricing table with 3 products, when you mouse over each of the products a description appears and then disappears on mouse out so far everything works fine.
The problem however is that on page load one of the three products (each held in an <aside>) will have a .selected class applied to it and I need the mouseenter/leave function to not run on this <aside>.
The only caveat is that clicking any of the <button>'s in each <aside> will remove the .selected class from it's current <aside> and apply to the <button>'s <aside> parent (I've not included the JQ for this as it's just a dead simple .addClass).
Code example of what I currently have is below, thanks in advanced.
jQuery
$(".pricing3 aside").not('.selected').mouseenter(function() {
$(".desc", this).stop().slideDown('slow');
})
.mouseleave(function() {
$(".desc", this).stop().slideUp('slow');
});
HTML
<div class="pricing3">
<aside>
<i class="fa fa-clock-o"></i>
<h3>1 Hour Pass</h3>
<p class="desc">Description</p>
<p class="pricing">£XX</p>
<button type="submit">BUY NOW</button>
</aside>
<aside class="selected">
<i class="fa fa-clock-o"></i>
<h3>8 Hour Pass</h3>
<p class="desc">Description</p>
<p class="pricing">£XX</p>
<button type="submit">BUY NOW</button>
</aside>
<aside>
<i class="fa fa-clock-o"></i>
<h3>24-7-365 Access</h3>
<p class="desc">Description</p>
<p class="pricing">£XX</p>
<button type="submit">BUY NOW</button>
</aside>
</div>
Need to use event delegation as the target element selection is based on a dynamic state
$(".pricing3").on('mouseenter', 'aside:not(.selected)', function () {
$(".desc", this).stop().slideDown('slow');
}).on('mouseleave', 'aside:not(.selected)', function () {
$(".desc", this).stop().slideUp('slow');
});
It can be written slightly differently as
$(".pricing3").on({
mouseenter: function () {
$(".desc", this).stop().slideDown('slow');
},
mouseleave: function () {
$(".desc", this).stop().slideUp('slow');
}
}, 'aside:not(.selected)')
As the class is shifting you'd be better off checking for the class inside the event handler
$(".pricing3 aside").on('mouseenter mouseleave', function() {
if ( !$(this).hasClass('selected') ) {
$(".desc", this).stop().slideToggle('slow');
}
});
If I understand you correctly, the problem is that you want the .selected to be removed, and then the mouseenter() to run on it as if it hadn't had the .selected on it in the first place?
If this is the case, you should attach your event handler higher up the DOM tree, and use on() to filter down to the <aside>s This way you can flip/flop the class all you want, and the event handler will work as expected. As it's coded, you are only applying the filter at page load, so the state change of the class has no effect.

Categories