I have a html page with over 1500 element !!!
and a menu .
when I click somewhere on document , the page locked for over 2 seconds (at least).
After some search I found this block of code in JQuery.UI :
// Clicks outside of a menu collapse any open menus
this._on( this.document, {
click: function( event ) {
if ( !$( event.target ).closest( ".ui-menu" ).length ) {
this.collapseAll( event );
}
// Reset the mouseHandled flag
this.mouseHandled = false;
}
});
the if statement fires over and over and it become problem .
How this could fix ?!
Related
I have a drop down menu that has different heights based on a selection of classes - one-row, two-row, three-row.
The main content of the site also animates down depending on these classes.
I have also implemented a function that makes the menu reset if the user clicks outside of it.
Everything is working as required other than the fact the I cannot use 'toggleClass' to make the menu close if the link is clicked again.
Can any of you JQuery gurus help me out here?
// ============================================================
//
// DROP DOWN MENU
//
// ============================================================
$('.submenu-toggle').on('click', function (e) {
// Reset all other drop downs and icons
$('.submenu').removeClass('drop-down');
$('.submenu-toggle').find('.fa-angle-down').removeClass('rotate');
// Drop down this menu
$(this).find('.submenu').addClass('drop-down');
// Rotate the icon
$(this).find('.fa-angle-down').addClass('rotate');
// Drop the main content wrapper down depending on the
// number of rows in the drop-down menu
if ($(this).find('.submenu').hasClass('one-row')) {
$('.content-wrapper').addClass('one-row-drop-down');
$('.content-wrapper').removeClass('two-row-drop-down three-row-drop-down four-row-drop-down');
}
if ($(this).find('.submenu').hasClass('two-row')) {
$('.content-wrapper').addClass('two-row-drop-down');
$('.content-wrapper').removeClass('one-row-drop-down three-row-drop-down four-row-drop-down');
}
if ($(this).find('.submenu').hasClass('three-row')) {
$('.content-wrapper').addClass('three-row-drop-down');
$('.content-wrapper').removeClass('one-row-drop-down two-row-drop-down four-row-drop-down');
}
e.stopPropagation();
});
// Reset dropdowns and reset icon on click outside
$(document).on('click', function () {
$('.submenu').removeClass('drop-down');
$('.submenu-toggle').find('.fa-angle-down').removeClass('rotate');
$('.content-wrapper').removeClass('one-row-drop-down two-row-drop-down three-row-drop-down');
});
You need to use jquery toggle
http://api.jquery.com/toggle/
See here some examples http://api.jquery.com/toggle/#entry-examples
$( "#foo" ).toggle( display );
is equivalent to:
if ( display === true ) {
$( "#foo" ).show();
} else if ( display === false ) {
$( "#foo" ).hide();
}
This is more of a tip than a question, but i hope others find this useful.
Basically i needed to make the lightbox slider called 'Swipebox' auto transition to the next slide, I looked online for help but found nothing.
to add this feature to the plugin i added this code:
setInterval(function(){
$this.getNext(); // Auto transitions each slide
}, 5000);
The file for this JS is called 'jquery.swipebox.js'. This is the code where you want to place the code previously mentioned:
/**
* Navigation events : go to next slide, go to prevous slide and close
*/
actions : function () {
var $this = this,
action = 'touchend click'; // Just detect for both event types to allow for multi-input
if ( elements.length < 2 ) {
$( '#swipebox-bottom-bar' ).hide();
if ( undefined === elements[ 1 ] ) {
$( '#swipebox-top-bar' ).hide();
}
} else {
$( '#swipebox-prev' ).bind( action, function( event ) {
event.preventDefault();
event.stopPropagation();
$this.getPrev();
$this.setTimeout();
} );
$( '#swipebox-next' ).bind( action, function( event ) {
event.preventDefault();
event.stopPropagation();
$this.getNext();
$this.setTimeout();
} );
}
$( '#swipebox-close' ).bind( action, function() {
$this.closeSlide();
} );
// THIS IS THE NEW CODE ADDED:
setInterval(function(){
$this.getNext(); // Auto transitions each slide
}, 5000);
},
This function is around about 550 lines down.
Also, to make the slideshow loop back around, you will need to change the option called 'loopAtEnd' from FALSE to TRUE. This is located at the top of the document.
loopAtEnd: true,
Hope this helped :)
Links that are subject to display: none aren't in the default tabbing order. However, when they're revealed - e.g. CSS for a drop-down menu reveals a sub-menu when a parent link gains focus - they still aren't in the tabbing order. Presumably JavaScript is required, but simply setting tabindex="0" does nothing.
The problem here is that as soon as you tab off the "Top level page with child" link, the CSS is updated and the parent of the anchor becomes display:none before the anchor can receive focus. You will need to use JavaScript to solve this problem and delay the change in the CSS using a timeout until you can determine whether the loss of focus has resulted in the focus shifting to the child element.
Setting tabindex="0" when the parent is display:none will not help, display:none means that the content might as well not be in the document.
I've come up with a solution that basically works: http://codepen.io/gyrus/pen/waKjKv/ There seem to be some issues in IE, I'm working on that. But the general idea is:
Add a small delay before hiding the drop-down
Set a data attribute to flag whether any links inside the drop-down have focus, and check this before hiding
This is just the jQuery, check the pen for more:
jQuery( document ).ready( function( $ ) {
$( '.nav' ).on( 'mouseenter focusin', '.menu-level-0.menu-item-has-children', function( e ) {
var el = $( this );
// Show sub-menu
el.attr( 'aria-expanded', 'true' )
.find( '.sub-menu-wrapper' ).show();
}).on( 'mouseleave focusout', '.menu-level-0.menu-item-has-children', function( e ) {
var el = $( this );
// Only hide sub-menu after a short delay, so links get a chance to catch focus from tabbing
setTimeout( function() {
var smw = el.find( '.sub-menu-wrapper' );
if ( smw.attr( 'data-has-focus' ) !== 'true' ) {
el.attr( 'aria-expanded', 'false' );
smw.hide();
}
}, 100 );
}).on( 'focusin', '.sub-menu-wrapper', function( e ) {
var el = $( this );
el.attr( 'data-has-focus', 'true' );
}).on( 'focusout', '.sub-menu-wrapper', function( e ) {
var el = $( this );
el.attr( 'data-has-focus', 'false' );
// Hide sub-menu on the way out
el.hide().parents( '.menu-level-0' ).attr( 'aria-expanded', 'false' );
});
});
I got a navigation menu that opens a submenu dropdown on hovering over the first level items. After a click on a first level link the mouse is on the same position on the new page .... so here's the thing:
On normal browsers (Firefox, Safari and Chrome) it triggers the hover effect only after the mouse moves.
On Internet Explorer it seems that the hover is triggered immediatly after load because the dropdown opens directly (which is pretty annoying). I even mapped the hover function in a mousemove but that doesn't change anything (does ie even trigger mousemove on load without even moving Oo).
Here the simplified code:
jQuery( '#mainmenucontainer' ).hoverIntent( {
over: function() {
jQuery( 'body' ).addClass( 'mainmenu_active' );
},
out: function() {
jQuery( 'body' ).removeClass( 'mainmenu_active' );
}
} );
jQuery( '#mainmenu > ul > li' ).hoverIntent( {
over: function() {
jQuery( '#mainmenu > ul > li' ).removeClass( 'active' );
jQuery( this ).addClass( 'active' );
}
} );
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
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();
})
});
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' );
} );