views:

994

answers:

2

Hey

I am having a bit of trouble combining the HOVER and FOCUS events with jquery. This is what I had originally:

$("input,textarea").focus(function () {

    $(this).parent().siblings('div.exp').removeClass('hide');
    $(this).parent().siblings('div.exp').addClass('show');

});


$("input,textarea").blur(function (){

    $(this).parent().siblings('div.exp').removeClass('show');
    $(this).parent().siblings('div.exp').addClass('hide');
    if ($(this).val().length <= 0) {
        $(this).siblings('span.warning').removeClass('hide');
        $(this).siblings('span.warning').addClass('show');}

    else {

        $(this).siblings('span.warning').removeClass('show');
        $(this).siblings('span.warning').addClass('hide');
    }


});

Basically, I have a user contact form with rows like the one below:

<div class="row">
  <p><label>Your Name</label><input type="text" name="name" id="name" value=""/><span class="warning">Your name is missing</span></p>
  <div class="exp">Who am I to address?</div> 
</div>

The point of my Jquery code is to bring forth a hidden div (exp) when the user focuses any one input or textarea element as well as checking if the value of said input is not empty when unfocusing (blur) the element. (I haven't really gotten down to validation yet so checkin for the string length right now is just a temporary filler). Should the element have a string smaller or equal than 0, then span.warning is to be 'shown' to the user.

This is all working nicely. Where I get stuck is the following:

I want to add in hover but without conflicting with focus. My desired final effect is this:

You hover any input or textarea and you get the div.exp to show up (exp is for explanation). You focus any input or area and the div.exp stays there, even if you go about hovering any other inputs or textareas. Should you hover an input that is already focused, nothing should happen.

So, in a nutshell, the focus and hover elements should work 'independently' so to speak. Not sure if I made myself clear but oh well, I tried =)

Cheers G

+3  A: 

You can set a flag to the input or textarea while it is focused to avoid conflict with your hover event. If the flag is set to true when the over or out event is fired, its code is not executed. The following code show the idea (I have not test it).

$("input,textarea").focus( function()
{
    $(this).parent().siblings( 'div.exp' ).removeClass( 'hide' ).addClass( 'show' );
    $(this).data( "hasFocus", true );
} );

$("input,textarea").blur(function()
{
    $(this).parent().siblings( 'div.exp' ).removeClass( 'show' ).addClass( 'hide' );

    if( $(this).val().length <= 0 )
        $(this).siblings( 'span.warning' ).removeClass( 'hide' ).addClass( 'show' );
    else
        $(this).siblings( 'span.warning' ).removeClass( 'show' ).addClass( 'hide' );

    $(this).data( "hasFocus", false );
});

$("input,textarea").hover( function()
{
    // Over event
    if( typeof $(this).data( "hasFocus" ) != undefined && !$(this).data( "hasFocus" ) )
        $(this).parent().siblings( 'div.exp' ).removeClass( 'hide' ).addClass( 'show' );
},
function()
{
    // Out event
    if( typeof $(this).data( "hasFocus" ) != undefined && !$(this).data( "hasFocus" ) )
        $(this).parent().siblings( 'div.exp' ).removeClass( 'show' ).addClass( 'hide' );
} );
Ploufka
+1  A: 

Your code can be significantly shortened by using .hide() and .show() and chaining the events. I posted a demo here.

$(document).ready(function(e){
 // hide all explanations and warnings
 $('.exp, .warning').hide();
 // add focus, blur and hover events to all inputs & textareas
 $('input,textarea')
  // if focused, show the explanation
  .focus(function(){
   // show explanation on focus (and add a class so the hover function knows not to hide it
   $(this).addClass('focused').closest('.row')
    .find('.exp').show()
    .find('.warning').hide();
  })
  .blur(function(){
   // hide explanation on blur
   $(this).removeClass('focused').closest('.row').find('.exp').hide();
   if ($(this).val().length < 1) {
    // input is empty, show the warning
    $(this).closest('.row').find('.warning').show();
   } else {
    // input is not empty, hide the warning... you might want to add the validation here
    $(this).closest('.row').find('.warning').hide();
   }
  })
  .hover(function(){
   // show explanation when hovered
   $(this).closest('.row').find('.exp').show();
  },function(){
   // hide explanation if the input is not focused
   if ($(this).is(':not(.focused)')) $(this).closest('.row').find('.exp').hide();
  })
});
fudgey
Wow, thanks a lot. I don't know why I didn't just use Jquery's own show and hide. Oh well, silly me. Thanks again for the help!
Sotkra